From bee2c127d3c40abe19be0de53a80a70e4d972c41 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sun, 17 Sep 2023 13:35:32 +0200 Subject: [PATCH] Update libwebp --- third-party/webp/BUILD | 36 +- third-party/webp/build-webp-bazel.sh | 93 +- third-party/webp/libwebp-1.1.0.tar.gz | Bin 4033877 -> 0 bytes third-party/webp/libwebp/.cmake-format.py | 240 + third-party/webp/libwebp/.pylintrc | 441 ++ third-party/webp/libwebp/.style.yapf | 2 + third-party/webp/libwebp/AUTHORS | 60 + third-party/webp/libwebp/Android.mk | 295 + third-party/webp/libwebp/CMakeLists.txt | 802 +++ third-party/webp/libwebp/CONTRIBUTING.md | 78 + third-party/webp/libwebp/COPYING | 30 + third-party/webp/libwebp/ChangeLog | 4626 ++++++++++++++ third-party/webp/libwebp/Makefile.am | 9 + third-party/webp/libwebp/Makefile.vc | 528 ++ third-party/webp/libwebp/NEWS | 315 + third-party/webp/libwebp/PATENTS | 23 + third-party/webp/libwebp/PRESUBMIT.py | 245 + third-party/webp/libwebp/README.md | 53 + third-party/webp/libwebp/autogen.sh | 2 + third-party/webp/libwebp/build.gradle | 444 ++ .../webp/libwebp/cmake/WebPConfig.cmake.in | 18 + third-party/webp/libwebp/cmake/config.h.in | 116 + third-party/webp/libwebp/cmake/cpu.cmake | 159 + third-party/webp/libwebp/cmake/deps.cmake | 172 + third-party/webp/libwebp/codereview.settings | 4 + third-party/webp/libwebp/configure.ac | 803 +++ third-party/webp/libwebp/doc/TODO | 13 + third-party/webp/libwebp/doc/api.md | 385 ++ third-party/webp/libwebp/doc/building.md | 213 + .../webp/libwebp/doc/specs_generation.md | 26 + third-party/webp/libwebp/doc/template.html | 94 + third-party/webp/libwebp/doc/tools.md | 516 ++ .../webp/libwebp/doc/webp-container-spec.txt | 870 +++ .../doc/webp-lossless-bitstream-spec.txt | 1156 ++++ third-party/webp/libwebp/examples/Android.mk | 96 + third-party/webp/libwebp/examples/Makefile.am | 119 + third-party/webp/libwebp/examples/anim_diff.c | 317 + third-party/webp/libwebp/examples/anim_dump.c | 121 + third-party/webp/libwebp/examples/anim_util.c | 782 +++ third-party/webp/libwebp/examples/anim_util.h | 73 + third-party/webp/libwebp/examples/cwebp.c | 1249 ++++ third-party/webp/libwebp/examples/dwebp.c | 421 ++ .../webp/libwebp/examples/example_util.c | 139 + .../webp/libwebp/examples/example_util.h | 70 + third-party/webp/libwebp/examples/gif2webp.c | 609 ++ third-party/webp/libwebp/examples/gifdec.c | 416 ++ third-party/webp/libwebp/examples/gifdec.h | 116 + third-party/webp/libwebp/examples/img2webp.c | 339 + third-party/webp/libwebp/examples/stopwatch.h | 63 + third-party/webp/libwebp/examples/test.webp | Bin 0 -> 4880 bytes .../webp/libwebp/examples/test_ref.ppm | 4 + third-party/webp/libwebp/examples/unicode.h | 116 + .../webp/libwebp/examples/unicode_gif.h | 76 + third-party/webp/libwebp/examples/vwebp.c | 654 ++ third-party/webp/libwebp/examples/webpinfo.c | 1186 ++++ third-party/webp/libwebp/examples/webpmux.c | 1234 ++++ third-party/webp/libwebp/extras/Makefile.am | 44 + third-party/webp/libwebp/extras/extras.c | 162 + third-party/webp/libwebp/extras/extras.h | 77 + third-party/webp/libwebp/extras/get_disto.c | 356 ++ .../webp/libwebp/extras/quality_estimate.c | 129 + third-party/webp/libwebp/extras/vwebp_sdl.c | 101 + .../webp/libwebp/extras/webp_quality.c | 54 + third-party/webp/libwebp/extras/webp_to_sdl.c | 110 + third-party/webp/libwebp/extras/webp_to_sdl.h | 22 + third-party/webp/libwebp/gradle.properties | 14 + .../libwebp/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 58695 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 + third-party/webp/libwebp/gradlew | 183 + third-party/webp/libwebp/gradlew.bat | 100 + third-party/webp/libwebp/imageio/Android.mk | 57 + third-party/webp/libwebp/imageio/Makefile.am | 32 + third-party/webp/libwebp/imageio/image_dec.c | 84 + third-party/webp/libwebp/imageio/image_dec.h | 70 + third-party/webp/libwebp/imageio/image_enc.c | 638 ++ third-party/webp/libwebp/imageio/image_enc.h | 96 + .../webp/libwebp/imageio/imageio_util.c | 162 + .../webp/libwebp/imageio/imageio_util.h | 64 + third-party/webp/libwebp/imageio/jpegdec.c | 364 ++ third-party/webp/libwebp/imageio/jpegdec.h | 37 + third-party/webp/libwebp/imageio/metadata.c | 49 + third-party/webp/libwebp/imageio/metadata.h | 47 + third-party/webp/libwebp/imageio/pngdec.c | 374 ++ third-party/webp/libwebp/imageio/pngdec.h | 37 + third-party/webp/libwebp/imageio/pnmdec.c | 301 + third-party/webp/libwebp/imageio/pnmdec.h | 37 + third-party/webp/libwebp/imageio/tiffdec.c | 293 + third-party/webp/libwebp/imageio/tiffdec.h | 37 + third-party/webp/libwebp/imageio/webpdec.c | 244 + third-party/webp/libwebp/imageio/webpdec.h | 67 + third-party/webp/libwebp/imageio/wicdec.c | 413 ++ third-party/webp/libwebp/imageio/wicdec.h | 34 + third-party/webp/libwebp/infra/common.sh | 106 + third-party/webp/libwebp/infra/compile.sh | 401 ++ .../webp/libwebp/infra/compile_android.sh | 224 + third-party/webp/libwebp/infra/compile_js.sh | 75 + .../webp/libwebp/infra/run_static_analysis.sh | 98 + third-party/webp/libwebp/iosbuild.sh | 168 + third-party/webp/libwebp/m4/ax_pthread.m4 | 332 + third-party/webp/libwebp/makefile.unix | 538 ++ third-party/webp/libwebp/man/Makefile.am | 17 + third-party/webp/libwebp/man/cwebp.1 | 328 + third-party/webp/libwebp/man/dwebp.1 | 150 + third-party/webp/libwebp/man/gif2webp.1 | 164 + third-party/webp/libwebp/man/img2webp.1 | 117 + third-party/webp/libwebp/man/vwebp.1 | 101 + third-party/webp/libwebp/man/webpinfo.1 | 80 + third-party/webp/libwebp/man/webpmux.1 | 271 + third-party/webp/libwebp/sharpyuv/Makefile.am | 41 + .../webp/libwebp/sharpyuv/libsharpyuv.pc.in | 11 + .../webp/libwebp/sharpyuv/libsharpyuv.rc | 41 + third-party/webp/libwebp/sharpyuv/sharpyuv.c | 565 ++ third-party/webp/libwebp/sharpyuv/sharpyuv.h | 174 + .../webp/libwebp/sharpyuv/sharpyuv_cpu.c | 14 + .../webp/libwebp/sharpyuv/sharpyuv_cpu.h | 22 + .../webp/libwebp/sharpyuv/sharpyuv_csp.c | 110 + .../webp/libwebp/sharpyuv/sharpyuv_csp.h | 60 + .../webp/libwebp/sharpyuv/sharpyuv_dsp.c | 104 + .../webp/libwebp/sharpyuv/sharpyuv_dsp.h | 28 + .../webp/libwebp/sharpyuv/sharpyuv_gamma.c | 419 ++ .../webp/libwebp/sharpyuv/sharpyuv_gamma.h | 38 + .../webp/libwebp/sharpyuv/sharpyuv_neon.c | 181 + .../webp/libwebp/sharpyuv/sharpyuv_sse2.c | 201 + third-party/webp/libwebp/src/Makefile.am | 55 + third-party/webp/libwebp/src/dec/Makefile.am | 29 + third-party/webp/libwebp/src/dec/alpha_dec.c | 233 + third-party/webp/libwebp/src/dec/alphai_dec.h | 54 + third-party/webp/libwebp/src/dec/buffer_dec.c | 310 + third-party/webp/libwebp/src/dec/common_dec.h | 54 + third-party/webp/libwebp/src/dec/frame_dec.c | 803 +++ third-party/webp/libwebp/src/dec/idec_dec.c | 908 +++ third-party/webp/libwebp/src/dec/io_dec.c | 662 ++ third-party/webp/libwebp/src/dec/quant_dec.c | 115 + third-party/webp/libwebp/src/dec/tree_dec.c | 538 ++ third-party/webp/libwebp/src/dec/vp8_dec.c | 724 +++ third-party/webp/libwebp/src/dec/vp8_dec.h | 185 + third-party/webp/libwebp/src/dec/vp8i_dec.h | 319 + third-party/webp/libwebp/src/dec/vp8l_dec.c | 1778 ++++++ third-party/webp/libwebp/src/dec/vp8li_dec.h | 148 + third-party/webp/libwebp/src/dec/webp_dec.c | 859 +++ third-party/webp/libwebp/src/dec/webpi_dec.h | 137 + .../webp/libwebp/src/demux/Makefile.am | 18 + .../webp/libwebp/src/demux/anim_decode.c | 473 ++ third-party/webp/libwebp/src/demux/demux.c | 975 +++ .../webp/libwebp/src/demux/libwebpdemux.pc.in | 11 + .../webp/libwebp/src/demux/libwebpdemux.rc | 41 + third-party/webp/libwebp/src/dsp/Makefile.am | 187 + .../webp/libwebp/src/dsp/alpha_processing.c | 496 ++ .../src/dsp/alpha_processing_mips_dsp_r2.c | 228 + .../libwebp/src/dsp/alpha_processing_neon.c | 194 + .../libwebp/src/dsp/alpha_processing_sse2.c | 408 ++ .../libwebp/src/dsp/alpha_processing_sse41.c | 92 + .../webp/libwebp/src/dsp/common_sse2.h | 194 + .../webp/libwebp/src/dsp/common_sse41.h | 132 + third-party/webp/libwebp/src/dsp/cost.c | 412 ++ .../webp/libwebp/src/dsp/cost_mips32.c | 154 + .../webp/libwebp/src/dsp/cost_mips_dsp_r2.c | 107 + third-party/webp/libwebp/src/dsp/cost_neon.c | 122 + third-party/webp/libwebp/src/dsp/cost_sse2.c | 119 + third-party/webp/libwebp/src/dsp/cpu.c | 259 + third-party/webp/libwebp/src/dsp/cpu.h | 266 + third-party/webp/libwebp/src/dsp/dec.c | 888 +++ .../webp/libwebp/src/dsp/dec_clip_tables.c | 369 ++ third-party/webp/libwebp/src/dsp/dec_mips32.c | 587 ++ .../webp/libwebp/src/dsp/dec_mips_dsp_r2.c | 994 +++ third-party/webp/libwebp/src/dsp/dec_msa.c | 1020 +++ third-party/webp/libwebp/src/dsp/dec_neon.c | 1663 +++++ third-party/webp/libwebp/src/dsp/dec_sse2.c | 1228 ++++ third-party/webp/libwebp/src/dsp/dec_sse41.c | 46 + third-party/webp/libwebp/src/dsp/dsp.h | 504 ++ third-party/webp/libwebp/src/dsp/enc.c | 831 +++ third-party/webp/libwebp/src/dsp/enc_mips32.c | 677 ++ .../webp/libwebp/src/dsp/enc_mips_dsp_r2.c | 1517 +++++ third-party/webp/libwebp/src/dsp/enc_msa.c | 896 +++ third-party/webp/libwebp/src/dsp/enc_neon.c | 943 +++ third-party/webp/libwebp/src/dsp/enc_sse2.c | 1514 +++++ third-party/webp/libwebp/src/dsp/enc_sse41.c | 339 + third-party/webp/libwebp/src/dsp/filters.c | 295 + .../libwebp/src/dsp/filters_mips_dsp_r2.c | 402 ++ .../webp/libwebp/src/dsp/filters_msa.c | 202 + .../webp/libwebp/src/dsp/filters_neon.c | 329 + .../webp/libwebp/src/dsp/filters_sse2.c | 340 + third-party/webp/libwebp/src/dsp/lossless.c | 681 ++ third-party/webp/libwebp/src/dsp/lossless.h | 259 + .../webp/libwebp/src/dsp/lossless_common.h | 191 + .../webp/libwebp/src/dsp/lossless_enc.c | 954 +++ .../libwebp/src/dsp/lossless_enc_mips32.c | 397 ++ .../src/dsp/lossless_enc_mips_dsp_r2.c | 281 + .../webp/libwebp/src/dsp/lossless_enc_msa.c | 148 + .../webp/libwebp/src/dsp/lossless_enc_neon.c | 144 + .../webp/libwebp/src/dsp/lossless_enc_sse2.c | 669 ++ .../webp/libwebp/src/dsp/lossless_enc_sse41.c | 205 + .../libwebp/src/dsp/lossless_mips_dsp_r2.c | 701 ++ .../webp/libwebp/src/dsp/lossless_msa.c | 356 ++ .../webp/libwebp/src/dsp/lossless_neon.c | 645 ++ .../webp/libwebp/src/dsp/lossless_sse2.c | 712 +++ .../webp/libwebp/src/dsp/lossless_sse41.c | 133 + third-party/webp/libwebp/src/dsp/mips_macro.h | 200 + third-party/webp/libwebp/src/dsp/msa_macro.h | 1395 ++++ third-party/webp/libwebp/src/dsp/neon.h | 104 + third-party/webp/libwebp/src/dsp/quant.h | 91 + third-party/webp/libwebp/src/dsp/rescaler.c | 252 + .../webp/libwebp/src/dsp/rescaler_mips32.c | 295 + .../libwebp/src/dsp/rescaler_mips_dsp_r2.c | 314 + .../webp/libwebp/src/dsp/rescaler_msa.c | 443 ++ .../webp/libwebp/src/dsp/rescaler_neon.c | 192 + .../webp/libwebp/src/dsp/rescaler_sse2.c | 366 ++ third-party/webp/libwebp/src/dsp/ssim.c | 160 + third-party/webp/libwebp/src/dsp/ssim_sse2.c | 165 + third-party/webp/libwebp/src/dsp/upsampling.c | 328 + .../libwebp/src/dsp/upsampling_mips_dsp_r2.c | 291 + .../webp/libwebp/src/dsp/upsampling_msa.c | 688 ++ .../webp/libwebp/src/dsp/upsampling_neon.c | 285 + .../webp/libwebp/src/dsp/upsampling_sse2.c | 267 + .../webp/libwebp/src/dsp/upsampling_sse41.c | 239 + third-party/webp/libwebp/src/dsp/yuv.c | 245 + third-party/webp/libwebp/src/dsp/yuv.h | 210 + third-party/webp/libwebp/src/dsp/yuv_mips32.c | 103 + .../webp/libwebp/src/dsp/yuv_mips_dsp_r2.c | 134 + third-party/webp/libwebp/src/dsp/yuv_neon.c | 180 + third-party/webp/libwebp/src/dsp/yuv_sse2.c | 758 +++ third-party/webp/libwebp/src/dsp/yuv_sse41.c | 615 ++ third-party/webp/libwebp/src/enc/Makefile.am | 43 + third-party/webp/libwebp/src/enc/alpha_enc.c | 453 ++ .../webp/libwebp/src/enc/analysis_enc.c | 483 ++ .../src/enc/backward_references_cost_enc.c | 795 +++ .../libwebp/src/enc/backward_references_enc.c | 1065 ++++ .../libwebp/src/enc/backward_references_enc.h | 244 + third-party/webp/libwebp/src/enc/config_enc.c | 157 + third-party/webp/libwebp/src/enc/cost_enc.c | 342 + third-party/webp/libwebp/src/enc/cost_enc.h | 82 + third-party/webp/libwebp/src/enc/filter_enc.c | 235 + third-party/webp/libwebp/src/enc/frame_enc.c | 905 +++ .../webp/libwebp/src/enc/histogram_enc.c | 1250 ++++ .../webp/libwebp/src/enc/histogram_enc.h | 130 + .../webp/libwebp/src/enc/iterator_enc.c | 459 ++ .../webp/libwebp/src/enc/near_lossless_enc.c | 151 + .../webp/libwebp/src/enc/picture_csp_enc.c | 846 +++ .../webp/libwebp/src/enc/picture_enc.c | 304 + .../webp/libwebp/src/enc/picture_psnr_enc.c | 258 + .../libwebp/src/enc/picture_rescale_enc.c | 304 + .../webp/libwebp/src/enc/picture_tools_enc.c | 274 + .../webp/libwebp/src/enc/predictor_enc.c | 792 +++ third-party/webp/libwebp/src/enc/quant_enc.c | 1398 ++++ third-party/webp/libwebp/src/enc/syntax_enc.c | 392 ++ third-party/webp/libwebp/src/enc/token_enc.c | 262 + third-party/webp/libwebp/src/enc/tree_enc.c | 504 ++ third-party/webp/libwebp/src/enc/vp8i_enc.h | 523 ++ third-party/webp/libwebp/src/enc/vp8l_enc.c | 1898 ++++++ third-party/webp/libwebp/src/enc/vp8li_enc.h | 126 + third-party/webp/libwebp/src/enc/webp_enc.c | 410 ++ third-party/webp/libwebp/src/libwebp.pc.in | 12 + third-party/webp/libwebp/src/libwebp.rc | 41 + .../webp/libwebp/src/libwebpdecoder.pc.in | 11 + .../webp/libwebp/src/libwebpdecoder.rc | 41 + third-party/webp/libwebp/src/mux/Makefile.am | 22 + .../webp/libwebp/src/mux/anim_encode.c | 1586 +++++ third-party/webp/libwebp/src/mux/animi.h | 43 + .../webp/libwebp/src/mux/libwebpmux.pc.in | 12 + .../webp/libwebp/src/mux/libwebpmux.rc | 41 + third-party/webp/libwebp/src/mux/muxedit.c | 657 ++ third-party/webp/libwebp/src/mux/muxi.h | 234 + .../webp/libwebp/src/mux/muxinternal.c | 549 ++ third-party/webp/libwebp/src/mux/muxread.c | 557 ++ .../webp/libwebp/src/utils/Makefile.am | 54 + .../libwebp/src/utils/bit_reader_inl_utils.h | 196 + .../webp/libwebp/src/utils/bit_reader_utils.c | 299 + .../webp/libwebp/src/utils/bit_reader_utils.h | 195 + .../webp/libwebp/src/utils/bit_writer_utils.c | 347 + .../webp/libwebp/src/utils/bit_writer_utils.h | 154 + .../libwebp/src/utils/color_cache_utils.c | 49 + .../libwebp/src/utils/color_cache_utils.h | 89 + .../webp/libwebp/src/utils/endian_inl_utils.h | 93 + .../webp/libwebp/src/utils/filters_utils.c | 76 + .../webp/libwebp/src/utils/filters_utils.h | 32 + .../libwebp/src/utils/huffman_encode_utils.c | 416 ++ .../libwebp/src/utils/huffman_encode_utils.h | 60 + .../webp/libwebp/src/utils/huffman_utils.c | 296 + .../webp/libwebp/src/utils/huffman_utils.h | 111 + third-party/webp/libwebp/src/utils/palette.c | 402 ++ third-party/webp/libwebp/src/utils/palette.h | 60 + .../src/utils/quant_levels_dec_utils.c | 291 + .../src/utils/quant_levels_dec_utils.h | 35 + .../libwebp/src/utils/quant_levels_utils.c | 140 + .../libwebp/src/utils/quant_levels_utils.h | 36 + .../webp/libwebp/src/utils/random_utils.c | 43 + .../webp/libwebp/src/utils/random_utils.h | 63 + .../webp/libwebp/src/utils/rescaler_utils.c | 160 + .../webp/libwebp/src/utils/rescaler_utils.h | 102 + .../webp/libwebp/src/utils/thread_utils.c | 369 ++ .../webp/libwebp/src/utils/thread_utils.h | 90 + third-party/webp/libwebp/src/utils/utils.c | 282 + third-party/webp/libwebp/src/utils/utils.h | 209 + third-party/webp/libwebp/src/webp/decode.h | 505 ++ third-party/webp/libwebp/src/webp/demux.h | 363 ++ third-party/webp/libwebp/src/webp/encode.h | 552 ++ .../webp/libwebp/src/webp/format_constants.h | 87 + third-party/webp/libwebp/src/webp/mux.h | 530 ++ third-party/webp/libwebp/src/webp/mux_types.h | 98 + third-party/webp/libwebp/src/webp/types.h | 72 + third-party/webp/libwebp/swig/README.md | 67 + third-party/webp/libwebp/swig/libwebp.go | 45 + third-party/webp/libwebp/swig/libwebp.jar | Bin 0 -> 2150 bytes third-party/webp/libwebp/swig/libwebp.py | 235 + third-party/webp/libwebp/swig/libwebp.swig | 438 ++ third-party/webp/libwebp/swig/libwebp_gc.c | 52 + .../webp/libwebp/swig/libwebp_go_wrap.c | 274 + .../webp/libwebp/swig/libwebp_java_wrap.c | 1765 ++++++ .../webp/libwebp/swig/libwebp_python_wrap.c | 5628 +++++++++++++++++ third-party/webp/libwebp/swig/setup.py | 40 + third-party/webp/libwebp/tests/README.md | 18 + .../tests/fuzzer/advanced_api_fuzzer.c | 139 + .../tests/fuzzer/animation_api_fuzzer.c | 78 + .../tests/fuzzer/animdecoder_fuzzer.cc | 52 + .../tests/fuzzer/animencoder_fuzzer.cc | 188 + .../libwebp/tests/fuzzer/enc_dec_fuzzer.cc | 161 + .../webp/libwebp/tests/fuzzer/fuzz.dict | 17 + .../webp/libwebp/tests/fuzzer/fuzz_utils.h | 223 + .../libwebp/tests/fuzzer/huffman_fuzzer.c | 65 + .../webp/libwebp/tests/fuzzer/img_alpha.h | 381 ++ .../webp/libwebp/tests/fuzzer/img_grid.h | 125 + .../webp/libwebp/tests/fuzzer/img_peak.h | 5533 ++++++++++++++++ .../webp/libwebp/tests/fuzzer/makefile.unix | 31 + .../tests/fuzzer/mux_demux_api_fuzzer.c | 96 + .../libwebp/tests/fuzzer/simple_api_fuzzer.c | 88 + third-party/webp/libwebp/xcframeworkbuild.sh | 255 + 326 files changed, 116107 insertions(+), 53 deletions(-) delete mode 100644 third-party/webp/libwebp-1.1.0.tar.gz create mode 100644 third-party/webp/libwebp/.cmake-format.py create mode 100644 third-party/webp/libwebp/.pylintrc create mode 100644 third-party/webp/libwebp/.style.yapf create mode 100644 third-party/webp/libwebp/AUTHORS create mode 100644 third-party/webp/libwebp/Android.mk create mode 100644 third-party/webp/libwebp/CMakeLists.txt create mode 100644 third-party/webp/libwebp/CONTRIBUTING.md create mode 100644 third-party/webp/libwebp/COPYING create mode 100644 third-party/webp/libwebp/ChangeLog create mode 100644 third-party/webp/libwebp/Makefile.am create mode 100644 third-party/webp/libwebp/Makefile.vc create mode 100644 third-party/webp/libwebp/NEWS create mode 100644 third-party/webp/libwebp/PATENTS create mode 100644 third-party/webp/libwebp/PRESUBMIT.py create mode 100644 third-party/webp/libwebp/README.md create mode 100755 third-party/webp/libwebp/autogen.sh create mode 100644 third-party/webp/libwebp/build.gradle create mode 100644 third-party/webp/libwebp/cmake/WebPConfig.cmake.in create mode 100644 third-party/webp/libwebp/cmake/config.h.in create mode 100644 third-party/webp/libwebp/cmake/cpu.cmake create mode 100644 third-party/webp/libwebp/cmake/deps.cmake create mode 100644 third-party/webp/libwebp/codereview.settings create mode 100644 third-party/webp/libwebp/configure.ac create mode 100644 third-party/webp/libwebp/doc/TODO create mode 100644 third-party/webp/libwebp/doc/api.md create mode 100644 third-party/webp/libwebp/doc/building.md create mode 100644 third-party/webp/libwebp/doc/specs_generation.md create mode 100644 third-party/webp/libwebp/doc/template.html create mode 100644 third-party/webp/libwebp/doc/tools.md create mode 100644 third-party/webp/libwebp/doc/webp-container-spec.txt create mode 100644 third-party/webp/libwebp/doc/webp-lossless-bitstream-spec.txt create mode 100644 third-party/webp/libwebp/examples/Android.mk create mode 100644 third-party/webp/libwebp/examples/Makefile.am create mode 100644 third-party/webp/libwebp/examples/anim_diff.c create mode 100644 third-party/webp/libwebp/examples/anim_dump.c create mode 100644 third-party/webp/libwebp/examples/anim_util.c create mode 100644 third-party/webp/libwebp/examples/anim_util.h create mode 100644 third-party/webp/libwebp/examples/cwebp.c create mode 100644 third-party/webp/libwebp/examples/dwebp.c create mode 100644 third-party/webp/libwebp/examples/example_util.c create mode 100644 third-party/webp/libwebp/examples/example_util.h create mode 100644 third-party/webp/libwebp/examples/gif2webp.c create mode 100644 third-party/webp/libwebp/examples/gifdec.c create mode 100644 third-party/webp/libwebp/examples/gifdec.h create mode 100644 third-party/webp/libwebp/examples/img2webp.c create mode 100644 third-party/webp/libwebp/examples/stopwatch.h create mode 100644 third-party/webp/libwebp/examples/test.webp create mode 100644 third-party/webp/libwebp/examples/test_ref.ppm create mode 100644 third-party/webp/libwebp/examples/unicode.h create mode 100644 third-party/webp/libwebp/examples/unicode_gif.h create mode 100644 third-party/webp/libwebp/examples/vwebp.c create mode 100644 third-party/webp/libwebp/examples/webpinfo.c create mode 100644 third-party/webp/libwebp/examples/webpmux.c create mode 100644 third-party/webp/libwebp/extras/Makefile.am create mode 100644 third-party/webp/libwebp/extras/extras.c create mode 100644 third-party/webp/libwebp/extras/extras.h create mode 100644 third-party/webp/libwebp/extras/get_disto.c create mode 100644 third-party/webp/libwebp/extras/quality_estimate.c create mode 100644 third-party/webp/libwebp/extras/vwebp_sdl.c create mode 100644 third-party/webp/libwebp/extras/webp_quality.c create mode 100644 third-party/webp/libwebp/extras/webp_to_sdl.c create mode 100644 third-party/webp/libwebp/extras/webp_to_sdl.h create mode 100644 third-party/webp/libwebp/gradle.properties create mode 100644 third-party/webp/libwebp/gradle/wrapper/gradle-wrapper.jar create mode 100644 third-party/webp/libwebp/gradle/wrapper/gradle-wrapper.properties create mode 100755 third-party/webp/libwebp/gradlew create mode 100644 third-party/webp/libwebp/gradlew.bat create mode 100644 third-party/webp/libwebp/imageio/Android.mk create mode 100644 third-party/webp/libwebp/imageio/Makefile.am create mode 100644 third-party/webp/libwebp/imageio/image_dec.c create mode 100644 third-party/webp/libwebp/imageio/image_dec.h create mode 100644 third-party/webp/libwebp/imageio/image_enc.c create mode 100644 third-party/webp/libwebp/imageio/image_enc.h create mode 100644 third-party/webp/libwebp/imageio/imageio_util.c create mode 100644 third-party/webp/libwebp/imageio/imageio_util.h create mode 100644 third-party/webp/libwebp/imageio/jpegdec.c create mode 100644 third-party/webp/libwebp/imageio/jpegdec.h create mode 100644 third-party/webp/libwebp/imageio/metadata.c create mode 100644 third-party/webp/libwebp/imageio/metadata.h create mode 100644 third-party/webp/libwebp/imageio/pngdec.c create mode 100644 third-party/webp/libwebp/imageio/pngdec.h create mode 100644 third-party/webp/libwebp/imageio/pnmdec.c create mode 100644 third-party/webp/libwebp/imageio/pnmdec.h create mode 100644 third-party/webp/libwebp/imageio/tiffdec.c create mode 100644 third-party/webp/libwebp/imageio/tiffdec.h create mode 100644 third-party/webp/libwebp/imageio/webpdec.c create mode 100644 third-party/webp/libwebp/imageio/webpdec.h create mode 100644 third-party/webp/libwebp/imageio/wicdec.c create mode 100644 third-party/webp/libwebp/imageio/wicdec.h create mode 100644 third-party/webp/libwebp/infra/common.sh create mode 100755 third-party/webp/libwebp/infra/compile.sh create mode 100755 third-party/webp/libwebp/infra/compile_android.sh create mode 100755 third-party/webp/libwebp/infra/compile_js.sh create mode 100755 third-party/webp/libwebp/infra/run_static_analysis.sh create mode 100755 third-party/webp/libwebp/iosbuild.sh create mode 100644 third-party/webp/libwebp/m4/ax_pthread.m4 create mode 100644 third-party/webp/libwebp/makefile.unix create mode 100644 third-party/webp/libwebp/man/Makefile.am create mode 100644 third-party/webp/libwebp/man/cwebp.1 create mode 100644 third-party/webp/libwebp/man/dwebp.1 create mode 100644 third-party/webp/libwebp/man/gif2webp.1 create mode 100644 third-party/webp/libwebp/man/img2webp.1 create mode 100644 third-party/webp/libwebp/man/vwebp.1 create mode 100644 third-party/webp/libwebp/man/webpinfo.1 create mode 100644 third-party/webp/libwebp/man/webpmux.1 create mode 100644 third-party/webp/libwebp/sharpyuv/Makefile.am create mode 100644 third-party/webp/libwebp/sharpyuv/libsharpyuv.pc.in create mode 100644 third-party/webp/libwebp/sharpyuv/libsharpyuv.rc create mode 100644 third-party/webp/libwebp/sharpyuv/sharpyuv.c create mode 100644 third-party/webp/libwebp/sharpyuv/sharpyuv.h create mode 100644 third-party/webp/libwebp/sharpyuv/sharpyuv_cpu.c create mode 100644 third-party/webp/libwebp/sharpyuv/sharpyuv_cpu.h create mode 100644 third-party/webp/libwebp/sharpyuv/sharpyuv_csp.c create mode 100644 third-party/webp/libwebp/sharpyuv/sharpyuv_csp.h create mode 100644 third-party/webp/libwebp/sharpyuv/sharpyuv_dsp.c create mode 100644 third-party/webp/libwebp/sharpyuv/sharpyuv_dsp.h create mode 100644 third-party/webp/libwebp/sharpyuv/sharpyuv_gamma.c create mode 100644 third-party/webp/libwebp/sharpyuv/sharpyuv_gamma.h create mode 100644 third-party/webp/libwebp/sharpyuv/sharpyuv_neon.c create mode 100644 third-party/webp/libwebp/sharpyuv/sharpyuv_sse2.c create mode 100644 third-party/webp/libwebp/src/Makefile.am create mode 100644 third-party/webp/libwebp/src/dec/Makefile.am create mode 100644 third-party/webp/libwebp/src/dec/alpha_dec.c create mode 100644 third-party/webp/libwebp/src/dec/alphai_dec.h create mode 100644 third-party/webp/libwebp/src/dec/buffer_dec.c create mode 100644 third-party/webp/libwebp/src/dec/common_dec.h create mode 100644 third-party/webp/libwebp/src/dec/frame_dec.c create mode 100644 third-party/webp/libwebp/src/dec/idec_dec.c create mode 100644 third-party/webp/libwebp/src/dec/io_dec.c create mode 100644 third-party/webp/libwebp/src/dec/quant_dec.c create mode 100644 third-party/webp/libwebp/src/dec/tree_dec.c create mode 100644 third-party/webp/libwebp/src/dec/vp8_dec.c create mode 100644 third-party/webp/libwebp/src/dec/vp8_dec.h create mode 100644 third-party/webp/libwebp/src/dec/vp8i_dec.h create mode 100644 third-party/webp/libwebp/src/dec/vp8l_dec.c create mode 100644 third-party/webp/libwebp/src/dec/vp8li_dec.h create mode 100644 third-party/webp/libwebp/src/dec/webp_dec.c create mode 100644 third-party/webp/libwebp/src/dec/webpi_dec.h create mode 100644 third-party/webp/libwebp/src/demux/Makefile.am create mode 100644 third-party/webp/libwebp/src/demux/anim_decode.c create mode 100644 third-party/webp/libwebp/src/demux/demux.c create mode 100644 third-party/webp/libwebp/src/demux/libwebpdemux.pc.in create mode 100644 third-party/webp/libwebp/src/demux/libwebpdemux.rc create mode 100644 third-party/webp/libwebp/src/dsp/Makefile.am create mode 100644 third-party/webp/libwebp/src/dsp/alpha_processing.c create mode 100644 third-party/webp/libwebp/src/dsp/alpha_processing_mips_dsp_r2.c create mode 100644 third-party/webp/libwebp/src/dsp/alpha_processing_neon.c create mode 100644 third-party/webp/libwebp/src/dsp/alpha_processing_sse2.c create mode 100644 third-party/webp/libwebp/src/dsp/alpha_processing_sse41.c create mode 100644 third-party/webp/libwebp/src/dsp/common_sse2.h create mode 100644 third-party/webp/libwebp/src/dsp/common_sse41.h create mode 100644 third-party/webp/libwebp/src/dsp/cost.c create mode 100644 third-party/webp/libwebp/src/dsp/cost_mips32.c create mode 100644 third-party/webp/libwebp/src/dsp/cost_mips_dsp_r2.c create mode 100644 third-party/webp/libwebp/src/dsp/cost_neon.c create mode 100644 third-party/webp/libwebp/src/dsp/cost_sse2.c create mode 100644 third-party/webp/libwebp/src/dsp/cpu.c create mode 100644 third-party/webp/libwebp/src/dsp/cpu.h create mode 100644 third-party/webp/libwebp/src/dsp/dec.c create mode 100644 third-party/webp/libwebp/src/dsp/dec_clip_tables.c create mode 100644 third-party/webp/libwebp/src/dsp/dec_mips32.c create mode 100644 third-party/webp/libwebp/src/dsp/dec_mips_dsp_r2.c create mode 100644 third-party/webp/libwebp/src/dsp/dec_msa.c create mode 100644 third-party/webp/libwebp/src/dsp/dec_neon.c create mode 100644 third-party/webp/libwebp/src/dsp/dec_sse2.c create mode 100644 third-party/webp/libwebp/src/dsp/dec_sse41.c create mode 100644 third-party/webp/libwebp/src/dsp/dsp.h create mode 100644 third-party/webp/libwebp/src/dsp/enc.c create mode 100644 third-party/webp/libwebp/src/dsp/enc_mips32.c create mode 100644 third-party/webp/libwebp/src/dsp/enc_mips_dsp_r2.c create mode 100644 third-party/webp/libwebp/src/dsp/enc_msa.c create mode 100644 third-party/webp/libwebp/src/dsp/enc_neon.c create mode 100644 third-party/webp/libwebp/src/dsp/enc_sse2.c create mode 100644 third-party/webp/libwebp/src/dsp/enc_sse41.c create mode 100644 third-party/webp/libwebp/src/dsp/filters.c create mode 100644 third-party/webp/libwebp/src/dsp/filters_mips_dsp_r2.c create mode 100644 third-party/webp/libwebp/src/dsp/filters_msa.c create mode 100644 third-party/webp/libwebp/src/dsp/filters_neon.c create mode 100644 third-party/webp/libwebp/src/dsp/filters_sse2.c create mode 100644 third-party/webp/libwebp/src/dsp/lossless.c create mode 100644 third-party/webp/libwebp/src/dsp/lossless.h create mode 100644 third-party/webp/libwebp/src/dsp/lossless_common.h create mode 100644 third-party/webp/libwebp/src/dsp/lossless_enc.c create mode 100644 third-party/webp/libwebp/src/dsp/lossless_enc_mips32.c create mode 100644 third-party/webp/libwebp/src/dsp/lossless_enc_mips_dsp_r2.c create mode 100644 third-party/webp/libwebp/src/dsp/lossless_enc_msa.c create mode 100644 third-party/webp/libwebp/src/dsp/lossless_enc_neon.c create mode 100644 third-party/webp/libwebp/src/dsp/lossless_enc_sse2.c create mode 100644 third-party/webp/libwebp/src/dsp/lossless_enc_sse41.c create mode 100644 third-party/webp/libwebp/src/dsp/lossless_mips_dsp_r2.c create mode 100644 third-party/webp/libwebp/src/dsp/lossless_msa.c create mode 100644 third-party/webp/libwebp/src/dsp/lossless_neon.c create mode 100644 third-party/webp/libwebp/src/dsp/lossless_sse2.c create mode 100644 third-party/webp/libwebp/src/dsp/lossless_sse41.c create mode 100644 third-party/webp/libwebp/src/dsp/mips_macro.h create mode 100644 third-party/webp/libwebp/src/dsp/msa_macro.h create mode 100644 third-party/webp/libwebp/src/dsp/neon.h create mode 100644 third-party/webp/libwebp/src/dsp/quant.h create mode 100644 third-party/webp/libwebp/src/dsp/rescaler.c create mode 100644 third-party/webp/libwebp/src/dsp/rescaler_mips32.c create mode 100644 third-party/webp/libwebp/src/dsp/rescaler_mips_dsp_r2.c create mode 100644 third-party/webp/libwebp/src/dsp/rescaler_msa.c create mode 100644 third-party/webp/libwebp/src/dsp/rescaler_neon.c create mode 100644 third-party/webp/libwebp/src/dsp/rescaler_sse2.c create mode 100644 third-party/webp/libwebp/src/dsp/ssim.c create mode 100644 third-party/webp/libwebp/src/dsp/ssim_sse2.c create mode 100644 third-party/webp/libwebp/src/dsp/upsampling.c create mode 100644 third-party/webp/libwebp/src/dsp/upsampling_mips_dsp_r2.c create mode 100644 third-party/webp/libwebp/src/dsp/upsampling_msa.c create mode 100644 third-party/webp/libwebp/src/dsp/upsampling_neon.c create mode 100644 third-party/webp/libwebp/src/dsp/upsampling_sse2.c create mode 100644 third-party/webp/libwebp/src/dsp/upsampling_sse41.c create mode 100644 third-party/webp/libwebp/src/dsp/yuv.c create mode 100644 third-party/webp/libwebp/src/dsp/yuv.h create mode 100644 third-party/webp/libwebp/src/dsp/yuv_mips32.c create mode 100644 third-party/webp/libwebp/src/dsp/yuv_mips_dsp_r2.c create mode 100644 third-party/webp/libwebp/src/dsp/yuv_neon.c create mode 100644 third-party/webp/libwebp/src/dsp/yuv_sse2.c create mode 100644 third-party/webp/libwebp/src/dsp/yuv_sse41.c create mode 100644 third-party/webp/libwebp/src/enc/Makefile.am create mode 100644 third-party/webp/libwebp/src/enc/alpha_enc.c create mode 100644 third-party/webp/libwebp/src/enc/analysis_enc.c create mode 100644 third-party/webp/libwebp/src/enc/backward_references_cost_enc.c create mode 100644 third-party/webp/libwebp/src/enc/backward_references_enc.c create mode 100644 third-party/webp/libwebp/src/enc/backward_references_enc.h create mode 100644 third-party/webp/libwebp/src/enc/config_enc.c create mode 100644 third-party/webp/libwebp/src/enc/cost_enc.c create mode 100644 third-party/webp/libwebp/src/enc/cost_enc.h create mode 100644 third-party/webp/libwebp/src/enc/filter_enc.c create mode 100644 third-party/webp/libwebp/src/enc/frame_enc.c create mode 100644 third-party/webp/libwebp/src/enc/histogram_enc.c create mode 100644 third-party/webp/libwebp/src/enc/histogram_enc.h create mode 100644 third-party/webp/libwebp/src/enc/iterator_enc.c create mode 100644 third-party/webp/libwebp/src/enc/near_lossless_enc.c create mode 100644 third-party/webp/libwebp/src/enc/picture_csp_enc.c create mode 100644 third-party/webp/libwebp/src/enc/picture_enc.c create mode 100644 third-party/webp/libwebp/src/enc/picture_psnr_enc.c create mode 100644 third-party/webp/libwebp/src/enc/picture_rescale_enc.c create mode 100644 third-party/webp/libwebp/src/enc/picture_tools_enc.c create mode 100644 third-party/webp/libwebp/src/enc/predictor_enc.c create mode 100644 third-party/webp/libwebp/src/enc/quant_enc.c create mode 100644 third-party/webp/libwebp/src/enc/syntax_enc.c create mode 100644 third-party/webp/libwebp/src/enc/token_enc.c create mode 100644 third-party/webp/libwebp/src/enc/tree_enc.c create mode 100644 third-party/webp/libwebp/src/enc/vp8i_enc.h create mode 100644 third-party/webp/libwebp/src/enc/vp8l_enc.c create mode 100644 third-party/webp/libwebp/src/enc/vp8li_enc.h create mode 100644 third-party/webp/libwebp/src/enc/webp_enc.c create mode 100644 third-party/webp/libwebp/src/libwebp.pc.in create mode 100644 third-party/webp/libwebp/src/libwebp.rc create mode 100644 third-party/webp/libwebp/src/libwebpdecoder.pc.in create mode 100644 third-party/webp/libwebp/src/libwebpdecoder.rc create mode 100644 third-party/webp/libwebp/src/mux/Makefile.am create mode 100644 third-party/webp/libwebp/src/mux/anim_encode.c create mode 100644 third-party/webp/libwebp/src/mux/animi.h create mode 100644 third-party/webp/libwebp/src/mux/libwebpmux.pc.in create mode 100644 third-party/webp/libwebp/src/mux/libwebpmux.rc create mode 100644 third-party/webp/libwebp/src/mux/muxedit.c create mode 100644 third-party/webp/libwebp/src/mux/muxi.h create mode 100644 third-party/webp/libwebp/src/mux/muxinternal.c create mode 100644 third-party/webp/libwebp/src/mux/muxread.c create mode 100644 third-party/webp/libwebp/src/utils/Makefile.am create mode 100644 third-party/webp/libwebp/src/utils/bit_reader_inl_utils.h create mode 100644 third-party/webp/libwebp/src/utils/bit_reader_utils.c create mode 100644 third-party/webp/libwebp/src/utils/bit_reader_utils.h create mode 100644 third-party/webp/libwebp/src/utils/bit_writer_utils.c create mode 100644 third-party/webp/libwebp/src/utils/bit_writer_utils.h create mode 100644 third-party/webp/libwebp/src/utils/color_cache_utils.c create mode 100644 third-party/webp/libwebp/src/utils/color_cache_utils.h create mode 100644 third-party/webp/libwebp/src/utils/endian_inl_utils.h create mode 100644 third-party/webp/libwebp/src/utils/filters_utils.c create mode 100644 third-party/webp/libwebp/src/utils/filters_utils.h create mode 100644 third-party/webp/libwebp/src/utils/huffman_encode_utils.c create mode 100644 third-party/webp/libwebp/src/utils/huffman_encode_utils.h create mode 100644 third-party/webp/libwebp/src/utils/huffman_utils.c create mode 100644 third-party/webp/libwebp/src/utils/huffman_utils.h create mode 100644 third-party/webp/libwebp/src/utils/palette.c create mode 100644 third-party/webp/libwebp/src/utils/palette.h create mode 100644 third-party/webp/libwebp/src/utils/quant_levels_dec_utils.c create mode 100644 third-party/webp/libwebp/src/utils/quant_levels_dec_utils.h create mode 100644 third-party/webp/libwebp/src/utils/quant_levels_utils.c create mode 100644 third-party/webp/libwebp/src/utils/quant_levels_utils.h create mode 100644 third-party/webp/libwebp/src/utils/random_utils.c create mode 100644 third-party/webp/libwebp/src/utils/random_utils.h create mode 100644 third-party/webp/libwebp/src/utils/rescaler_utils.c create mode 100644 third-party/webp/libwebp/src/utils/rescaler_utils.h create mode 100644 third-party/webp/libwebp/src/utils/thread_utils.c create mode 100644 third-party/webp/libwebp/src/utils/thread_utils.h create mode 100644 third-party/webp/libwebp/src/utils/utils.c create mode 100644 third-party/webp/libwebp/src/utils/utils.h create mode 100644 third-party/webp/libwebp/src/webp/decode.h create mode 100644 third-party/webp/libwebp/src/webp/demux.h create mode 100644 third-party/webp/libwebp/src/webp/encode.h create mode 100644 third-party/webp/libwebp/src/webp/format_constants.h create mode 100644 third-party/webp/libwebp/src/webp/mux.h create mode 100644 third-party/webp/libwebp/src/webp/mux_types.h create mode 100644 third-party/webp/libwebp/src/webp/types.h create mode 100644 third-party/webp/libwebp/swig/README.md create mode 100644 third-party/webp/libwebp/swig/libwebp.go create mode 100644 third-party/webp/libwebp/swig/libwebp.jar create mode 100644 third-party/webp/libwebp/swig/libwebp.py create mode 100644 third-party/webp/libwebp/swig/libwebp.swig create mode 100644 third-party/webp/libwebp/swig/libwebp_gc.c create mode 100644 third-party/webp/libwebp/swig/libwebp_go_wrap.c create mode 100644 third-party/webp/libwebp/swig/libwebp_java_wrap.c create mode 100644 third-party/webp/libwebp/swig/libwebp_python_wrap.c create mode 100644 third-party/webp/libwebp/swig/setup.py create mode 100644 third-party/webp/libwebp/tests/README.md create mode 100644 third-party/webp/libwebp/tests/fuzzer/advanced_api_fuzzer.c create mode 100644 third-party/webp/libwebp/tests/fuzzer/animation_api_fuzzer.c create mode 100644 third-party/webp/libwebp/tests/fuzzer/animdecoder_fuzzer.cc create mode 100644 third-party/webp/libwebp/tests/fuzzer/animencoder_fuzzer.cc create mode 100644 third-party/webp/libwebp/tests/fuzzer/enc_dec_fuzzer.cc create mode 100644 third-party/webp/libwebp/tests/fuzzer/fuzz.dict create mode 100644 third-party/webp/libwebp/tests/fuzzer/fuzz_utils.h create mode 100644 third-party/webp/libwebp/tests/fuzzer/huffman_fuzzer.c create mode 100644 third-party/webp/libwebp/tests/fuzzer/img_alpha.h create mode 100644 third-party/webp/libwebp/tests/fuzzer/img_grid.h create mode 100644 third-party/webp/libwebp/tests/fuzzer/img_peak.h create mode 100644 third-party/webp/libwebp/tests/fuzzer/makefile.unix create mode 100644 third-party/webp/libwebp/tests/fuzzer/mux_demux_api_fuzzer.c create mode 100644 third-party/webp/libwebp/tests/fuzzer/simple_api_fuzzer.c create mode 100755 third-party/webp/libwebp/xcframeworkbuild.sh diff --git a/third-party/webp/BUILD b/third-party/webp/BUILD index 7d991c7246..b6ef3be99f 100644 --- a/third-party/webp/BUILD +++ b/third-party/webp/BUILD @@ -3,27 +3,33 @@ headers = [ "decode.h", "encode.h", "types.h", - #"demux.h", - #"mux_types.h", ] libs = [ "webp", + "sharpyuv", ] +# libwebp at c1ffd9ac7593894c40a1de99d03f0b7af8af2577 +filegroup( + name = "libwebp_sources", + srcs = glob([ + "libwebp/**/*" + ]), +) + genrule( name = "webp_build", srcs = [ "build-webp-bazel.sh", - "libwebp-1.1.0.tar.gz", + ":libwebp_sources", + "@cmake_tar_gz//file", ], cmd_bash = """ set -ex - if [ "$(TARGET_CPU)" == "ios_armv7" ]; then - BUILD_ARCH="armv7" - elif [ "$(TARGET_CPU)" == "ios_arm64" ]; then + if [ "$(TARGET_CPU)" == "ios_arm64" ]; then BUILD_ARCH="arm64" elif [ "$(TARGET_CPU)" == "ios_sim_arm64" ]; then BUILD_ARCH="sim_arm64" @@ -37,19 +43,27 @@ genrule( rm -rf "$$BUILD_DIR" mkdir -p "$$BUILD_DIR" + CMAKE_DIR="$$(pwd)/$$BUILD_DIR/cmake" + rm -rf "$$CMAKE_DIR" + mkdir -p "$$CMAKE_DIR" + tar -xzf "$(location @cmake_tar_gz//file)" -C "$$CMAKE_DIR" + cp $(location :build-webp-bazel.sh) "$$BUILD_DIR/" - cp $(location :libwebp-1.1.0.tar.gz) "$$BUILD_DIR/" - mkdir -p "$$BUILD_DIR/Public/webp" + SOURCE_PATH="third-party/webp/libwebp" - sh $$BUILD_DIR/build-webp-bazel.sh $$BUILD_ARCH "$$BUILD_DIR" libwebp-1.1.0.tar.gz + cp -R "$$SOURCE_PATH" "$$BUILD_DIR/" + + mkdir -p "$$BUILD_DIR/Public/libwebp" + + PATH="$$PATH:$$CMAKE_DIR/cmake-3.23.1-macos-universal/CMake.app/Contents/bin" sh $$BUILD_DIR/build-webp-bazel.sh $$BUILD_ARCH "$$BUILD_DIR/libwebp" "$$BUILD_DIR" """ + "\n".join([ - "cp -f \"$$BUILD_DIR/src/libwebp-1.1.0/build-output/include/webp/{}\" \"$(location Public/webp/{})\"".format(header, header) for header in headers + "cp -f \"$$BUILD_DIR/libwebp/src/webp/{}\" \"$(location Public/webp/{})\"".format(header, header) for header in headers ]) + "\n" + "\n".join([ - "cp -f \"$$BUILD_DIR/src/libwebp-1.1.0/build-output/lib/lib{}.a\" \"$(location Public/webp/lib/lib{}.a)\"".format(lib, lib) for lib in libs + "cp -f \"$$BUILD_DIR/build/lib{}.a\" \"$(location Public/webp/lib/lib{}.a)\"".format(lib, lib) for lib in libs ]), outs = ["Public/webp/" + x for x in headers] + ["Public/webp/lib/lib{}.a".format(x) for x in libs], diff --git a/third-party/webp/build-webp-bazel.sh b/third-party/webp/build-webp-bazel.sh index c199cba8f1..530c791945 100755 --- a/third-party/webp/build-webp-bazel.sh +++ b/third-party/webp/build-webp-bazel.sh @@ -2,55 +2,64 @@ set -ex +set -e + ARCH="$1" -BUILD_DIR=$(echo "$(cd "$(dirname "$2")"; pwd -P)/$(basename "$2")") -SOURCE_CODE_ARCHIVE="$3" -MINIOSVERSION="9.0" +SOURCE_DIR="$2" +BUILD_DIR=$(echo "$(cd "$(dirname "$3")"; pwd -P)/$(basename "$3")") -OPT_CFLAGS="-Os -g" -OPT_LDFLAGS="" -OPT_CONFIG_ARGS="" +COMMON_ARGS="-DWEBP_LINK_STATIC=1 -DWEBP_BUILD_CWEBP=0 -DWEBP_BUILD_DWEBP=0 -DWEBP_BUILD_IMG2WEBP=0 -DWEBP_BUILD_ANIM_UTILS=0 -DWEBP_BUILD_GIF2WEBP=0 -DWEBP_BUILD_VWEBP=0 -DWEBP_BUILD_WEBPINFO=0 -DWEBP_BUILD_LIBWEBPMUX=0 -DWEBP_BUILD_WEBPMUX=0 -DWEBP_BUILD_EXTRAS=0" -DEVELOPER=`xcode-select -print-path` +if [ "$ARCH" = "arm64" ]; then + IOS_PLATFORMDIR="$(xcode-select -p)/Platforms/iPhoneOS.platform" + IOS_SYSROOT=($IOS_PLATFORMDIR/Developer/SDKs/iPhoneOS*.sdk) + export CFLAGS="-Wall -arch arm64 -miphoneos-version-min=11.0 -funwind-tables" -OUTPUTDIR="$BUILD_DIR/Public" + cd "$BUILD_DIR" + mkdir build + cd build -SRCDIR="${BUILD_DIR}/src" -mkdir -p $SRCDIR + touch toolchain.cmake + echo "set(CMAKE_SYSTEM_NAME Darwin)" >> toolchain.cmake + echo "set(CMAKE_SYSTEM_PROCESSOR aarch64)" >> toolchain.cmake + echo "set(CMAKE_C_COMPILER $(xcode-select -p)/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang)" >> toolchain.cmake -tar zxf "$BUILD_DIR/$SOURCE_CODE_ARCHIVE" -C $SRCDIR -cd "${SRCDIR}/libwebp-"* -PREFIX="$(pwd)/build-output" + cmake -G"Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake -DCMAKE_OSX_SYSROOT=${IOS_SYSROOT[0]} $COMMON_ARGS ../libwebp + make +elif [ "$ARCH" = "sim_arm64" ]; then + IOS_PLATFORMDIR="$(xcode-select -p)/Platforms/iPhoneSimulator.platform" + IOS_SYSROOT=($IOS_PLATFORMDIR/Developer/SDKs/iPhoneSimulator*.sdk) + export CFLAGS="-Wall -arch arm64 --target=arm64-apple-ios11.0-simulator -miphonesimulator-version-min=11.0 -funwind-tables" -if [ "${ARCH}" == "i386" ] || [ "${ARCH}" == "x86_64" ]; then - PLATFORM="iphonesimulator" - EXTRA_CFLAGS="-arch ${ARCH}" - EXTRA_CONFIG="--host=x86_64-apple-darwin" -elif [ "${ARCH}" == "sim_arm64" ]; then - PLATFORM="iphonesimulator" - EXTRA_CFLAGS="-arch arm64 --target=arm64-apple-ios$MINIOSVERSION-simulator" - EXTRA_CONFIG="--host=arm-apple-darwin20" + cd "$BUILD_DIR" + mkdir build + cd build + + touch toolchain.cmake + echo "set(CMAKE_SYSTEM_NAME Darwin)" >> toolchain.cmake + echo "set(CMAKE_SYSTEM_PROCESSOR aarch64)" >> toolchain.cmake + echo "set(CMAKE_C_COMPILER $(xcode-select -p)/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang)" >> toolchain.cmake + + cmake -G"Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake -DCMAKE_OSX_SYSROOT=${IOS_SYSROOT[0]} $COMMON_ARGS ../libwebp + make +elif [ "$ARCH" = "x86_64" ]; then + IOS_PLATFORMDIR="$(xcode-select -p)/Platforms/iPhoneSimulator.platform" + IOS_SYSROOT=($IOS_PLATFORMDIR/Developer/SDKs/iPhoneSimulator*.sdk) + export CFLAGS="-Wall -arch x86_64 -miphoneos-version-min=11.0 -funwind-tables" + + cd "$BUILD_DIR" + mkdir build + cd build + + touch toolchain.cmake + echo "set(CMAKE_SYSTEM_NAME Darwin)" >> toolchain.cmake + echo "set(CMAKE_SYSTEM_PROCESSOR AMD64)" >> toolchain.cmake + echo "set(CMAKE_C_COMPILER $(xcode-select -p)/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang)" >> toolchain.cmake + + cmake -G"Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake -DCMAKE_OSX_SYSROOT=${IOS_SYSROOT[0]} $COMMON_ARGS ../libwebp + make else - PLATFORM="iphoneos" - EXTRA_CFLAGS="-arch ${ARCH}" - EXTRA_CONFIG="--host=arm-apple-darwin" + echo "Unsupported architecture $ARCH" + exit 1 fi - -SDKROOT="$(xcrun --sdk $PLATFORM --show-sdk-path 2>/dev/null)" - -DEVROOT="${DEVELOPER}/Toolchains/XcodeDefault.xctoolchain" - -CFLAGS="-pipe -isysroot ${SDKROOT} -O3 -DNDEBUG $EXTRA_CFLAGS" -CFLAGS+=" -miphoneos-version-min=9.0" - -PATH="${DEVROOT}/usr/bin:${PATH}" ./configure \ - ${EXTRA_CONFIG} \ - --prefix=${PREFIX} \ - --build=$(./config.guess) \ - --disable-shared --enable-static \ - --disable-libwebpdecoder --enable-swap-16bit-csp \ - CFLAGS="${CFLAGS}" - -make V=0 -make install diff --git a/third-party/webp/libwebp-1.1.0.tar.gz b/third-party/webp/libwebp-1.1.0.tar.gz deleted file mode 100644 index 63885d3d5305f12ecfc70dd4099cd7582e8c57d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4033877 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 z%0D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

-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

ps<4VTM zVssLtSwjZ0%-ro-SW=s24gnSt8D`Q+I~LTcjFUE2jiMrbuh%}khHnC6EEFwYkE?TA zVp+GG85uj5Z%_a4!@p7xnn|XEL2z65b>Yh&C1q*l(E07zQs0DThyL^vjs29Ser zq9hc6DF8?~2tQUJLy$>0SFp_6%fV{h$iZi~^q3qGK{9oMOy!DE+x{Q7X}vqGepA#TGQ zreqhc)`NL(9)9KXf4#;(;Jl^Y+xs;bjd!CmTVC8G3wS?IZ{DqrUhb`Jvy$MRXNwVw z7uh9989-;q-FLUVPjX!Qp6`0d&o4IH>IZ%e^xwYot{o`Wi6R5_D;j$gO@^~=uu?#B5Zea&3U znv(z;6rLa;fFuf<2(QSsg;JJyWS%x>19g0@4?s4wQYBKC9yRtHhV&v`q z=YQSicR#*<@XuW%W{mc-?=S27k1_A{|K88<_P?$%`Um`J zzViR<=XwABbicpZ#r^f(pS@lDecboAzFXYm;Xk8Uj7f@-B32Lrvz^QL* z&-bZ)>}1=jLM6qdQap;2Iwhsnw6{44skaq->P^wK(S`P$Eqmf)3_IQjncQ1%8h4>K zt)NY>rbIAQAX(tNugyuPxvQ-UqOe};D-q##qBR3nj_=eScINv`GQ5_mOyt8lOiQoI zdx@?TG}tPN!@+J0WsDNK%<5Z#hn3cqpCP7P2PW~x>vd@FT9&cd-oG5Uo`p94b=Br~ z+voqjnfrPstE5E7o##`fyS%;l`w{;+CT5pRx8#gfBKH1w+s>pPh%bKBe(ZsP&FWFs zaLuNtRM^>?+9pv|K%gDl!#DS>{wn*wp7VQz8Tv!3l7GbdxPO&imrExCVnqXGzS^Lj z-+TXg_qn%6Ru0wU{vUl{tt7T-|7e+G95t$gGpXHEeP@?a&z`l6+!k2Xq;ir>=8l$j zPbK~}E&R~GYVET&)|w?3`pk_<&7?MskUii=JI-H~E_Cq!4l6 zRu4|AP3&$vqcmdx*C*3uhxO6iZdAHcRppZ{+6z;w4EB0T)mj@ejshGMgVD#GvHWOk zCa+lQj29-J2Fbn$M@Owg6$-FwIaBNQv9ieyV_9vFsN>4ES)BnvUZ)4Wj~(~jPcDa1 zQ?4%ES!rDv<{5vx{Id-^!A8MqzW~c9Q37-#C*#e|Yu8?Bb8invp5yMyg&$vwna}QH z07fvr%V!st)uM#vP6m^ml7YNnu-tbvxTpZahVCwZN1_F$i$*7Z(H?@xy9 zbUVe)`^c#nXj5R)J`Xf|Pjn!Qi+aJ?!T&({L`JBO7$LCOX(>#H?P2 zPp04J_dn-gImC^wdu{A0>&_va>`fDtEY(5WvfX+OS+!4tuG9LELwn;_O=p-i zr<{$cHL%lbS9C?ehKx;(0@*r1gBqe~tG1qM1ndFLhS-@CEF>UU-`EG&ZqT__&*2f$ zEi6+#_hYP~WkqAUAlrpEC+hU?wxf@INixeVFCr>!SgGqQCWat~<3`xTvn{{?_j0;whzd$B?mC(&z>Qq)#qwM)hgOh9T>Yh-6TXp)B@ zDzmYtz+LXHGuxT_w6Nj&zDwLdOu%~5&7I`SD22ipabYLy-R>2C|MdIJsm*1d?dIl{ ztY3I>^Aaav0^-E%-I30jac<|!iX5>V8%P$?59fx3;bRY_wh zXntyK?K-w5HlveJreZp&j#O8p^d$I9s#S|ij!9zC5i}%)80jTT?Y5D+Y1W}1aNw9= zU|?IX&{WXD;b^!?58W(F42yT0mm%OvpXq{^Wd+Gv7usqAkwByup~0g-VQvdKCZNCw zx=fhF$PlS8u(e{1N&-M778R()Mgc}dRY-x-0tBp?8mU@X0nvg&R7y%nq9_B90Uipr zy^eYejTxO15N#Aa-P|m$*O~smx zK}MX+*xNFl;Q44P3gO)0^X9mlt(I{3sX15tn#@%PUQZjGuBihKMfzZ(QVSDVsmjlM6O&fagN+|%| zq-DD&A#;`}*JcV&c6M!J+?T#vj*$s8LSzV}v!M*8V>&mzB#ma@%q3Lb=h-j+;xa*! zUB}VYrGY0$+3%4yx)C4NGdrCxb-g&N^=v%Zr!7L{l=d{s8aoLC8}n#8t7DS<1H zuBD|WMTZ>8=EyHutl_@ik~?qYW%Rc0uBU#cn`rWW>b<9)U-fi@-ZUOgDVYFKWKNS{ z`UFW4GW-Ob945+Kv^pmVS6ksJxdOZSeH@GM=Kv&1GDzTLoik~>2`sjfTPB^%OoKE7 zRzT(q90oI5&flaXxk&mDCQ$-NB9nBkR!w~}36MB7Z43bgGI`d>iE;=dw3r|vJv)Gf zA*pisTv=rjG6&PiI5k4Jko&M^03nrhqGZt{$QFns00zl)CKrE21WCtf5Fm+|OcI2G zx!Su5-AqL?eY!QNG?NKL5+>b(1e1qIkidsROqzJ_ns5Q4f6oVVrSU{zLDd4o-rH)3FGYgp)|)NcfZpxG^EgSj{aHOs+FzvhI`xV5Ezc z02#o{1fCVq+<0^u+wTo;Ag;!+L3bJYOvX#r7zn`d9+%ArBT;iWAd|q6bUFzEQ0-{K zU06|DPzVuu(RIi5tNrIYeGS=P^0qzaNAkLsrGCFY^JLHZv23Uy_3lP9fd(f8pO2MsN z59XtX_dD^sb-Bsj5{wK3OruRBlwdl5OpNQ5Uw-E(-VUI@tDmwqQ z)b^`KZV+qs(5Kkc?l$nK!U$Fu!^An`^N4r6+?+G+&gVfeko`sS2yE1(ID$ZQ&5yCd zF_5SvTPqRN8nyAAg8|`@4#A+6)wWC=Wp%-OkM2F?w*_B&U;9+o`R}*g=Nw)f_?+7= zIR&q8fTw0^eZ_g})%o99d*;lY+V}0VQ{8F)BW}M$2YoLbcjQRcOvjRe^jSF*KAU}h zt#8lt_gJDv4an#;1*c=?#Zc{0RaQ@C=k{_=2AsxJ#dX|buRaTR7WX;ZB>SfKu>Shp z`?2re->z)^USl^_M z`=-=kVAPh6<4EhUK2kAIO?pjOvwLXBV%4mqhr+R<)460VJx0=}W7F^2NN3EbPCeGR_Kcdn z)W&(@(yDECMgAdQLG9$lY^T6ARd!|BOkN@FnxVeKY51K2)EFeRhA{{FaTQqecpID;~k_3poo&Mj^N(vx?35x@zS1 zeD+v&0>y@i#e;{CftiVr$`JAZusJ%LvWR++ITRr_-^<1=^Au zPIH}~SYFD$o!WlkJat65h8DM1-~a6@jc0zN^K%hLai*X1z~$xV8iw*AXzK9Q@0_(Ic>JuyL_VEr3TGH@7y7|j@UAll2A97uD#T`_Uaw}ZfvF7_Ojj|dSY|+ ztHhB4>o}fHPgd=D9NNq8am6al@%D3DYd<-oe=0bx_I2rpW_DLs^$MSTbgX!^*4>%= zTYuR)F`=-QToiseCWDcEypu7 zi7tlfv)ofHCtpo? zZct0hMVmBP^!0c(hYh{cS2mr(#SIYY(`9L7;sh`=O<)^0z2m$y%`1MJ`x)Z#zVj`A z$-}*xf69x`f7~uB(6h717@*rk&HVbFg#$#&DY+VRFYB!yYwc4uG!O_ADXfIX5EG-J zx29b=VdyyBW%jQ#LBDbL7_T)0)lwL^GT*B9)JriF2~Wky5U|GPWOx^%t(2pu&5@6~ z!EI7*Xe;AxVK_o)Flh*lb&i^K$#X%c@7}iWyI<|U@_Vf@#AKWKfX_338QI_}-R zdEL+2e9XqlEB>4Qh15Gg-%mL%;ei$w0>oLEU8o8)Nib4TJ?)!XscRX?vgH^X8>l(DA!_r-8pXzd+FcbU$)27ZgCR zu!U3Cm|Vt?l$qVgU((_O1W^{^hT?f8~)EkK`P&=ErTkrCP`J#AhGhj@h|u z+mGzT*Va*E;ITcPG2**anK=|~!xZm0j-{bRnZ==%$ib-6PnG~ z%&{F-nqiW!CP8u+0|vDlXzc*hB&=`TSb$QGrLo&81LIY5n{RT`9LhiYPciapO=WXA(hv2%L=N3<%?E2K>e+(_$u07)21Ay#7#j67o$xhSKR4xG|DuZh;8i3w%BW@CYCg z7$B&z*b4%PiuJ0|>e- zH;F{S9ywjI(Iq1LXQ6jq}Gkd-?iPA!BAf3iFG~ZHu=sPK z{zzWE+p+k%;eN_hU9=XUk2Jg8_t2-q=_K-97Pp+van-*cts!~cd)M^nWK55#Fd(2J zqA9xJNE;NTfe5GXL!PVFKOA+JSt{Hq2F8E@tRSPSO15Q=N9b;@``7GfJnKXE+~p|K z#n>y!3A}z-U)Q@Y$*$g=Im)p;b822`uS+%0yfgf)8F-w0GC0Q}#|B3mH>!14FYx)c z*C<@qkL*X@qc-}me9?w{GaU4Qobd3pc- z>HFW`-T(8c&x^jgp`X{tU%c<$-_PFdbX?5VzO}FOb$@gn&6~m0r}*XGEw5|#dFTLN zK%l=epZ8~4He7cTVQfFidvsI;30HxsIzeY#P0VfUk?I6{JML(A*VQK(!p5*50YC*s zr{m~^)Hu4Y+50F4W-$T7hIMVZiG7BBsC^kF6_ahE8_vG$Uddwct9N*Uhin zz5D&>SK{}1c%L2j@H)jcBN?i!H7gGgQTrZ}Q@7n|nPWrO!Kwy!zIa79+p&QN0O=BA za7HgxS1R+U@h4lECNA1~@9N*K`OhDgc)k6;TPMAL^>(NI>EP=aWKfUXy~ULzD?ZiU z>}@7pc{=`L<#RLECHCZgOw7`q9o<}WdJpsO7o_t&qJJk?qp}?|Q@%+{!|JwE!^B+>VlsF7Ib?mL3ef9g*f84o;v8$5qHG#K@ z_V7`l>9Tl~o-V8%s$`AaQLo6hykaQ&R`gLsu`~4ubLOw7m6c=`>WI!A1*h~8y}Fu; z9?Bo}RkUU^+j>81Gdt78X^X?g*HPzNrH_p@x4Yui%ZN>e`5I!F zV0G6ipOJ<*B%1H-PVHIqHfk|iJigb}>|>QGcHHz)u}xI1546^b?=(j0!RB<{dvC`E z?mXcrG3}*X%OqtGCQ*6nc3aP3A6e;OwS>cImEAsLz-ApHSGP|c9q&kw?3*E8ojKBc5*3P(vgj}cF&gw{%5(I`KN9_s7Z z^j815v6Y;i?^Egs88oZhbSkR6|J|D%-~9ZLKWp~6q)~fqWgZ#+$^7k|J)St9Z5cA# z!_=mdp^HiLldnIXsgs!}1MsHvDBi9oU*Bt!wscRPIP-GPd5;Xh>3Lip-?)#eYdDXl zGv&B@-sgIz9%6U=m$`zR@%og1UGDQ5u1!+1x88sac$7|=(qYMK*PtXd+e1U^WS@O1 zvvt3wT>A>y+jZzcdaeBg?abkB47{Wz%B~ac>}1NgUBD`)uxE;rXoNLPcPu4a z8Wu+a8^Rh5W6b30>!DUlWx%*NgRacVOml<9Zh9RvJFo_t4w~Hb{_=D5Ngdx=cCUD8 zll%e4*F!Hev$pZ5SCXsNZ=ojcBsrovH?lEy+md=9wvF4vFLGsl_G!A9UhmWACzo-j zQJL&_mz^=*y|9a<}`OEy?&aBSA zzk9#)#I))4F@v4I-_yuH-@I-X&fj1DrPG=2(Vq5dNaz{5AN$Pu&VK)U^$9YLZ^QGK zL8p9J+zYOqr#&zGL}?5r&_t$fr6mlg!9=8#*3@d8aZI?lJ+PRxP#wdLh*IeU3Rdi3 zJdiTUZYd>xD=ZMCVFVyTrBfgb0D%B){HZ`8P?BgAC@kXeA@Jfh-`dULwXS|O$c)?HRr|vS%;OZ;@ zFhWp`(7>#tki{vO(}Y|92BI{G@O4Xo%wqFEm?MZn5c*7}s6ck@yVpwA2d(KyFM*D} z^nI#Fz5H_z|N8LX`CI>M+xYVC`1||I|NZMv{%@b^pZ;&}|FQb|_Sdifx_w;#yY(Ob zh}YNlas0cVKcD{neB1K)>~oA`%xC7oHh+GKkM*nXcnAgm; zq`|cU!`RH#OR0iy6M1Zt^v=QH7l?(AQ%AL&7#|FR!K4(E@ zTPR5lQrYIlF-%kCC`VIUK+=Y8BVuATjZ~J?&=?4%jg&eUats72QUMBTVKoaQlNPon zHR-@W3VJ-@!tO&sfRT5J|@4_HRIjJ&^7A!>A%P0F@np_aOcz9+Rkfk z@F`?YMuuLP&0_ZM1rX48Ta^NE*yarf=*NN6z|WrU!D5kR2ch z*4=Sy_yUlVr=$Sr1S>6k<_R&t7=0td$L_IB#%h~`S(E|iB|rIs6FKqy$PXg`?`|fN zOaN)&3*_RByGud{@dX%!K_GFs{A2>2FpWB+1gE2t6Hv&vrH15S0$?x$!cPn^QUp(w z-Xz ziCO_fqCVFth>+9C$Vub|pf8nlTea|?gyKj^QV*FVZ_ z$8+89&hti|Z-qDW$L~GAzU{x?eE-$#ei=`GKD+&Nh=&?>_M1@|IYVSMx{6glFWO1d zW!`7~xaq4bWbA{cB^l(9RgJURvU?diU=YpOy67nMMow!Y9`S>=NJ)sF8GXO@G@stQ@$=4}4}JdIoB!^=NB{1>qyO%I@c$zYd8g%W=FbE6C1evJH!gCazkWzg z6dY(1k}X9<@2g(1Xct7<<6h;~_{Lf9yA$WpreNV}9l7?zTfrTbcE8e|c z>qB|%=iBM){{I@y$#%M*b#$i@OTQoX{|C8PohZQ3HhAn7f927@ zLEZ~SxJQq5MemQepAa%Zm5@^HJG94PcC(L^ZedP!D%Mn0#1%2AF~`Lk0`~u(CSfCp zTZKWmKywvTa8#@A$?>cXV5gl9m1+QGyM?t)vG~uYsywDqUnLEwgkn%Y;J}wC8$zgz zbOdw@6#yDJiwEDFf7xsQUse8g`7fh!JF_=-HpDX~ZoLQCH|hTXqyIyC|ND>)sL=E$ zYNtN}NU)1^F{qwLaYbIQ{qdO^9I15NBUp=1`QPOb0T31Kr0@KA?fjSa<;l-}J}hhQ zi*^Q*{lYT?U4nlhM#cPt@`^~c%fhd8E%YBv6SCG%;Z*9WNlMN>6(`e;A- z@RsN1^?doI(NDkZPSQDd-+MfzG*9WakCN*T*F9VSg*V`xx?3a{bKCd+xt4pw?@sJv@lTHfmooBJ*dX5Vw?n{gN3vU zOGs&IhA6NR31;?vAI`dyZl{f?bM~HrKVyiC~$myAEEd+wJ(jo1@vWg_sgk%%#P35JTtcMef zFSK`6hSM^yi7QCb1wRNcHO-N_BbSA9)B0-~|Dwge(8b@%`rClN<@{eN-C$g6>_feu zbz42^KmPOlXQ%sLbWaWEcdAzYjv+!kqR&69rjCe7?#sQK+xIPj(T3a^-pOAr&)=5u z(f!}O=l7evuF;*)&3<_HW+vr+R&OXrsHGmdDX{h1<-GWoZ8z8)>Lb(!*%&IUc_l_y z`TVBm-qF7{KgC`5*Q*%>>Xzp3qxw4upFO1#mxgT=mViJ6`AefF5bL2c!I>9UYTF^z zwB7UQwTaFjzw|%ene!qj71s#}rxzS~#-C1V_Vzjm{l^LDqcPd1UJMH#=l-X+dkY%c z+At3Q8HzF9nGqrgATkt5%02F8s;&_uKJD}DXWX%|3J5heG*`$0%bWTn*qq#EgH%_? z1TEOE(=uW>33>Wj&Qg9wnG$W_UutHD^hA^!Y zAVZ`K#bBgmJ)xlhlu-t-G*S>?NLw)gL@b)40y+aBaX>&s5;!)(NJ$B)A>u5H39(LL2|*~-LI@aynV4XT za>~*YPM)5^%62j!paE=XQ!g5d0+IwF0Xz^;4Pb0S9Z*D3CL-dciDCqm$dXPr5rkN6 zm)~+o2S$>J;5GmX0f2_4232-|vYak2=}=I&$Z`P$z=fEuFXnq|L>=@eeX0r&ZU9k7 z%KYW~YvA;8zS{?>yMrCA4#teA5KofkkWDsa%LI4t+=mgl+KBTM_Jy8Hy8VXA?WJnAE6r=($aG(f9 zNKgS_Baj++5D~;cATl7vAfix=L{t%%B&`8Prb0o4R01#$<}@t2XLH#e02#0VfglI~ zHsFGw1rRo5n;;DnU?y!Kpj=Q)3uenf8cITF%+!(`sR>8}4-gQ65C9Ot00|gi8z+8u z5BoGC3Tg=fAOZmZ4Zs8rK%jsGnt?#cx(X09t;#?G89)PwfC6BkBMp?Gp)xg52*@A} zfR2EuO-)L6p(r5}bP=lTdvI)F1Y>pPlxwV|#xDNrLM8j_XY@otHPi?gKm<@qfPsNZw17m41ms8~I8Xo- zwE_evf&f>H0moUWkb{^zNC-iN6@mcS@Ko9@*%GSmbg~CYsuL6#O-Pjj zm1=rTTv9O%P|Ii~f;IGIbHOEw@R6Tw9w0R-^J=`aywB>}>eTwol8f{PL$ zKdC2wK^lO7C}1EsKMzKczY0xm%b zt{DU|7*T`@7C-@K8ZSu96pgJCGKeDbd%j!Eka?LX!vZkEhXRox6?CBnw?XN07GVb5L>BH+A zJ%#-}c(g8f=goob%Sdad#%e3=h*zMuCVeJ|4mUWHFTTUg6aHvgp6&lQg2 z!e6WU;?aL)Ui)vH{Xcs3{kL)d77!MA1QA@q0u@)xUqk;2j%N3IXRa!Ls;&=mH*0tV zM_d3g2H_R{HgFODrLlsa=lN?^SM9w$DX->KU*U~@oU{_%p+GjO`l9+$QXlLCc(sTp z%)p?B>MNZkS`>k?_tO8I{m1_{{ty4<@>aim#6OUS=5H}>xV^m|RZxIrDP0)TIe72&{LE0%wdg%Ra@PseCX z1*MrGi@^g{ZKEAQ5A$ZFUG2`3hPlhLz(-H2fz}?Uh0e6P-0#A>>6QCIMS?sHPt}#D zSHNj}yeh3z7p`PsD#(*DfyfnMLl_dCSFj84dgV!u-;{lY0umY5$ zb_yE3L%2>^Br00Djw)gm?k*QD8h5>_H6!A` zyY(45Yw?s?X`-*w?Z4@GJNxx&{_+M)9Cf#@Rcf|K^1fQ%>}Tx6O>J;W#W}ssA2=D` z|G=|3vFD6A{PoX^>lZNYP=9*Ig6mf6lk2?k^>+4G{`A9MXWaANMR={3`7Y1Q_xiWt zwr>yjbp{>Hb0!m&?zIR*evg9r%R^rC{F6R^9KFUUB@yfR4AbrOaI@5z41eckX9&Nde%PIt>)CEAxW z?$-c)tcK^qp=`Jd*>LS|7D6f6nL+@96Txvbg+du1Q=0klM62QS35w5dYE5NW=WOS} zCOWN!43I1hu_3-)J}FPu6QyJ;iOmiRC>8rh)1Bu{N1LGM&}vBM2Xp-F`>K{Z_vFh6PtjY53`JW`Gr}#a68TpTR^v?Af_0#sM^1g^B==dov z_APGFJ>yHmc2A{N+*gMRve9aTREP7j{_@DPVD`Ee@sgQ;vJimfcyG{S6NnSoHfL*y ztsGVp}P8d}}a80cW=F#BUC&QeKuncT>68N7AAy*MDQzKFR1L%>)b9+~&P zwml~bhhQyB_N43@_m(wtB=9I~S*(lWXEQQ%SjTh*W?#ENA@LaltP1_t7|M$DVi;tV zaS3G@vWK&aGvr`~YBmh1rV1bhAq9d+L=ekO+(i+_WUR`P)X0&S86gBnAr?*n;gB$u z2-dZH6Ra^Kg=C=D(+0dSWw-z*5hxfE6oCn15C8@UlmJ9iBUNZHNF)OVs+g5Hr~*m? z5Cbekpak*)C1OxUEJ~sT0S?4au!0dJVJ2aKg9Iii0uErxz+i%q0GK#t01y(O37|NG zgtCAQ94P<*1W5?PBmhbRg2ax30+In3XrnR_0uz#G;sNE(XanM+3TU){^WpdLSl&NM{A_6b~FbN@}A%IW>0T56I0u&%gK^VY+0#Hf&|7P1VAEEQXEt zfDkSO7;u*hdI}c;Ko7y5XnGQJWRn}BH~^Z1_{jwNl^-*yFo)D0D!28 zBC1MTFk^JM2qh8f0T5IP1fT~c0BE312!V(dR!CT2ii#IPKoFn-jewd6snpRuh=p!d z1V&LM;+dh(xQ8hg=8XD1ouH070%Frd6;cw3O|cp(G&&}2n8LU-xfPqX5v``R4$=Z7 ziD^tgr6lYDg#sBc-F%FOxonk3qDOBP+qeD<+bRPRgJ<-`^v7q>uIr~Q3WII_W^Of#m(<0! z&ecwYiKJc}Wx@qBY|UwjPyCFZ-;S{N=kYaPd2tpx+7@Uq%T1YU_G%%?b=S7*2n!}t z476R@gNR0$iG_h*Y=TTKB%tJk0|*HLemV&PCRU)%&uM)I0MjN?2MPRfnON5Q}ZzTC~x;TwQ3${ZX<7F$x7plHd+S0IMWpyPDdHJ&X(CQeYWMMDEHG*zSk z4;TXXFaG`jF985Fz^JAJ00CqnfB*ydlL=vhg-kF3AiM&ADo6tiHGlwv6~F*NzyK&& z3?wWV1cD(@Fay#6005Ui#X>d{uz-Sw3^M^&p!~_SGXVhu03ZP{TY?G*7P1lwfPrKf zEf``D0w4eY1=N6MF#w>X0bJ~MHP}2SEG9y=xeY2&1*TaA1cU&C0ssbK2{cT5m!8U% z>#=eRg99*?k=j;yrK9Xdi9-h0j@iS-riwk2Z|p8S%R4vr!BLg%i-?iu8bS3bsP7Gp5#0 z+#!d(-V5aOI;hX9Jtw};gZmcm*Xq0)jjJEiB0XalGBbDUk~1DzUw0T0_ka;2Kzz@@ zKac<*z(}^en5SLc6SoIGnvse^WUA5N>V`>JP!nWd>w_bZAO;W^+K%GnGWNTD_)B3R zNkw4rpfVdSJ#-6fF=K!*Jh+vLa~{#a4X82B32d(a^@sh2Yzj3!H8+Pyb)q~b0Zgo!L`(NX3PtQ;1ULppSR6u>1GXBm?0Jx8?I`-rJ{!GuuzQkNb0OctX#%55C>!E*>4k;U#yu`0LCv<9>efyTvDy8})Ua ze3&^nY(E*T3OkwOuYU~w*LVGUkInJd@B8L(z>(g_d ztdIZl_dEAFe68DDx*y5ceUInYy!b=a_siqt8ZpZwzQ#qP{x;_?!tBA>uQsFnxhvn5Z-<%(1VaqC))JR(($`zzVRnck8* zMZ>wDR)l@@1~#Ic4SR;;e<)@%F1Jy-B-y!Hu3Of7ZDgto8+-F`xnQAb?YXWSHq_w((cu zN@E;WfLWRpm&;DO?s&y`Ts}7P8KelaU=nkZ001b1fQTVY3@Vaq%&2JR+vI$M{ilhJ~D8v8? zgc{Hu0Hg&325F*Za)L`*&;o}9IFMvCz-S5uW(dM6E!ngILnUaSfC3N<0z3gApo9~I zCfo)@gXlH@32by=?_=XDJFY4nhKe>S285ws=_-R6ntb?C5l5>ncz#S{{UAR1ib+*~ z+t5WUplD2u%8^hg%iRhvy}nS&qC6%+46sIRyKX~U$OO;g5=SV+fD#Qbq$R9EW@3aD77!9*>J*WXio^_i zzMxJB0g(U)TGm7XDB(~G0_a2tat3B_1XMsqSW5^=K?~5<0EP%COIwOYSU3Pck_bUa zB?6291d?8uL;;S0P$`YXDH;+Gktkvy1pq~0j8r2*5UUWD!g7f&s;e?WaD;0Bq~>x_ zAR2ti+-PnOV>ZxIsHXC}4Li5+p$uM7u20k8)XPHxL2P0thsafdX8T2p)og zv;mYRFtni}1aWSKfM_z>12R@N6p=~+$Y=<$U<81afGW{MCVYsXCMu0WC6|&C6hIJ( zfM^Ki3RO@*IFynSQ2-e{RE)BL2nN!nffTd}d*rgbtSfqhmh?Rs(n2Yip=q%#P#q}L zf=HflAsm)Rn$z#`MKGBUH3elvBxE6!Duicrq9qNW1Z4yajY)729ViJFQHcSZm>C#E z2)QJHNB}Ws##0WIR3b7UL@64=5kLYe1Q?QCXMlTNZ*o#K(Ug*9NxcV%dIbhLpeGvW zqEO|5*pCpiWo%V{8bsfz~zR%g(Sa=B|9UziFV zsS*uQ0Hs8*sEgDhST>UktPfT@^at}>dAc)}gg76wzJByNY&c(KGjs9YLlDVA%G=UZ z8wjv5uGZXwQD%!cf4ey$0Ln6$XUs-Bnw?wDSa6TgTNvqA-6fjPCA|t1e86tzvXOuZE5>YjYac^T7J8$!4 zuQ3)+qX2MlD!J&2tdmc`77{4t%NXmdECN>A)*rC~mUiI;ghw9FIrBu|rCt(sASw#@ z1ROY8AZqHNkrj|B0SuBv;zF^J6Ua69YKm1k0nSKHvQo`~rfIKwCNdB>`EaN)$@XG7 zL#MI7CaP`6^|8;$D0bN7h5^$F*aP{Q?*PGnXom0)s^j54aSn>|2rg(K91K%Gbb)bl zfB+WwkSct^L|}eeB?ea=pRAF&AYh7537typI0YLt@XPQIf&gb8HvTE88VZo}(`oo@ z>dh}-{2B(Q5{5|>0D$;1CxX$g4w-fV$f!*vCYj_oHF6G&Mx>)51Bf92F#rIpsE9%| zRa5~HKocQAMZgLLfWL?Xfdv4d1-t|R*Z{Bu0{}3|XaIkT@pTpgz(R&u3|2sZ0tf)v z2rPkx7O-TJ39tdzOhJPI2mzoFKm-8wlSKq709eEj5O4_r13z`W1ZoBVWD)`fAO?_O zC<0qFQOOnvQve_=;R0X=A!ZdU*=e9z4FoIz1_5aF1`n`7Ub#0G_bHhzRy+X^s}TT* zVE|x(3x)xvgH=}FI=9M}D$(}$fvz#V%FflUYsp^i<2>)#EnzFi&qw>r*>E0Js8|N|t6y`bo`J_Fe*P`AmU?qNT zmc(+zqLdk8hQyT=mbnR7?z!7@jU*}(V-J8poiKOvmR`hBZyHr8i|~xU?4vL zl5)&(Av4z$bRAFckSbxOXscL(k9_QTM~z(R)gSBN*!?REMN%(AZi;=66+mTkW90P4 z=>2y)_#E26Oh^SsnVXJD(qw71rNSYW)e9pCKYj1{&5Qi9_;JO(lGEz=d{sTR*JJm( zL!JDUVdmWTZ64|pQFmS+=1czNaQ^4vK=0uH>aT#mf?Mzs{1CkUDyU9sd@udiKmX?O z&DYPj_!w8*a6rTYihl(L{24sQ7?|Jb^D@6@x@&$iKp#S!P|{ciWPeuD*oqKlo8B%| zBZkmzclCljW)`r*CuLWCz@D<*Lg2P5o&FAYcJ)S=xuPL9g_OQU)*- zl4Xi)=$eXbQ=f2kb6Nxg2Qe9EsGVj@Nmdp)q*h_-0#yXp7^T`q zE^b}r5v*{c%7Fq@8k zKvQFDySaR3bUz15dG5`}kAK}yp8E8Uzixl=`1vvPA+KgzF{Gl>LV zgwywXJs;q(G_*#dirh{d%?k>)D$y2|1yMeL0Zki`FiQwWS_B3}RZ!L>W#h;?iu6$mTR_zk8UfwY-?EJX>WV4UQODtEhPQH`C3=#Ip%&< zy&es=rS&xb;Iu)brd>@V>+Ay`{Da5B*Ic2%s`^ppccjLN1uCg5-fcg!uYCKZ4acUM zK7CvGZ<3f8iN>@AP^5KizBMW;3zSe$4ca4HEH#!c!U3}6s3=0{3=$aELHPp8k@W7M z-d)rAaww3hKx9Y-X~^(gg~srN;T*WJBos>N1pO5_QN97T6ofFr001RQxdPeH9RY~L zQr4RGP@lRYt{?;~Xl)aYnYv{_9#L! zv4|K1S{MacYa|-54oe^~05qT&&_YUL2m?t-fEXl<7-oO~QKV6EiW4|eqz0-`f;fsm zMxs!n1VKpzaM(NKjD# zKvY5lsx%OUNdTAu6Chxh5)?EOp#d2HDySs|AOb)EKwttU1uz33fox1U1U{SI(_}R_k+*7l4I9PAEb*xUGf$0J2#~5;~BA@(}_Fh%lnK z3_>0fd?W0Mn8b1T9I^3Km2Yop1$-PG}5iWS8rR0B$QePIR^dQz3>;Q!yh@#YmBe zL`+~3DuaVD2qC5-fWkCX03vZfNITZZ0|7A*a!gUOpSngTnz(=rOXal?r7Nmd5Z*!o zR1EM4SDh9?#*ZY>)>7RDU(rZ93V(g5$TXgNF=#U21Zg8fN&_WpY(~6mlViw7oNkR){13;9fJfBoP6eU9mpql9R6sZzP@hGQYRF%~O zbd{GRpcvwZz(hquua-j8mKvzDg=-bUaKxTN#~z_;VnF~%szQ&mU214Vac4|jSOPEA zwW~X2pK>&T%IE!T>S1Pt1|wS?ZgfoLYK&?o7e#^xPnhiC-C=REhnQEThNCNE{39j&#EC1#5ZJF<<8JwE4DlC2z%HAl8`vBVPm zCC~A13^#22?yk6C9Vobd8<$l?EbL+3R%=F8=6k*rlJ5OyBMw2s^`BWj>;(WTw zk}j|Bc5^3~R#sPYK~nOh$ud|MNJB7(fteq{BCCKiXiF?I@|1JMk`*ba_+tCR06{-@ zGq;KsEaNL)>K_WN+GydbMq!2rIe7ZpMY$oWL*qD3D_dw(b@_SB$|b<+>nxfoME!VoCcwm<@iumI<#z z{y@F0@lDn}oKF)SQt`qfL?cQxrZ?xyzhQq~Rxi8XD$dHTFdS30Hv^l^lMzgOatRH9 zV1linq36xP;rTr9w`$3-a}9S$WOdnR3$UeIRQ-~0;X$j(~2(zdqu8 zy!z)i_a6%5_UGR=zx+?-(EQ-t`>%)VZ`%Kr@ca#~kiUZaukgp;;QTc%YUj{7?_FC* ze^8ocdhs9S4tQXJF%A&Hh?mH%JA5&5^c7F?pVcf@v^JJrk%YU{Wl<%a*g)g7%{X*P z(JmWLm>(aR1X`O>&R&x;FVVng`*3&TerWYLn2-H+9{tMf6VFHv{^GU&?7G~mzdZbp zuZ;+Q3wHxZgD@Tj>Nl6~EZ)H#`ZeURx?6p|`8yl*ApDbk58RcDoz2_QhBb~H;x71V2Va@_QYLLp38gklqR z)FBNPgcl2r2&9yVG^!lCpyJj+po#+_RD{W(iQp{<1+xB~p=6e3Y1+(YWeeYUXew<{g&s+a-N`WrPBDj4MPp2mvZ;J9^V$~cksy!U^mk#dt zaDv@2-G~l{U)I-r^mg}X4$m)buWh`){rYj>8?lDBE_R*c7yIDx*FW<8$?xs|;_UN% z2IbU+WvfD`B8#G{_0-DLHnde!UOzNxu0#e>?uzU2Q4~NSIFKzmnY0Zpw%A0HddwxE zYnwQYA4+F7Nyk`lGDe{~MwqwP&aWS_oWFTcGke#%EV+t7C<{^dtwzJ>files+U6t7 zT-kH{zI1Q)lQqSZVe|trgyePUK;fBIdhQKi60e`%`f&Z3TS#1cTdUMiC1zU}Cx-DR_aby<_{`$b_(NQYNdB^Du~N9986{dn(1q_= z6pSKGa_i9jTb|8@7dfUkssmd=u@2{?4tPeWfQX?cdYe$Rvs~0$ zXB`LiI=0n7d=}&A;x0Ln9Mw!xUsh;_fJ1=ZDN!h zbd!Z!GgB+fL>Zpc0wPQGYvf5>BB zZZjWNeHIAnkkF6wu!LY{S_=$(2Ggs-nS{J}2nYq)*qy4$i$sPTFcAqNV~m7kD~fHS z9$&|zh)p^X4JpSc(rTLBwJzD4c|2DHxJI1uuMFjWbkvfIf3uY6UY@3j#*pl?g-Q=;tQQP zRu7A`?Pxbq8Xkk4+8`C3!c+XMWTWFD03t~cis#If ztIG89vQlJN(iLMu(PqPT&P zIN)tF0mPWdAp(E`Z6MFE$k>)3fdEh_1QG~?0&oc&SrCFb%7hX&9AE$kk_bQwAplSa z6i@={DAiCP0~H0ZgbA1^2tYvr5r7*w0+@=9;QhxUn?g69?C(9b?Q%KqCUOmDbmU0q>a`6*)AbRKk6!{t}P>0oHAvhW!<!FgJYjrIz3SYy zWkwbN9cO1{hinKWK%BgtJT?9qt8E-)06~=r(!R2E@ldDzkl2|Bi2+n1i3K2pkU#({ zkp~1|0s%}+DFKt1r+TIT3|9du}V*svt8sdRg-3 z;fRZ*t#+F^qX!CxR58etPF(C?o zr)U1SJvH#`%kRDM%6b6E#HWFQz*cDleBbrZZQFY{TVAE0e66-T#~3KvFWoGDdHnvL zwR$0$d)`7uxtp8oac_Luw1@ZKlZ3I{g>pHZTeY3$tf`Nx;#;87rWIRqr*=RrQO3S) zZfdE0`_WA69h$q?FrX}1FwcCsOI%dM#LRR#&J{HTkZd%a`#n~#Fi*nZqd$d(gkNd_1W+VCM|KYJk8>b7$x6mc6&+gq)!EN4#fc(qKdOq`^~uYohzYNf z&-Lx5NHau{1R28@6!`wB3lO1>3VNjCtcvJN9E2@HoaG0SQoqvne^KJJq1-x&Q;ceU zcx=J9w-@x@s;7>{U2;v-=w5L9X1c}m9HK(l9+76SYlwY&*q^Td>f;vvaOM?9z5V>p zizq$_y!#bAscqaKaEM=jmEN`2y}Uo@z9#*j*ZCjE6+S>g{|ZK;G931vZ!6yJ?8HC* z{i`3l=$EU%EcYq+1S(J{TR5^^|3?QR!Y+F64mw2O*D0*)1NAy0|=Mhc~H@!ao*~@q2{^V!K!@j?^H@&60 zY!_P~!o;{cHi89KJ6-=`)4eqNld`w=0Z4WX5&N%sUmZjFICMN-oTEFG4+Ye-so*-3 zl69p=WEXcOnA>1Lh&hBTjO{v9Kth>gKrTufR>)24m<(b>+4RV0(1p&*D2Ca>QYa#X zSfdn{aoVb$2h%PtgklA_DAIt8GKz`BgnCP0c7S*vyisbC${5iO!vGYhPzA^}5OhO{ zp4sv3rBYovD?RjJe&f-sTh+zFa-A*V7y!pEIG)e*NiUv^O`s@%1)G6XGJ` z#=t3zE$cJmGCBS7;_ffAe0JE!oTcuG-*>etSBq-z>g?pV9ql#h*_oQfOCwPf5Jr2% z{OF;!s;YQc%?{Ua7~Ri0w?)RNpWa|Wa=fN7wV3IY? zw?WEI%XW^N>SL}vK`p384DSc4=tmP4vIvXYd#C9w!|ZkCPuX_Z;Zp0+oKn4XFPL6u zPHScHN1ci8^cRVte^7gpsrC)jY>;tFTt*BcgbB!~-uZRjSQzr-No~8tn*vc3 zngXgF7anmxy!gW>8#39b_*uOFJGvDvb+L@NJC0L7c@G`a_6lT*GP2S{hB}0jHkBJ| zfd?L38lZ?8F~Vx5``(Lb=Jb5huP>6Dr6#`h0@R2pnj&f$aSXEv3Y6@`{g4mBqiXzW zIe4Dmdh~hM>wdlw{+xez6?|JaPv-js28z$aJtkye$JN48ojmjSNme&lQFO8N{mv)G zkI1d5v3T?F^-o_Lbk2^71^qwc%v@93BjIpGYGw^N2o-?*z{FT!focJW9T1vf92sKJAzJ ztIF=&``dk#^K~!q+Amdjm<8GdQX1H!EyxwFC_|yIN8)*054YBf=c}fNRhTAVNe+T1 z$2sjZf@QrY8LF!bz{-Yoa9|&1a#_S5%N>?UYi5zQg*>H4Ca{MuFfi3?K$93bt9Q;L~1?A*|B2hKS08W^_TyI;LYdr4l2txqXkW zN(~O7L!x-%PNYM`N;J{>l!7!&93#-8^;pIvhyhF?kpp@V1PP%4AxMCWwiE~oDLyv% zwc0Dp)tZUXrQo74agBC@BL4MnZ;EfilOW4vNqQB9KZPjNqKp zMWtg(jvxW1vN(eQ5Er7=D!qt_(P((nm5ceLdgsF{b{Q=Wc3&l{Y}WR6NjFJ*EoSe$Mk(djN9*d%unh^mYI5l9;1fJzAH0MJlGvI>!;6DcSQLM>{jOa(R30+JzwiB>SgN))JA z2Ef39AQhkh3=#+c3<8V*1QHNp0s?>oASE@dNkk3wUaGbo>A^tiEor-{yvF4N=LZd6 z?EM`nLoK*UC$D&rg<4ilTd&I`piHb2X$I3=!!asU;AYAwu%LI_=wO?@Trbe*2-umn zfLkD%3!idwa3)D)`*6w9b+ zln=B;ccFb>(`9TGD2j@t^%=I0QVShT&d$Z&Rbi1ywcu*Tti|86_>sj_4Z8v@n5%GO z{KLy1D0L_R)oUIVMq?hUL=mGTAeL#85hrbAAS7@hDFkH#&7fomL7|X1Q6iK8fCmCp zQY8?K1qw)jEa`B@60@Kh>c~UbG6q7D(?k~Icnnl!G{LEkG6abpXsl(N28J7Ub|-K9 zF-?|2$Z(4|7g;ZLJj&8+^xZ=Gb9bew_y8bF?--PnzNj5H!RgTkI8u3+#ZL2zOG*?G z6;Zt~)e!|6)N6r25Q>;+pab9-082n5 zCg4a}6w#5KZ8Y%6+wq+K(}JQ+4-CRff&Hc@p?#M6xdZf*)WTJ)AN;^X-~cd5O?wt` zp%h>QjI#=o7m`HEDnC5~81}h%#6~t2ie<@}1%jhblx2!<`@YvGg%cA&3S8LbFvW`P zi(Cto&qbm^BqkchS4hAYvC-hCCqW+?7Ctc$m}neGffIp=@|lmulYW{+}fVwO86apl5~sWwpsuT3MNMMVEPf) z#It&l-|MlG83BEuZ_uCWDs!+-Mgj~#>fV*Os!FwXTfN!G?8^26LDLi$ekY9B>@e1wzu>@h0feP7vbvCqZM5!Z;{8~Xu;Btw71 zb4`Sa+{~z1q)=RvBUe)N9u=RnZzg$LT}c zxutS7wR--tnVZKXR2V7};6u+3j9b8%fYU(}oXr>VN-gXYuUll_2G!x5m@UN%ct zi8%*D*K@45yMMU4zgiRfp zDIHT81`2F^ixUii?YM-7P-UD4<;GTcQQwB?y>o|=8eV0q+*kzjxYfR5ulN0+{QR2_ z-XHGO)8pwZpI*0Gt9Kv(@E~Kq*O3;zBl!!+PUG%*tHk8sz;~PZa=V@-4L3j>g$-JD zjsaqGYMM2+7K)A$7qE`4TA)FD99TSuLkUEKJ9z;jU4`!=#h%H#D>Is54lb-LQi=_O zQ?`NxpHNVwTmV7E&_h#ZbrcOKpr8^&P;@Yr8bXEOM9@Y>A`$_cEK(7rr0i^FaZxQs z5NSsCCTm;D%=dmd<6p=xPCHNc)b+`KJni#ESjcd}Bs9WQ^gw}TgJYt zjBmm|`FfHM3#_C~Lzu3C?Y z#n2DF6|k;&WombcXSRmoFqY7RvN8Y^KcybcWXWP3U90a#HPGM8$iA?hH!GKalB#Lo;bRQBX(ytO(r zncCo;C%!&|2g&ud372Jn2oZLz5)UZmL=*7>Wz_k)(&MQr>d5Z4gN`Fo0WwsFH$Rh? zzi4R&DdQEA(3MMztdoH#O)9Iy(GX2HZR_mxjoZoXWarqpup%`zlVAAgGlB3*MPQ1| zz%^q5Bb-WAuO6**?JUN+BXyH3F%D^AGU=i@kJ{;qA?sIqu0|zYR~cvLwzl&&6-6R} zDM0{H5kLt96!NUE#Led4X1*kehzx}!;V0CTTRLpXm#{wv2-2Z0VF@2lRA|4R{nU>d z+Kv7hwtMjg)fg3fZ4gy;OdriXO$ZY!lP6S1yXc`;lU5!xeD-AHP{?UTlVSv1?G0ni zSOYV+ucWUp$aN%WLL;@;HAe$Oq zDysle5UJ2x6~Ja`C{VHwR~4=(0qsQ69)~RQ!LoaNZ2K3R$JXi1iBL?d62Vlu0bdph zVHGc8{^;s5PJ|Q$diGiFn%tLm&c4paX~z0~k~Q0z+5>ZHUJb5P(L; z1R*q6Y(@%%z>EO48Uo2x8jKJzfEj|ckzt?#Nx+~2h{1stkc7oDpa}?oN{Up1027$x zgg_v`q9K=2d4`HI(EvpnNKper2EawbfCr!;;<5-d`>qCFJqb`H@;)0!z(Amw1} z|9)+pF%jZJqc9jX5Ez?TS!pCFIc?-Thnu&q=DMXYUxR890}r&1dh*K*$nV ztC*DKp(7v^6=}uHnYVO5y{>McT|^(43>ddg#M$DZlv22?mE5x?iJjGwPb|HCVWX8+ z?az&BakSwT6X8KHUH8=R!sX~%03gaihecvE%CpY?TAtaY2)AJ}vEl)*^%uXo4jiYf+0p1OaL&ny-Zv*o8tt0muOW0Kgy$6hi_G z2AF^VL##wPLZGO?WcF<=Z)#yH9$FiyLy)X4W<4$Qo=z2@-T(=n|P zMfGHbQ1N~xQXLl6th7}mMhaG>)Z`qcu(|ON2`mVUAYhwdS)*6RkTU*YJ^Lf(hpe7WHkvXiRW1t~pF=SUhCcLAFB{s}b>C5G?-_L>@P>So# z#E!8P7e!@itefICwuc=PlMJhBBTPDlVvZD(L`XS=l@vb~#h(PE=>d0YL`8;?CMn)J zNrQ+XqCisJUzROhua0^llGa6SsCau%?hFSZY6u3`O{_5B@hL7y7O{n~X9sy!plM1v zM8OmO6djc4o@dq=J89GKXlYVyTpCDc&h`++S%(@?26Xn^j+U z%DMPDH~3n+=1znn4yKvyC6eo@E|x~g)7r9@wTx$9eO1Z4BqJYMz}%hK`%O7h$juVN zs6tu3j4FxPc93(boW!E}ZL=`E4C~$V9R)IG6p2y1fm>N%Tc0_w>QtavB9**u`@FZ& zE3$A}+fA9sxs8y4+F%sHMzza8BqxiF5w_WAwoCv?Et$k+lua$q>pIU_H+yIl>gIu& zvshP6{~LTg0b8o(ez~9IlZPt|p%V+lKIL?9lE_aaAD)~@Q74QqFl;&iRfBE>3ZUSu zBz$62NMpDqvj*+-5IV5p zNFxwJvXD&#nl;sE1fT&3f<_q=QHv0@S%Z>d2mpi_Ac`RXfB}d>2?3Lk29ntTLCj)M zff73X=myaXMUKtm2*?K%yFl1V$hg@r-~ zAL(f2&MhEFWe4}lBK?Rymzchw4G>4IP2!v^*nhnJg7c? zxB5^`jdRyd_qY6S$6FWp_N;f<5fwL;=`D0k@8=;uWOq^owFx}B?#DsDPkT(*ZJrO| z$!6XoDuwVqmq0J|@xUK<>t!Wmo`7j%=q;s_ZoOQ`e=$&fC2%4;`?4D@c9`NqYb&(Mh{S>Apk&zB9sz22>=iP z0*Qvy6#6WH-_wdpDKRDHrlQH0FlshWkQN7&q!dZRvza{qwk~-XT+;}Iv8B}=(HxGC zOY8hM(V{y4_2Bwr_xzQIKg0iz0>-*GiH_NT~F7q3A%rohAE(P_ie(V4GNBFCM zSNvQrf3D^)fg`?%>oCHvI;zzp_zWWZnuaZ|6a+GniIKg=-WpF71C#As)C(=`hxe_i zvyKJlCRsxp)uhbRjBeUhe8CkW2(IlFgR3D5`(1i@d0)T!$7>B^2YMk@ciUG3TBU)S z^+TA-@wD+P1{7kxvp%Hb!3GM_$Fva^tq=xI0R^jPc#GgV6p%?dMNEWB0VGIO$W5Fj zCyHWa)KqcB2v7hI+;taeY#U4nkOtFMsqRss3Z>!zTb?lk02BnFsbFQ2#||j2070S3 z0#~L15n{_J7PS~{CCrf_U=%o?8SLy2sA*JbgUiZiPS^cBZ501n_(!?lZ#v69WPka5 z{``4C@^Nxg7`I(44Yt$W}e zowh2|J1?48FVz&PGN>w9KW-cs7T6$V$iQF8byEao1y#UKWUY)ZbGA9fJ)qLia8~-W zjj6NeoW^iOA%&^ogG8_O8gnz1a5P--(3HK(I{qbJAGB(xZH9+1gtuOOHlX$S8tmH( zl+KXTc%3P^p4Sd%!Fzk2a{g8G41MA5%n~bFD1qw0$;Nm9m|72m*4#)%Qe}&$PJI|p z%p*K871QG3YSe-iQlUAh8uFy}aJG2#NqArJQL-tY9ge~$^FG3PFwO3fqgy8za82Lj z-^q)Cm0HFei@3hJ(!8`WS=id>Y;3RS<480tEP^a?>c*#Dt=?X5uAF*pw)XRs%>Y67 zN_YImDB1BTc*<&hxvS@UEqip7+*vOZsttVQ6qr7QumnK%B_?7;g$|WYBorgzI?hk> z;GV0hF5u#=RNPpjmS5Ohb!%YHu29?_!!_GiOW6u$&>T2+5v2`;{E86O1dv=yQE<-R z8@`tA>9QnPhYpH?7F?S%HYtg#NGF&w3>-sVi)TB)8f~uGnS6OQ9crMJ? zllcq?o2pzl4lAT_X;qLCBdh`^%`JmAwMMWr7xq~MNR&W>a)JiRWP&v#E!?bz#1;V_ zXuzOWfMYO9jEowPiIO5f5Jl!LMw~9ubk-CG1k~YXO)@rWg>u#DUC`}9@km~wnpoS? zF}9pnr|FYM5C9g+H%g8HB`nih11q5{f}w2yS||bxa{!=7Ab=hDwvG&F0!5%@jY&e9 zfX^g|gv$mo+nBU5Rg5MW8X#k|3^68JF*SftX$jppCM>9_b3+nbf_5e05o{oo12n-V zCoqZZ6>Jyl(gEpiheT6+#M%pxRn7!j%wK&7I!DU)P1#^X=_2tDnSvDeD|(Z(Yuc z1Gf`?wg7Pei|Lv(`}DBl23yFG5gAEY+EsDV0!g-`Q3L902wJupKN3E^%;P>hqBkVa zvC$L?Fc~pQM^z^tn=`3NxA;JIy3Cfm&Kn4k=1OSi%M8HE`Vt|4v00bf>%AhzZ z!^%&m_O&2rw~^Z+SO}JJ1jUzO0Y?Xg^DoC_Sen_G4%6COUkdte`D7IwLkm+nD2)5- zmTFQnsAkKI&~(%^c!)+omOQNTFS;#Nj2Ht{KuoB+8oM4FYn~a7V4N&uPUtuo7Snbd zxRLMF*vwtdeUYQL)X)zp&Uqf`*}9M3%c%Ff#}~Uxd6A>>gidq}57iUWoF?8(Lqdzt z4u|T%NSIiwx||VxSF=RSGgPHo;S-ms7yN<^hE{@kk_;%4LoqS7YGY#BQtV)2R_fo4 z_7PhkE$`M6q{!joY;~YbQE4iUR;ycOs#<`GrBYJEdpEZ9D3*z1%IZEh|OI)2{3wml2Is9;ZaG&5azE zT5{KXcJ~4+&zJME*VwIXr^@6}xX^aIjOI#8myw+Y=ZO;G3?qQ$OxvPtBWyeTOyl#y zlQQtRHzcG+*~Jpc!Ied`*gR#?@=atmplfgeT=G%Ntj|jlb7Zh}c5G-^n`M5~1Bz1S z>pbmsJ;!ibsY}7l7kZ~x9}p#sNfrerr_7*(D;H6~0|rCD+yxlcB3BHeaCX@!9EQan z9WKwhiqiA4%SRQX*CSIV{E3Hdg&Ige0)&I1Rl(N^Iv%8Nd`Ljh5>(a7%|NJd`i7EH zmE__M4q^16@L|yJqhYaU7&k&q!(aeaASl@QX#hT38F1rJaserYY=hp3ba>b+jNoUswS`PBgpmV&BB@Hd``T6b{OMF&#+-ekzT%yt_l-t3` z>d0ili8D)K4P*pV1(5UQ+ z!x3sjJY;Lw7u@Tpn9X#vTIH28Py~PgzHd$so62uFmoYz$xVIK>{Xmb97Zg|-odR{Q z_bDMqBv}vv#P5r|s}c+RS)v7h4Q_516G!)vy5!=Kc3nxkAqhYc_h z0#80Nb?W%axntI5j&ZK`kNwXRe_{_bP_(;yZy(;=dmX(#zh3FwgPXAI+9XfzXE~2Y zJ8Eyk{kGS1-MU}C9w_;=O#~^B&p^>gV zYgCA53{+f?YGhg<#?8Q3{&&$+PvJbe)y*Bq>>h!p76}PcXI3F4AY-F7K>g>E^2vzvVE5K2%KgR7mD_qQZnLSxW z@tJ!xNTj!~t*j%ftIwsqR2s%2h?T4rB~EH)I~Zdv5k{3LunH+&pP#NMcabO>sIn^n zfdoZ*#=22C@VxFhFK~J5Bn!;#d@F898cg~qJ=>P7(%_036ere%`pMQVSA(jmZQnbL zy`2CZ0wdUQ41(2ZD*Md+>-D~OXFaRj=GAjXDp3nl)?w3sCdsN?J-Ic=OQDi&AP0AE zj8d^e*>Hzz|8<{!cX8OF#~q%MM?+4~CiCS%vDtfZi?7R@Nv~tmi-Sk!#FMsPRqPmm zlXy%V;4JsNM}Y;@lwV1H|4R`1>KnT=cye%1fH&Xwbo8=x*EO&}hRVw6{n4BpzRatz zACyyaw@VkIBUkrcdpJ$f?`1uE_JN-6V>|26#8GN+29-QsC@`BYL_nuODH1iTg`-Rb zEF?hc#A3s~_4bQ%U;psrC_fqzqqTL(B#F>jXK(YEfv*ywUCXV>R*8EnYgsHG!j@RC zRa!grO3Gk6Ixbcu32xT%WU9N=XCia{1Agf8Ta%=0y*+*X>70jm+*r}Uqt6L9Rvch8 z`PSlFtFGNYN{wQ_9_ok&~{i&X-WiAfPjWBN<}nP+aPoO?Jt)j?Jsij-&Iz% zi-;wcsUA{C-59$azyvJeM3)?RnKRTJPq(n2qK!?XVT>MUkLAoK zy3FNbd)8y7cLix2pxo~NdX$RaEQoM=0CM+D1c-qRwZH)>A;&mv$-<&Xa#%QZk2_d~ znWSwID2Sn&NVO|tUXV4B*5;$o$yF+}f{yZxSdt%SowU(kYm|16w1HJgx*iq41H$BU zcb6(AbU;|wx`J_vJvG{O-}88N?VO?E-L8E@m^3m$QgCUT?f0`TT`b71kc(wzF1>+V z^7D{e1E`4)2@)a7PDQ~Ku!YDa^C=4&qZW-@auP-ikz8?%v`jfiHF{2=w}@1#5WI~( z(VxXKZK!bAEAe%0IUDU_O(DHNQWiHYHo*owZVq~>glyqxh{mxpFaZ;QNvuFt@q`Y0P7K2p%Z)yDl4p+|3}p4*KHMWMfHd47z=Yin1cY=pUfu(#oy_g> z;VDB3nBaE1Kwgd6VzeRi3{O|uou7K%Y0q3w#VQi%Fq7B8+MLyO@!B3-5*}<)d0@`i@6Pz!5!5(Ix~=Cb<6wc7x=q-x9zge z7Iy8&GMNptfVJ4_A4k9(PR)+P;u;r4RH38T6H{CEIaHR(#@$rcSkwOevUSNt9T-#7 zuJ~Ex2tBHTzE&uf8A5E)%W!mD?~Ux5hYGS=uS)k~VKiU|qCK=s$^yM>jv5G^LOm$H z=!~%B0F#k(oHZ>%8=_k(P^}bZ%@^3H!*UU#nGxvq8eR;bBw;Fsh#f3!ROW?k^vr^M zJrDWG#y+)uM6cdH$+tj?w&9G<#>nv2*_uFmaX{adgoyB+Rs1?A)1zyZh!Vhs=D>YM z(^O!=*_0Iq1$A`U>1Cv_Z1$BMIPcr(Nmx5Ief@DVn$#~2QeQ0nUUvwX4U18`6$PZD zRYK-T`n+&xjH1VK1d8G!F+fJ=?#9QyZO`@#w);v47X88Gs5-8G#uY&k067B3qA6u) zdM|V;8jKPYGGt4tLKa^8MbW}!RE*TovQgZdWk^y38m4lh5YPw^fXlkZB9&~!1x!`d zQH5|o0Y$}HFc*TQj7LfYibZNz1%(_>)WCqbmKoZ#WIzT=6<(+mAizj`rnD=A&ef4B z#}&EBgM65dG_x)OjS+-^535wtPNT9G)G9|X6saOE21uoV!C;t$T-H!Rh22z7O0qW0F26H9Mh1$&-`U4AlslZjVCT!fgF#%CUdhtd`wvcm33;Q`_r}I&bOCm z8QFO8C7ZN&&_}uMUoUomzK9co=H(ZU);QhXVFYU~I@(OEy{FPk;x1US7A~+I-PxFV z7A?svzU&YZWb70QrJrfQ2^60yHf__Qm1t<2pNgxG?sR6kV?F8vk8zjte7~+1;B`bDA-Wg@Zeq2Bfp0(HkcrgW+q@3 zP8uIM7^I3#&2D69xgK0Fcp4^*L}uG_$qlnqk|oUs>yr_eZDNXdeSu3?zMU zL3ZD=?a!p!3?lC)(r(3Y=YbCTm2sBFZy-hy|mzH7r(+L z@n)V&yivO!>;|2&jZAcBa4U6vbd!FfoRRM%4xMed6|@`d{i5%S+AUaCu6E#Uc7d3_ zE(!&JT7wjBMjxauRQVpEBM)|Jji1#1-TXIoqO`Bv_PpEkEKO|0=BlHC9Ayp$sXANN9Et#{fBjw zcMlMtv^XJPTJyM*H`LHtPI8ioHj3|S_8S)Wd~b*A1n!Z?3pg7KD4{;y~Q{-Ds--o^-H7%&?Qo{%pApV zJ{q7js+L~wcqaL&y#8$ccUE)J&bafivJ5H$B>*4*Kmis(X~8qp%sq!|J$&$fA~ZP2 zLA)zRp=7t0XekL$004kQAS9p&B?1ft1OOn22Gllw(uHlkemU$Q(>kOEaWe_X;Mwvc z4gJaCvFYn`pj(bxX&n#5!uFQ?d~RMB02Bow;ExD?RZ*~WcDlv>W3XLg81L<0t2$MP z;z9n`HSA6lj%I_{qUqHjBM4T z1E1M>_0(_Y?Vx*B_n{|+OZOafM2`ky$(|r9UR1F@&$%5A*ZkV|f4PbE{CQsfe_o*k z(64`@ia(FA5?8}?uf-hKkug(_8cA?R1fR&o=H>c@HWopz#m)m}Yyyo@kUD7{rEVKw zZ32i|Yd`|F#>SRFX#kt_Lp;}ente#d{DA(MM@@Hc*EkJX5{&WpV@Wt;Skgres3r-; zZEYVPO_6!AUDLp5NYKTs^z?nYcGju@0dib{(ivNg))7>Sy@{Ru*O(}F0E9I`T!Hm5 zVowWHlLHkJR;VKktO|Yd^i@K&80YNXGs-ZJ{a$q%N631er^+F@%F! zK+zA!Bi>za4f~d4^fNxyn=WG@7E!Te6@t=HIRYkhqMbonhDcDs1V>qtc6-plQLw2I zO{m2KToZ2xk9sUyr`tDvk9)D8dAHv(IMb?NG>Dnm<8wdBgYRBGw|kClx7!rQvA2Ax zhHRMZ%o4IJ{pb2fO`GWg^wX_;g{=YWHfq6yTfI>rYzWb9lg^pznH@$0vEWs0F)k5% zk~qUE@*o&i;$Tv%3Y5ZIDSEU=RdmHv1*yL>?&riC?EnAwPDm+7j-kI{>FYx5AI z6YJ?YN2y6a4eq;wNg2!x8(V9X+STUXopVlN?sBMk@zhxvrqv#u!jwHMk72x9Ddrt` z5rtZxSqy2Y(S)+#v%atCb^VuAxpSxQI=_qd@rF+t@zOQ0sHiMd#V;$wmM`e_un~)L9>%E@L(7nqw569l``imr7OFJZ10_45 z%UKniU|@-bU>KDkjo@S;?VU2Lqp~*G!ZO2A?dZ6W(`#V{e97MNzv$d%~1vnUL|&wriPUd<0h@6XY;@YDDD^D!;|~ z>+<|nkGH6fjkRxwQR8bNP?7fI9FF6^7CVy(Ne>vAwpk9CYlll_z_4{5PwWPRaWlge z@?wKlqkL*1UGsyPlRDS<++eSrAHP^%jjzSM#CtPcL}f z@#EF}F^IojHTn7D@0Mm$KbZSvl%%?bZ;I`bzHZ$5{KDN|^DKi8_kFzPb3f~Q)%0`f z?>2@ty&0B?M+IigMm5%r62qv9N`-M|d1^w_m`CpMU|hv8&%=Bd8fgaOL!x+}PKuE$hem=a;m0G5H$m8J1OMG9RzdWhLpL+>=JM5)J zdZQ7wW>JMwl9^s5AnkU;?y)V=g)Y`}2N8GjSQ&^VbvEZ}pqY>$!mywzj`nonS&@x( zE(n;$tvtm-eRO#db!fD}c*}Y0cULdki)hmcWkcN|7-Z29m@V!IIa);(kow5E&^UYr zYXsgi^w`364H%>gs5xj}DnBsVz*XaIDx`AL;j8JrjTPCu?mlwyHpE+=dOo&RgrDZ^ za~H>+Rr8P|s;#{Cec49EW6*tOq@^{xGjw`H>kilIrf#9A;#Oal4BuP2>{X&zowa;w z^p)wzbIDRXu}sU1pXpqC!2>qd3(M-x8E~omuoR7>(*yGn!$Q!8j8y|L3&kK-Zar%{ z!dgAe$%;tkTqa9bM%9wQJw2axi@|D^heN_k0)wws=^RJ<(T=q!PcS{4h^VWbNAEKR z&5Saizb?LQmT$I3f+i~3VW*=!rYBF@I!1(qfO>QW(u`X72(6Avz@f5!Whg*qRuyID znQI^`XAAI4>#h^ww&$u@*x$^&PO9lT0dA(NFP~|tbcZG!JSM4PY#lG}R82O{0kOE* zlompHn7%1P2+L(-+tBtaQ)7Kzy9M-es*8bh(1r&(@t4kjqboti6StZt<0P_H*`}(Q zHSL&v z$|GdEGJ$$f!BXahma%L`hvk3{1TIHJ#97mEj#X44K9m4km53-6Aq*4F00vpkrAn+K z6B#Wqh2Yjuk)|dDq2pR$YQUi;fE`B^DoOE!AA~{%*s@Xxfrw_5!V!23_hBbTnIc8V zh>0ZQz*)maR}nPCswb|A$b+mLHN${)_(g-zvvP_Lf+{{BUPUV&KcUHK}&~qlumf6N4Uj;$~|+^Qq|-^MHx< z));mr`U=IhG->+Y@KUJ-iR_tgO~A1Um*0au-+@)Q_;Sx7&J&%}?I8WVlN5J$ZmG_w zcedCb<}+ZnWD(79SP8_(G4&(vIX7UPLs(8SBLy-l zrP)FuD9X};E$xW$fNPieAa_>a?U59a`~H->50IOJm*)?~?d5TDw*5Y~%~PIsN>b^I zMc)cWjWTPy(l9^DBGeK)ON^vI`mEr>>?3xxRwdxXiOaUaVOjEIrLSzZ6BAW9__V?DnijfAP^L32HnLr`Wdd^K(wK?+CK|g(i4|9L8YVig`v2oDIn-`cfrsMS+_pi|P@%#z! zzH+Zpj!rNQY;lC z&_#QLE%8aps)UQURT^gdx|R5_u9CBKokoji#J4@R`nhr5vwW@XH8Je=Y(KNU((bR* zGkkrqZuRC%?B214gK}`y%hEsh!G8KT=cYFznd6JlO!(YBf4!EMGUxKXwTIoig!XuY zpzh8YOH*;U9h*sIulG@{<@R^{i1p?85!CqN3wETn zp3jZd)_y79Wk#f~!d9M(!IGJJbFxCkb3Wp#KG*f@`TQr|NFRVGNfI2wk^mHdh%_ok zu1b?8$9?@e9qsD&lDw!_AIp(ygrRWW#t%dJR<$+bA&8u2DOpt#f2;`M7o!81F-0 zAKzRB_=~^%{qP?N_lLSE9%6@X=RMtGE(Z8SN!gIBWgOMhGS)pnQ% z5mqe{f&EzO7}6*nY{-6sg*V+XOeH|3OImi&cZi`_IJ6y8<|6fL{_MQ=EsMuj92vNK+sV)K{0RzPYCU%Ol^t9V&(LYZ9K%CeX=c=MK z+y623+ufI5e0|1b%lmnTz5nvxUxatRe%$)y+xB{?|IQEiZ2jN)`}X}GJpOq$=akp# zyo=W^Ub-Oneds+OJ$?KUw&j<{uOG$FKYjRJi`@77c6FVs4lfQa#C)6e-*%}2TO7Po zpQqNnv>uhw@1RG?GsM+V(UE26;fQn>iLl)bW)h6Sp+cGq_Ru1xqDtJcLEFQ5+gNWY zj@!@o#Jxrb=i2*td(y$xS9*m5&Fv2M^Bkw7<^s=w5h)83*pES{Kii zu6;5b z0h>N2R3HP!b+nsx@+7%tJGycC&VEw-sb}7PMZ-!;@9a^13=BOAm3e%gy!m38PzCo) zkrzVI5WV)Vsd(~2wTk*HhGJ0V-+E#(`dq;NUQ*O`Vu(>O# zEXCKPlKfQP{;02z>vSFF08QuX8wt{(Hw+|`x!_LqZQ)fnT8<($IM&P-qoO0(Vr4eO z)S;#{+Qarz7{9{ zH>x7aCTjDf5=vGh-CjyGNV`5fwQB94V=&Qm@;j10-;YL5JY{QVYbZ@6kja^(f7|o7 z@9Whs`lzdX)<-|<+xteDdTdb%G#D739{W-5n%x%9KLqpFfWK^Ua@9g*%`DV+vlsKn z`|DG#=V@w#`2ku|<=6J2+E%(9T6-}aUTRk6x-So^hkX2}<$p7{>|XUjM?@HVqat{0 zS%QdZr@4@4>eq_p)o*@m<*x@{uD%|5tR`C2rCLNriv*@bhMMIP^WN@ytho*kHQ#&n zN!6F}Eq%WB=lF3RKmEe`ZL?zgD67s^-unE*E&jIH-(J+|?Yre2_j#gk&GWNU-;;dw zS#t>_?b(Upipo(L2P0656qNyPIf>Moc-Ab{L&t21dwd39GK`>*B*3CDLQR42yezRY z-2}>MJ)Vcxf+jnWLTINdwx!{=m=rx#t1Aj=gEkQld1*1(!nrrfDwZ*76@-xBtsj6 z5nK+&q-1EZ(@{6GYZZyHz(m7(Ir|*;Y{oX#1s+E(gg42h^s9UpQyxvM>>->jj^_F} zpc`U<@nr8W3&RS7E$ib1xrJ#Vhu*V~lz}Yj;hJ*n;3l_GMHtSJHQLwALt&%eo~5*5 zWpvHMLI}-_-#8xA;m*8{uUai@-P5VlzpwTs{{l7BhH6#v_EybpK6}uxaa5$8TyYDF z^3}z*N~yuy6Wv@dA?moQNg<%z$aIEmABmIL)`=NXh_1ofP_`bFh9{72p@m?DarKZF zl?Ytvu{Kw-bM{tHT0cjrU!||pSwhN{=%~~uux=QlC=j5)0W(BF=B7Kf(NEl8Jxy`S z-OWzL++KFpJ0^TOR~WX)^=@?O>NglC!nL^o7!ea&?j9_^5$>B@C%cvhPcbIYwtvi) zRJ%u{kzzyMwgfG8igRzwc^9;XE-#9aepFRmyRMha`!XLt?xf1r#eV&$w(|9Kb9II% ztyx>#2cH_C{K59OAxncZuN@>cxRA?oujPentwqLoH1#oSC(G6>IzU9rI0*4mi6}9v zDi9NavI=zk+kku9g!$si$$Jm9u`SCUFwqq+tUcGW?VdRxm$%cx*yCcDG>A3TV@J4! z<@kp3_lmm~e4CRty#OEp_;~raG1nPoq!=SvomCBMZhCjHwZjPb=Nk9ID4yzN`?FOYpmr2*FrR& zBWpZu#OH8YRTG+|(jQDSW~m|1lWJ<2Gn8Q@d#gYi$~T~8By~s*!h$RWfCeyZhnm;n znTXioX$1=L#$&3y5-X@c3qc4-Y1P=VYhrgx)3@|A%J()2o z6@w~fPzfEeYBcbsBSI8#BLap9v=R-=kV3$~Vt|&EK>8dx`fXJTwP{?iDNF-0{-93- zj6Cu>_^jdor;rc*&Uiz;)*mRyr~MTiXt?Wl*?d$wC&jwNB{zG<0`P2{NTb*j7o0gW zHN)~_zTf(O=aabp*niWVK60Tb!J&)vTUD@G8eEMCJU!hFisXaVI?Y4V3$GCxGal=)r*Xa7L@o!$jHTBCIJ~p zwB(YdijM(f&MOs{vE(DE=n!OrKCg)SX+P2Nb#e}cjom8RZ z!o1ALC5wj@x9yvMHjlE{34H`$qM0EGUB-~xEsQexGUT`knM;%gN=YS#oM%Z5I5T5l zJy<0oe727U!obxp)c^w=7)nFUOc)mu!G&q?odIyBh$wtYIO(H?$dD3+kp|X;NI?VwkYY$_?o;&R7Cy3G1yh4S)QuyRN<+$ec^;`M z#S`>1elwDBZ;d$_j^NuJpKuE5M(e^1axU9j>AUMAu+8c8@MFHb<-_(hE(#YtNQjaV zb)4dUYH{7ydViwXbG^qfzWvbs5CVad-3))cP6fqqFiIE>Oa$SOKAGNW#>MpD$IHv> zvT9PG>y|+iC@@*q`Womz8)?;2kF-IS@gmO}SbNicCg@w^4z31m&8vIXg;(wGeQ-0| zbL<=6kSOM}qxZvUMrwI@IgJdwcQ5XYZJ2~+E`uD=~rl-ZOGE7PM>Ub7hIEw8+NpBD6B%dXa<%L#ohgPUc}V8hqCeeD9j z0uu-T008lQ{*6G!C{o-1E8Ww}k|iJ@fB*%GP_$}Eub+J0Kh3Yt%aZF~ZwsCLQ9hWc zzZPc^7#wxZ+GGMOxicP;emb*NMI%bn$rs-V$X?BCZnKR=AR^O{Z3=V?D)bDjO<^n9o?pXH9lX|VU` z-JOs0OY+Wxzx=Cz{Jw4;!;ALxcYmEPU$1>8*?%3sIeu2JaHL3Q6||Ao=F?gCnR&!O zm}mN>FR-_tWBcs00S}QJMw*f`{l%o=n3h^W$OK0=4khF>+u4l#!$tnxQDfI)wezz^ zTgUayI9n|<{9^(4{yU=&wV6#dGZ%6mG4@RNCD+I;^T}icj^OCm_2t{}Xmsu5I@m`e zFbL%oacGQ;=@`ccP+Unsq{=l8caQsWoH$9mlJ6?sjvjmE@)h+uVxWWHDQbN>p_hZd zW+(TS>fato5yn?`GV3!p0A$d}hLI@v7$2doFRN4*$w|_GG|oRr`-`Y_7Bh^1hP5U^ zNy^ua_$aYjFZ0~obQ{3V@{yT5Vu%?yn2`=6iFHS1>*_r3+DbRWhDKEi5|mk3R7(Yh z5v;ws@EBxW+nU*yU!>0E&BOOuyId7F{0cqxc=yiuJ(FME!~gQpjl#7VI5DO+u4}KP zwLYT&H>iV27)0Ys_{#OS15@OsmeH$+Uv&8EoQ$y78XZ^zBT&aIs)D8TbkCHWgt|+> z@uW)xG^NFSsWX;`U3VzoT_c};IcLhWxoWR^^VH)z$FM?`)_m^0ef|3SGGL}ZF5VU8 zm1!MzTZ(w#-1Ya*IYFwGhSI@7!t`?nl&W2k(#H=LZcZNitb$6*HDDg~`;q-~@aOrr z;$rPVfU|xh$15{cHd-(Z%2rZR3D|`*lk96^h2(IqK;C-&LUb$+tmUd~%Wx5aDHGvb zXxfoyTn!w?TEoBXYq+c@dCZ}`@uQUM;AelFR2S#BUxuS)Cnd`5&;G_qHmR!dGu`*;<_Gj;7+k>O>`J=pMWsQ7lf&c8R4yKy%;Hf0*e%II8E^kAJ3q zEgxIzH|Let*YADwYvuG8E#EbX3|KR3Yp%Q-Q`XTRad@h?_q_G3f21F`!xqTwmAv^LrP+dHpy!2Y3W26oC*OL8EeOB6A!i zD|^t0!PqojoN8}u|Kg^#yv84$JU{(wZtBl%I5Cz+ln=D`lu3^$XNdOay zfM%3MnvV6esGWIh^0cWcjJ0)JB)t3Z}>=ARU=-$Yrh)=zbVPPG}H}I4G__ zriXxS03#HHXq~J#Dl0}QLyF}jjbR(+d6F##bU>s+EX2kjFSg+zVrnw#hFYWSIR+Qf zaZh7y|FW);-q@;-_4{x?GmcVphnI0jfR!nY8Dj)J$bf{d>8fvk4@_Q;N5 zDF-PX?IC1+P{L_JyXEjI6r^eG9!k~wd>x-}{=LNcs7XUtxUpG3HtKrz`sHqY0lm6o z-hA*S`+d--&Wu}Hmsg52n^ILB&N?O9Kg zonQhbRgxRq8`uo}Z1Y0! zxP82fowznqsWfbDGmtu_XMH%5fZ80hPe&J;Mw>pV6~x8q{;vCkA^H@I@eCAG42J|y zxYBnR^}zQdkQ)0DI?! zAPzTxg?vb6ah3)775!fxU2GM(J_LCM>*JR zZn6S{LRy-^A_}upk6T?Yn{-TF!j>T|rn{|!(^P5&ev)f~3N!{MVym!7uv1FFps_dN zfSz^IICAq5ygFr1U{I^f$Z zgfNf-CY^L#DWi8=Pr0i)0AdLsx*#%GKxASg4NH!k!Sw(bTZ>Ij1qC!fq(G6+0E!v8 zFbJ!wUmOdR!MuqmOb)%0q(aVsQuHQYtnAAe2}>h_4W`L@;EqfAJ{-$1STI;7Fsukm zB*;P{h&ey-O_C)~^3tp!?2!f5Gg`BwqyRCpIomu-2m^oCj}r}HK+RtA^ZAM2J6^hM zb0kOm1;R16V;7gWQu)-##A&_3$KRgM`#Qg9P>AjHvyFKcT=;2Veg3*$*2i3Cl^8B` zAp{7CMQ=wU9U(Ajd6@g#k_i!$hA^FWH zJlJSMVf531d5-R#plu84dx8M60^y^ftYnE|`?6uNiyD|TCShm^GPt*>Wi?<+TET$njW-DfSVrR^QKy{+Rt9zU8@veWg^!X7QT$EBPU}!c?EW_n3 z(b$y$nd0n)g5zjPM_4&y1uIC#(gHdu(+Lw^r z?h)m-n>ph;&qpa`HQ&ykwzAs8fB5|I4?q<|AcSng|FwVf*B|e_el`=~`Q>WdU^x%{ z!uo`IrM%jDd`(QN&0e^76-SM=ZPax4jCSjdrTw}pP=P?mK+piA;Vd{26*Q0QnV{S; z(YD>Xjsav;lwK+y^a}aseZ1D)AFH?Th$0ELD}H0SiyO@tOt2L}z!XAOx^wx7%(l*b zTQr1cUad#AOLp}`2b5z}FfU$PSz}h~wKv%*1Bl|eS1 zV+cQBy9r1|sa{Qf(ql}3@Se6NMUqGYn@j(I;rp{&dGN8k>y2BPWuQy))>SXQwnWKv znbshdt>v|*MpTOcubnSbn{mSdDO&!Q(dY?>oY>AexxoX@0B-=k<==PdL?K`a`APNXT3P*b3W0z z&67dn!z(&x{jz>?`uWnF+I!9X`&4_j!?%AJpYQ+gUGiKRNlZ~u(iPUDbmX`j35mfd zGV((scJ;i`Rr19ouhf`LqoHAR)DUtj6%h&T4}^qeIS9Xi2*-bF>+k31k6&>%ZCu*8 z#qS(loRcLda*w-3M14eRC~cD!UbSsmX?Z=BbY`8@am_2pjyOMVzV zXcp5JjrgHM?6o?{;#`uFcWxkS*EqN8shm53A${=<{>_RF6;J>0KUh$r24`@zClzv}Ague=YZ4tpqJdy!d!#t-a@YB$oxJAxOZbhoWqP~HCB*fPwfC7VXsh6!>r2rs z3J*I;gOW|sr#bg>%jabjGb^wWBqsom7(sW3i41g9Fcv{lu^So0XQK{(gz!i+j@Ywa zvcDgZ$u@bcDpQdTj+z~4P-;IDw8>aYOX1q=-S-|(t>5|adK0Vr*lvh!Ho3Skp74f% z^r9d6HmPeWJ}QDX1FJ+rLRmP>+K6ak1l+m|S>)JJ$WFywbJ^6u1EdEn}8U$aA7C*{S*+{r^7I|I3+ogRHv`{Y4JHJ%4+Y@tMc{cFq|bT%%6O zVD0z)lU|=`Vm()9c&wuntS)lT8Grled9CsLOE55lU<;2OLuwpfD0Hb%@Wi^`&hu>^ zMSVo@T0ZLKB65O@xi|GVWWS|Y(@5uNEoKpoLF3s_EI7tt3-@PLk$AYs-7HP73koG= z%fNvi%Z46h^ANHvlW*d+3Ha3Q7OAAevuqI^OWf6&3rW26O zBW+I?8Hadq&atjUHBL}^0#N}n*ba^ZM`S)VKt+lPbQi^--bH1mC0Oi;|Go}Zno9H?x{ra!)()R1X?Q{LR+S|L6 zcHPL}?Pg`4o=R&4i&ojg5HL%X&2nOd0F(rvw_0hYducnhAs=M3aSr=lTR$2JFJC7u zq_jljH!((F{I92fidlF6E7$> z&*I#G+awvZZp0Lib)PFjB`4ZZ`Q3h3kdD^7ie$&@U2cANZ-7n%&Ga+vI+Zrz+3K-Z zYYPOt<(&dqG-rDk-B*kKjMQ2EXN7G77^Hd)YJh71Yw?Uz`M#?ym{WV+w@Vm$awvjl5G7z?`dZ ziY8m1%3&5>qM-^%_v|m92adfL(~eWbZl~^Q%UTKbS`%|VPl%+6z494gyiY@-tD9vulF$V?w^R_>617le0L zs*+2J%6tuJ$sh^l}nBqB_kIpke*bzzM(%EDjoy)5_bRyXX-4~oSVomze#-BzH%Y|1vV9*$$h8VZc z>CPdds_}{M#S48wB;L^#?b={5iZA}8$s?p{zR>tcTln&;`Pd8>4&AG#tNw?3W9{17 zWO=(1M|~K6e);VE_3Qu7Z2tTPm`9%U0#S zjO-&)SU>RqjL3Kb0+*--k|gH`Da%VmkR&U3(auNIL@+4>eM&M@&@AvVhqSR^d6EWwSnph}G zY$n0QYWp*b^3vZ<6V~@Fv(Mvatx7#Ol@d&tL$Kk0tA`4H#Vsvv?tnPpY!^mzhFM}L zoG?S%XD&viBwpJ83I2Vt#amIqb-Zxx&*@s)pj4UAG&sWylqE;x)=^;kQk=G_r+Cg$ zz(uc#$(SwLhB32gXPGvcrKd2{b#YKHE0ZK>1xIW?I?qHr?sM;2j1Ffqd5i`jMD z3SR74Q~1VoCzG%Zg(Jtx9*~=54O9~jh1fX|ya2`_tkiUgz$mL~Tu52ik(e}d+sB!c zVQrt8P?AKOvS2Lo#mr#)!bn3xFtTy(<|GqYG+8*86D<1#lUaZmW`u(o5j)?X4`V5% zx@PJO2EE{AOz=nz3=#<=B!&>{T2#tnDpZMPMMf5GYb6wc29B5{k%~4s8*?UQzcrUc zUVZl%{T=lL)sTB(a@BTiOGxtOc4N@}UkcigpJdz3-QMi?#S-l&Dy*oM4ZaYgyGK9Of z{Z<>x)n20ha!5T!eZU*q)E`AxUO>uZzpQ$Y#X_n`(cOr}Sw8YEy?lwMi~GQsGgG>C zXR{}_8L}^cL<$sFFmup|cX0w$SFHIguJHyU@nK zFE2R0{t&R5r>ry){&fBLS=AjL@67N_9j%V5JaxpXW4QTCU*`)wn}Zn7XS{t{P9cx3Ibo%eJ&pjv zNRv)iJ~<-U{^f(?j}`t1h!5CqL`^pr3?d027zP;vwFsuX3?~L|`fKg{^;&iFRfqAx z7nlm&g@&RmtkAhm1#hUAE zSEsL;WF^0Lcx^>q+sATq=FHHeWN}%CQKR4Inia%HF%n}FV&#ofM)#@J0>^9J&LD#r z!M^#csI@h1vp(}1`w6W$V#K%bEr~X-(iiWBed8lcV3+L0KH70zyqmN^laM6Ock<-B z>AeruxQxl^dfgVkDgV@+XZf;N58lM9L!erd5|2;Lh4YO4g=W8yucLS9r2fyi{;;D_5wLqKW`-h5rA?sT~_OJ##fH!hjJQs;lH~vKSA!57BNL z{r+UWKmJG8vqtysoGvr&cF*i`9=`sB@6R;8V-``0PA{cTOn?mylk0n(THUsv=JP;M zqvOux^0iIO|;Y7BvNNziwZ^G?u?HS|Ei$~{C z{`OdYYqIy{c9)(*{I~g4%q&vllMb|dKac7eGPBo9WtFLARJIs8r!R`iqq1%>qFTa5 zMz(3!ivb+Aw4}zzd2`ge2s{IQQ zV@q~B@HIe^q&u0tweW)6(I!GYIue#rBq1dv*`{AQ zY)+{)ACL#|c1gEEI8p4DI3|b1L}W@IK`jy`N3R2x+Yo5!b5@{UOV@^3@uHp$>-daj zn?bQ)wO5Z4IzV&zOEHu0$*)Z=c6wCn2}BgZBZZ)Y#;f_tD(ei@{haIbI;3@~`t`Bw zQNQWrFahgKu6m9A{59@X%X9A$%}22`H~f%?1Ob6y-siz%V5B`5<-$z{Sg)q+VQLU3 z%_(6(8pDZDOJWz6%3N8wHLo43q_tOV$~7V3&W#z!o=U1e%M!wJjur)c8$G^%TU@7E zllv6}#h5KuS&T)tj=8VNv?y`6ii=Wmrd@cHHh9AGW_*3>ye*CP`U*BV(#G)jC+OuT z`1Pvx)WurpN-A;g^XohKJj-Xnl^wWqsydanZ|7=jA(!WMmBW*f33IlN@hJ;5%%|5~ z87&&_4*T)bLB)NvHs0uN1*bgS7N&Y7jYU>01|?yL3SyCGBJix#G_7Xq;0zPSk~FKn zPct#KG;S=OW=Bb=!mzRK9-R=+o z&~>Q$zdz6CeN9s7@Jne|yOT@KwRet04EFD5>mBL{XTa%p_BQKrajd>67boZEt)XRv zHSt1Rtj`;>9%ZrK#@4s>>htwG=S=nO%G!rKGaO&f0gD62?d0>v_bNA}FRgcuW}AnJ zm>Rp@bx!A8^f@!qsQ*a4VN9}xU}*s>G@6t|}3?BN`wC=fZJ0uOh2?)_{J$ zve)yVj}-$cO~Io9%5(|Y$T25#B_O}~ zqqxD2ps$C$jzQCiC*pm~DVoo}tnqt1!jJ2`*+p}S>Rr+Gpk@J=@JpY)o3?GN<&`=U z+7kS1>NTVPoY7ZHm#NPiRpo9iTn+xXHNECv+}+Yc6P;L>7eEn0`%w|>NIiFlBOuYT zqyS+5?&mH{$cljm zuBD%0Smo5P4Wv;kHLmr8XLBrju}X8bA!eG5p2=C_3ng{_wQ6T+sJzR-Z1juKqP@bySt5*dWC8dFOpNOt#k*GSi)#kAs?bPyR$tG0`wr*OONEKD|5c_jG^R zaKWI>bE!xmCPxT@=qK4v8MTFoep&iry|;LLG0WafGeXlUMoTu;YGrG% zB)BYx0h~!;th5uEV7M@~s0aswHJ7Bxgy)oV&o~Q4OF@v;4Z}#8Fo6L=hNi-nBGPGtf+B$va$*=kUO*UWAcbOj z$0L_SU8aoQDdX$MvjUE^oGX$%3eGI25CSb+qUMHr;K`w8zliMv zVMo06&A>D>>0TNbbZRIyGJwrG>R4jt6Ioc(Yf(~3k-{Zmf^7!UNdeMiR(LULb0!LW zWfeG@&!`L5LdEF%s@}tFU2n!h7Kk$8lawRFw{7%+fD(_9p)k%LLiTmZMrb^v)9GleOomKZV; z;6P}=R8eh%gTn$Me3)IVQUhnW_7+1~oGcdS!ifWf0iYojSqZksmNrBVaw3T#5m|`owA3QhF6j+rcAKQ>~=DqWwL16m{t)YEjDzu1)*huk3)LOWpe4k zs#dOH;N*1s;r02IeDpYZlPXj*eRRg_9PXUHvKHif$2-;i%z>J)60Q+65-GY}cD59| zonociE_&v6PM@^$&ew?}Hb+sB7orqil$$rTSV>QSyd7V^a9o-t zT;p4Rl)tcrB-MqZJARcFY2jWRJLaSqSL_N#LMqdC%!KU&-P9{eZy4BTpDxi?S1sqA z^Gk8rW1ZD4wFk(i| zYhs<0xjx_8kc^RJWT(gypuF2ZZu57!u#}uSW5uou4)z-x&+&(!-&&nqJqsCinY)Tr z77%r9tpT9rx?>s(zrB8YqyJp4FO|Sqbuja%ZMf<>$CW=GdfwFAx4r%gf2nw=l*O{rv&rJ{7y&^JC<=ojP>}{E;^dgC_c8I35$BhP-m^&p9HF`# zO9dI=NVS8t`lbH-rY5F8)|qCQF^}#Y2j!#7+2RQVRZEm*bX-AIi#fq-EB`hC?*|A7 z!UhgtT6@JzxzC~2**gre0w4gu{hs>wJ^Wg4eZ7&tgi90J?g<8aYVL?8Z9nI7>UvLK zRo&%NstC;X`kbtl#)6lk);>?S&ZuCV{$1KgU`=)@&{2Lt)bZ#&dnUX&DD{EsCE7?|4obfAN`M?K66^{KKwvb$8C;e9!&~gysU}6Y{G4D{HHz)y{x;+yu8QSNnY=?F-Kvlbv7t z@%i<{JDVr9hEJiDt~3`{(gw;upG07)`gO)1!^drGa~FPcEq^}SsEJ6{&<15ijM+y~ z%7T)(9PQJHO?se480i+u$wz{wC`gRFV2_y*w^T>L7(kF8NvI4tMMT$hz0d4Oa-e^_ zc_~uMK40n8WPgX6f#G7?m`B>=xLJkmTc{1<+OeP0)&PAi@FtYq6OL=S?!YBlE|X4_ zf+9pHVYQJuk&Vy*&GYlRki{c!i>A9yyhC07)905`mfXLa`JkRPx29CuRk|n3aMS@u zCU5nULxUluVH;(osBZ7CCU5TOt31W5-7oeObnm7mqNGn8gJ`VcC?wz*KjTw0uMZ z1f&jJF%oD{tSFApBzNs}zgo^RlahSqgL58T`;%XuuTJfq{vtEQ+d1hir6%h1eO`2B zdDKo8XON1Ud|-9JK!v4FdzM_Auie(yHamu#x|D9akU5`^jf2ukz{*U?e#8T>Z@38N zYVmc~YJh){Qbd5V7px>|Xc8=%fpTTC+*S<**7mkLJ5zS4hB;$Pu+waOC4C$-L$3*L z?Y5o>w{os=1NQVUO@6VC!}X_VNccblWMpFyuNR&Kb#7(l#-4DN0kEgJUU*d$Yqj^a z{d`rv-PN6i3kTI4Ug?8scbztFsGe>?PNf7>i)D$9G*v5i>qPFk{yJ)q!@KRWspW^y_i*91OF*V%Yv zpj0&My&g^8-UlO~VY-HC`}L-wqOKF|Y49#x3D0r0M)d;YihxYORw}U1PNebh!GMcoQ z8mc*uLbxTQ1w-77DG`e|Yy#{@>SsAf(t8syQ8aK}MOZ2l=rsvbu!-82Y zuq^|u93C8tae*>aOeHC|y9V<$@XG#XR)DD>{ zDsmb%CUdZ8Cg~Mk*LmaM@xQiF=u;q1lzx+6zi^L7R5qv?v?3aM*? zu=biwGFpj2)kQU1@L@&J7Sj6^rqTNie{Km&M-8WSKJxPRj>MB3U58{7ikrJ$6LO|M z!F8_pA0Exw0?$kDm&*QOLOcBG{p|EndDcHJyLt{-Mv)u=9Z0q8^o~yDPL8X=+w(JI z0s%w`#pInj9;NS|893Ig41F;;k#+w_=jJTU?3H4-pamL&kxm4qgp9Z-3bNs% zZV?k;#WKGwkf2aQds4y%0;rR;XIu0rY*(Tp3uXZ$gwWHh8BWlX3pSnz0yNYVtRz%4 zKUn~bvJE(>u?j)zX>V)V#gauv{9!W5M17fKL0G*O`Qk)sKmMi~gG*>qZBk}&VHv~)vK zNPrW~%%)acT+KK{6x#q&&RJ5~bTf|xCPqQoCY)0=#T^D;RMt;zElL*riCKXG6iCqv z40AS|#$hMJ8FI})Sh(z0lizG7Gf zr!e4%Tv$^L(*c+nJ!{UVkZ~Oui=6{C1QZt`O)MCIV2m*53FIPBGw3L^7;`2ltsZ># zKBNu7tn!ltnO01IxIl=_B1BZ8Km;l^Mx(Z2V-^Lx9^&VYcB)IrQ}5;-U*s0W1`N6# z05X7P7g&i%X;*F?KGQk2dj)u4jTa3z+iYu^5#pUa`W<}KWUlt};PmOa>S9cy}%ET^JoE)nb_SFLZzRGGb+@?JDb#+OUI^Px0!L{B07Q*TAw&hiQD;=Ci#v5WBWr7O*_lEV@F;hW zn3)A`g>9PC%K*DDRtnV$tHbk~P!#)=cKwGlZT)Y&L+0VB3O*hD_s7R zC#G(~`1PKvp8!ulu)ou~*(MXtph{7C2Z#Uw0SE!niVlE-4d>dgUvs^VE#}ku7_zZI zl2%UNyyq{H;asu5K415i-@cux=c~v0B|kbSuJ&Afp2u^%bqLfzO=AFUQho7+`NmwO zS+Y)COtZbFI-PiGa;sLa{OE9sEUvh@wwt~0eD?6971L{aP)K2@vz8FB#KgFanwX1e z0=u$FOY24l|KYjd^t=Dp<6+c8r$8f&>9`QxLCy`OtV z%zeEC49>JcL7M;r2uK))y1%~N@xLqZNACyVwA^;V0GTDIPWdsfgF_*qB(Na{5W;M| z{vmii4|)CeM~gy`mQ=RcDfP}s$nX1ZLZa;>~psb>%98hXHuy-G<$4^HLI^? zAD{=wdw&D{+4XhOA9$9fYzWQd`Qh80t4pD^Hz%Bm@5N1?N<}E4qDm}-L(M2e!nhd- z#6+8{$G=QpqawiDfZj5N$vLu5cmEf)11ap1(Hx)$b;O184szpIV4F$$=j)|MOap9> zwn^jR4POBrb_(0(R)@vYbenuSxI)HEJJ6Wh-5u3*mK)7wImP`Y;w}O<66!X?``-k)Gea$c@g4KJAnK z@oA14@9X{fVqa+B@k}$dy?4A^c(q3K*L?~ zhG)vXYCi($5?#V3rCmgm(V!mStLinEK%*%s(~nHDInp;xh@}UFL1jf$V`qjBWfvob z_}tsy_s%mC{n^rOaxE((swXeaAz#$V@Ve)pq`D`bSoiFqbE$o1Oq)4_q(rWEX39ql zl4RH(`$|9v=61T9KMbFTJdHd3J?Vvj#Kau}ZCR^Y1nxjIZ6Db)6zOW?;VB!M8&v$+ zx7u15RXZV-(=NibECLO;y2y~j^z!%$kJT(zoWUF|Th_Yl1)oWilEgf!Xuk)i*;l@M zZBL?1wB-@ukU{Oih!oVQ-HsKXCL|w1jBQ(jcE{KxXSu8LoY*Qp{Q{^;zcvOSxms8L zq3Ig4=G$$tbUBjR}NWHRH9_ELzFI7^VbKa|HH(!zb%;yrWI8rEooLfIpTHiX<_(-($4bhr|>!pv$~-v^Vy?U>Z2*&FB* z3ErkA&vxfk&tBBGuQgEfqkdsOR&Mb?M{eop+XrmT0!!2*b98uMuypSINos?VE3WnefRkNYjD(+DE& z2I3HLlRxYAMR`GYk`>ayq*$ogIeR*(UN#q-+DgP$FZwX9-jhtPmC_0Hp0q}Vo|9Yx zv8tA;wT<^ZWo{SsHq)+u8~K|k+omv1gQIG;QHKrIS`|(up`}g+mphdjmE$9|?P_#j z9C5j9k75vD)&p`KH7%o}iB1GeTvq*qX#ohqNdE`_y0h*R&Z;`N)CZ}OXZx%7y2A4~ zvoE=X_g-eb>~^9jSg&N=uNR;APyTTJWGi>wpN1UWp{6o$t?lNd?ml{WA1%=K#91ai zPD+l?gB!~Y8FYunR{qJYITDFIFSz`MI6sanedU#XW%4IfmGfaptALMJeBB#vN9z(Hw~{Cx9zLC~`s z-8z<14x08dTLl?%^R;oUSEc6ZC~r$2MZQ*0Dzc*@>uJ?=&|?vd$1p8tvpVxBJIjcs(-p+{v|v>xosnmvqUN z8Ibukj^g+h$xvDXo*%~JplZ~OhKO`aHMGQt#tMa5?l-cIo8PJ%^7A-|GyA-FjOl)N zIO4%f_ex^GN(iZ|X0uE?F_~B@D@2eG(Zo;r537BRYrWR>YBk%?-l=3|X>qjp^7muy zM@*@)zIqJJ5eu}0s;1r+w=v^!9JvrK!r-+#ZW4q+KiF=1o#Q?s_olzM%TE*a)V^G} zhGuY>Cielht+~b38A-VI=J<;V{JPcjp_4gj#Lzm#n2DZGq z6O(3JDGH<(nalQD{Wk+>EgNTZW_552`UJGRyH%gI*jH7%8`q*b$`!TxM1;^fLRha6 zj+%F972^qmOK#`XzIE4;TYU#`oNh`KjH+yTf-xZKL1o4qqf;ZRp*!nj97ZsT(qZ2{ zsn@kdXpd^{E_u$f`Oo>qxL32A%otyTotx%zW7LhFti;0Bme{NL>{(;LxiD#f1nQBb z+~7A)?D1gZ3FYpJ@sZvE%^V^_GdCk9+6RD97$3Pq+EkCDM&d4Ys`q1AXWjaD%NpVJ z7@$oseY5@+r^X>Zl5mJ1siCfRrW&R>(u)Ebwry!q~GM+g|7QH(x*K)a+o{-^jCQbE8r3^=NK^SBFL3f82lGxxU`} z{*NnNBfZ_!WzEkzM@s#<-fj+f^xW@^^Bn%=^G^!BI?|Qa2s&w7$7$D{`AK3t`o(&_ zp^rtSKj+1rjauFzk{7q{e6VE+6gO3vIt}TLb(8uLuK4 z+_TChO<~rsaW*8ibSKQ!OlorF4IiC`5hSyOw6DV89$fa&DT{D>oVXEnv# zvWo*(3k_IsCqyhk+A6U?0x&S@8@-SfcLItexe9?F)%bGTZf8h&Mi<5zW}s<*hrgIt ztWNYnh(#bUW3TR>&~ynGF3qg@-X1F^cs!{}QJKYRg$x}E2I%9GHt-e$p>atRcr!*Vnh7nly%h2 zQXugmf`BhJ02DiYBMlVM6lPK6${ACEqi%hx2h2o+rAGWxD4GC@VjE$Sf{<`7n6wYB zlN4s=u$ku>bg$$Y0fF4uH^UkPFo4`R81RwN%x4=lBGyfFvYrvxR@ls3Ty+%=_ucjt zI3y}G8m5}frDrKYU=jvHv)EA}D|5*N!U~!yO9*61!FDtPuEA}aM`17s0cZk73@k7N zqS7ctqOj1q)V5yGdbIXBbA3y$Rk%pk3hBaD#BO+-+G%QCZ8Xl~eK%@hyK`&DSFFk4 zIIh2Xel%K7@S)i|EqjzwoAvk3d(w+2#FF+~DQ+=Z1CI_NL4vZ-d)iS-tukWO+;sQO z>+&oaXmR#7Ybhna9_RGag*_&3V=n<4kvVgc?J?I4og*qT0?oPlPm2M>#TG+Pa^c%rQub z1%K(Oe6QoMjN+=Z^66&=2f14a>+F`;wheBwd@iidq&l4ZUipsS9AQPbh&#XhcGpvA z`h;sR07z&u7B5Hu7aGXUW^!%6yn6mce}5aL^-qTWnb+6P{ZExwpJO#OtEn>y(}s$C zCvX31j=8lxYilkk-jKCQF=p}~iBGsw6@rbBl(fp2tBe@Up>26~uA-)j>WXLEE6k+&x`jAMY{=PC_;fElmm1_c{8a)OgY2LYSn184l}+wBl~PO*6Wr7 zg_xu?LC69PHQ#XO2rO<@d^u)#s*0jnd@_4F)U1q1c9uuo?QL3XCr?8irFp2O+TP-~ zle|tV9Ig-e)5n@9@(BbIfsz;C&PuVhN)?d{LL~x#RitnF9eMMc^@UC6?5Kyf*Bzs# z2JDMeny%*&Q+pP5EL2l6Ari7U0w-d?;+Qu$Gn*@4Z=)C4yBwjTkb@>;vM?n2Y5Q8M zSMh$rGHw(d9`$iNyP3#ojWiM6gmo^&pizvlU)Yvi`X52*S_CWU!VSKAY@Yws^}pkQ z8DyNXE+wF+K%I#_cr0@bVemOm(usH49YWg?C=76&$Qc~9 zz%BFRj4MzuJC&uP3M|#<4d{8m@kzaPRZb{}mr95A;q0J9l2gy?0alu5_} z0d5T1X1ZlM(G{)dLJ|NCN4&qU-0erE9I{?AGw90cnc}KjbXHxxjtYFroK{y4o3sK( z)|h7dycIWkY;mt9WWe2{afUBR&+NuN4c}Ac?-Hb*xCX}&5Q{Y$lT+fJEL^hgdJa`#WfjGZwd(Akek>-ttc9^9 z1=6~b)COVaP6e|#c!7v415tSp5L!c)wOD+QPsg8fb(#gJVXZ#T>rW1TtsVZ9`Di@{ ziM#juBzds+%76B0dwFTLR*twp|LgznNN-rH&0j{D7x(O_y52Yv2v})S_ned zhF!YvMwHvx6|L?f!b?764H9c9-&zIuT=u0lcj#7Cx)rudd%pIq>s1PI78V;Y43y+2 zxZ-$QeU;(NY=kp`SrBl;RK0}s@-kI@Q&l2Y6e(Ku*JFEnJl=&qWd~>KPfhGlnygCC zgU^rAwGT2bsrR?UU&ek2!6_g_3TRc(Hpnfks8XdprQ=~I;JMu`o(2y^l7)G~>aRig^5gTz9TDrN%F{TlN`4lI-a(U6q6Dv#|pSf~tH z&#OmWqzh%E>zv*6kwF_C&+rFTb8A4#wgC!}w_ckSE*F-2qa9hZkHbcpf>oZ1fNEh` zkN_*#l|vPP)`hB~I;N-?E};RY0FBf%FeMCwNJI87spO_3HU`XvLx^~!0)%M)va1hneTMR$ELkEAWgu`) z`6I{nfHCc!oEBH?-4IDuiSP+)q(<*mCe9$k5^6PMh0MxUgpU^IGtbs&8y7_Aezto* zuD)Nx>stRSMXN`;1kXh$A;2IVRW4-lSj z%;AC%pUB-;9WdgnodN=U-92IbuxvFp2j?d|&Gu^oy0VL9JJM*lJB2w3UB z40s$<&fCiRYqb2zR?tz?hj)B-=pJP+z<|@0 zt5zBl4H|VSZAE9wc~)%vqd{aozY(jKx~IbNZiO;L8iIXU@VeBNR1$vOh+y}*9>;ud+onKkVT zP}kXNt@j~^Q{A!FErPO-dPfbeOvG$&T#NfFw#D$l%_V%}1EmgQQt?H{$3 zLPAKzIrdv9tl=1jfmg^b$_vRybY|wTB@AOG8ev8DbgHY{yJAe!JM)TU^FQ(AA5QuY z4;MoqLyN66FqC@>OVT(Njp+gYhZuaIPDPt zPwPntz~K9?uz{j$z@X1K5P)&I7%W-x5>G>$UbH)Hy`Gdv@E`yR)24xej3t&rnn_s! z#m?ml7|57_5g88`1Cno+3$1V{A6U9-vc8E!kQcaf@vUI^Lf|ub^h%uTA#jlqUQ8E- zi52zx&9(Nl8iVf;iuRf-M*ziAVd&d#Y_P5M{pm&kRy00ksME}qk!1i!rgP_sVRFHo z^>|j4sU^*Fw}EJd=fgHJ`87ZMSN%7eKJ);^$mr7tpHwr89(eya@RJ*isEU9E7FIZX zGiD&BYe*zwIu)8rw7`MfqgW8wke~F#I0a3F|Kf)O@V}GUiLfW1`HMuW95xcBdnkG+ zD};FL(~4!aw!x8_KK?tEo~TijySSc+W|jFhpYw zR$D4L3re4GJyDeNQDU>&Zfy=UP);%+vI&7!R4YiZ(4wRy<*6d;NM76cbyAw0 zK@e9BI@^IW2r#SbM8Ye_ORWND8oKwc-Zko$qq8rtFLg&?OYg{l-*}%zBo`b=u(40b zn%pz{Z%O$iPd21y!b3g|93KEe=g%sP9Rtc zFJ}KoEdTURxbqM1Tz}Wv|G{_GKd$fIcfHO3IOl&8>-VqC*Y)kO_P>rC`j3L2>U-Dq zcK-G=Wo4bp{9Nk}>Pc~;(={-2KiubMRY$zFrEXO?3bSzkDc9dwsLJbZ);SQWmAmw< z>hrZIM1V)|Y=~0KQoGD9s?CXyTjK)Ve{Jpxmy!RD0%1_EUnc{_IcHwZOZ#E-J|V{7 zD_IW1ME1Pj`?V!!%ijJIZ9)PeK?@Z{M{5Ik-Y*yVDAq^L_fA~~m?f}-Wy{qOE*C*@ zthK8OzORXans-UW%WucyqrIgke!K^W5BPe+*od|U1OU>60B#X*YLn;%=m4Mq007G6 z58b-*8FS))@`zt}KD_3}P$R03w@QfDswvn$5jli&tMIzIY}henEr@D&Aqw{!SLbuK z$vHcErD--QG8I%jAth7r^6v9k#PM?9Dk1b%5L)&bZ|GVE0yq*Q}O$%plP|RyDaf`nE%%A&5dN7u?li~e)!YT;q^B1)623f|5|?T#!mz7B*QUg$ZOXy zpx_q@TFYsf&y%xP?q^?lKDk>g*B!2Pe&WvXQ=f|}zz*j!+)#o?D-9s|73>cH4S@20 z9P;RVF!0rC4ZZf0<=hZLiprV1e57`P%1Q*KoCS2#}Gbb*oJQ*zkiIiAq+IL6q#3YVPH#_oZ zKW3(jac9%z(N17t)g=)`<(s1|iVRrf)x6kM1i@fEzG{58}fLu^H&E7yON(za+*AL%hS# zXp{t!5^V{L83%OA8Gw*94QXmF#O_QH+t3(##7C>_JNsB#p-CU&Ayi?-{1*93dr3k= z>-^yXGiKCaQ(zFwnMbpi*BV-}l8bw!ixjVJV_CDpy`mACDTB9xzzuH+f{Tv1#MT#A zrhY60ZaMa=k_Eo^pJ7m6zQll zG9@I(2oNI!B16t)d!icRk=m#!kV4TVY$0z*fJkO>CoUJMlnAjwJb4zD{7_>SNU(%_ z>g8ZddqxMZi9ywq-`twOa7YK%Jwiw>o7lUNTSWK6q)sG${I0`cnV z;;&Ft(nxibnSJPiVm>yvu|Aa^*3Q&Ade^b&(?eu^UK)jczrn8=r06m_(kO!>7hDK4 zFt4`~5*aV~D;bGV!F#pcxS&0&a(lFJ;p?!<2{RzfyeBl~re!+G=G>q+6`&qw7I6Q%5yxJ*$92gIbj*HSb=sJT!mljimWu%!P4eMUyxR70E0{p z9CMXoljsq(+XY*X?ZX-~+w!+>lC0dub-5pMY;60G>`D}t4E1It_@j~WPp0um=!*|y zy@&A*CzJ_S39gwb>}M@q+UiUn)Q68vAYqL?;8Jx|-21+Ik(O*mj*}0s-p&ZH@5ka#BbY<; z+uEOEFIy&g)U#B|$X->6vB?QCV(Vu1aFJM6O>-j6etEa(w1tm8j^TGdnhoCR<6Nrc zavbkjmv6r6L5u6fMa3$9FDGbybC|sSB-;7h{mhebx22&!u(KCt=knb4n606J?6s}8 zLhzDeJgilbEy#%Wvb*>w)a~I#XfmcJMsy0Jt2FmGVb}espE0f#tCUbiyn3#QiW1(B z=@e8+Q7%WXLan+h7TyDEcZ;go<=t*3I`2pSo4|p%n zmwgkzliWf>^%ffEoN#E)v%EIq>eLl+mT3Ckf^hc}@5ANFRm+|Ci(SQCmp>QdRx9Df zwtlU$T@q=kJ`xK0HtR8)N9>2nsrVnPmS-ghZ_eAN(an72$Bna%?0ahok6_KF>u~<^ z*#{Ocye&OjueS=9d#mfU^{prSY!uJlSMUv!@7L-}y2Jl}RsJISAASWpft^Y%Rl)6K zFU}GDT>5Fd_vX~e><%tLZGm4?UL-;U#gq9vwIMFYhwzA>y)zPt$F8rlthSwr(i0lX zv*Ob=@S439^3EKMx38tmnzA@4;M8Q~o1R*#i4CJ9+GE$aqp8Z7^P+E3ZR#G$Yti7cf9W5RX&HA({z^JARlXc8(SIHEHG z(?4hYo9_QvAN)=V--^Hay7PPMulwGQ@5zt*b7pm{A$=*2#d=-s)+ALYVdey9XYq@C z{c<~d`lFvJ-ZCH47QB~zilgCG6C)aP&Jes2jnRNLG);*$-9J;q2F7ut0M(5`8H~q) z;dI~d0XCu%I@530zAk(T6E!7dAbCm)cEK45B1V#q7a9&`6J+Xc83HKS^6!!r*S)wl0UeKu?r;Zrd2G%Id;s%O>^wuvf$O8=nGB#GFyEjj36Qi|_Ml zq!4o3Vp*GuFWOV#nvI(kYYZW0Gf|>N9Ul#qT0p)fh{}W}ENYU9#BdM;8=Qu7DgaHZ zCva5q{f^P>)jDhrOtOf|7OO-NX`8JSS25@!Dy@ZZ7XLWk`0XQpv6b0luXL2vwR%r$ zo0h0o`8isaL5-iQG*b3rU9xhFhJ6v|$5Pjn0T>JQ7Coy{`+D~U%Vtu#JvMs|Al0YuCqU$0LPE$}0p4Z>CialKpK?3;;Zk@ok$SkOUSx9P zTgKgY%|}oU;qG#nvS6xGDB&lTD;KYBd3)Y?0>PfGs$!32O6JMv0SD>C8xlDYSRu$& zR3!odJVo^+2GVQq^kZ%|EdM%v$7d}pj z)_9-;_yo!^Bg;=$+r5vNLB}oZUXy5CN-Z(%9QJXjVl{fe? z;CA7o;^_S-V&v5qPzZ)1fkbzY5o$p#s6fpC0RT|lt;PHp>-BPDzAH!0#cbFeRn>>d zB9eF_cB#3M(b9X6=E}GomGq1mS1AkFrY9Q_Bj%0fh$|YLO-Lkmz2(X>Dgp(`c&}G! zQkPki%)Da}Zzw`n@(4)7V3uAun^z!E(G}Hj30_c*FRmmaQAn3jNt6I~PeQY@9kKbJ zfd36U>eFD>&Bq>8@UwU>%C@xrI;+`a%T`5|gy1Q%OuQ7&J{c~)ip~d|YSB5H*y1x2 zjY)CV1G$S`tcX~6<|8Rc7qYkS4l6XENftK5$}Ys>tNKs{Jg2*`Ya1BGCV9-S^Qerp zpF=LpyxWs2RX8D;MmqDFv&h{HCxCn&r4VMN0wln}P_h^*|vN0r$Wtf!jI^a=#2X@CJd zJc3cv*PU%PqHq;xTIf8A>;eQ5_Ha3Sx})*KI!Tf=G9*4Dzu%fj?~h>~T3ZQcWXYqB zjx~BXadCMh)ewa`RzheE4PO}sUyS0DQ4?ac*C+XjATVByiHthqJI%)}B|56^BqFor zE^`DuiISw5f`>&b>n^le=!Ecf9MFy#v?_k0svKJ<3?Gk=yv}&tNjFz4ijhn80y;(n z{ZzyQX5v$UiVK4uNSUKv02O65kyLaJ@KE3>w7laObEV&c7Dp<7#bsE_)hNLEYbrD} zk?zv!Xj*hBpr<37WjJNMh_Bt{x&6{Wn6y|Zb0=FADRn_^Kg1;YYN5Xr&9 z%SKBdW06eAD>_8MWI)e67R$qo zP?*~kcb!kzdyXC2o;28@ZfFyYn%FA`r7%8OM?obgh1nod5ycnmceG%CBn1YY#zRi6 z6EOuO>dGU%uu>?7T!|`d^kw9w)s7GfG36s50L7bxqDjI&$yF7qyk<~Ur<5#q+(&fV z+!i>+EfWD#4bD_61`YMw$Gl^!xfIELB4#bzZ?zAa5FUGX%-yYW`^0l(b!MRLDb=d| zo$>eX8oZidZ6zE<%d5Ow;%4jYsdw7f%~1KPC7t$P7UwVRZD-+*l1QOOL2ir9@P_>t z2LCdzJMB=ZtEiC9_M@gfSTpNxy3SH_X@zb}T$a-kDT&S9RxWr*p@vdmMhuwZrM1>f zMJ(n*~x3gPHDefa$D-o>>G)``Tq3pYU;2r_D5QLHSklnipAu@TxhlJL-uQo#;z zc+YDtawwtlw;$_eV<0sKJAsuLLaM!43&iJVnz7oC(Qfdv00Y@|-(L6AE0#wfzq<8APGsF+M+ZZ<(zQ{gq1BSO7`HIL1$13c07YIU7U)uq(l?xZeEb4!_-fmmkf(NfGt z7;sGIr8lwD6YL|CtsD0*x$rhU4G6X<%MH7UEU6T=$t+YcMX;~nx~6^7l0h(-ka5yj zZwAffJXq*qsI82auYezwnU2J35Fp43)kG^R;w#l$OUt=nZ5y_Hw^-*m?K%J{41vaT zg%E?9C)=x0VLLq951J;|Y1(8glwp%xU*oAg@6y~eF%

^L@d{iar~C0CR!dKokWN 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

Cf^b|Ir$WwoI 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%0AYYT1GU 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ð{4^?`HpDtxee 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 z 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 z²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

csx}N(PdENRO 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≦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

Al#Cui;L!5kxHMf`BHp@%o#Dov>x)>MQ)Rbvqk} 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%0A=Db%xA98LmpZfjVy_pW~msr{P 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%0AK?{Le>EQi1+Snn02M+S83iJwm?BFM|KetA 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 z

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

R9Q7kbYPyY?n< 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 z zggv4C8pPLVf^3lO)DN9H_v4Ju(b9dS3mvs-$D7%HI&s3(ozM-21lEkRQ=$QTX}pcI zq^&=nH4I3f3>;m;^=JF}MR)0gYJeH4_z9Vg0bI-U*;A<0OcQshf^)nMqkNK^$MeM{ zC_zgzd;|%YE}C92*s$cz+;scBm3y)2cj%;Hs0@C9Xiu`Vcm&3uS3kY}spF=#T??Y7 zci?|DpmS0NS}a8;{<#|BYq2FO{25?_K%C6NiH9zfMg;`aWyZt1Fa19IbnP0@qQ^8h zOpov#rl@?Tzvz%+v7U6BUaO}YZ)5?VeI2x!J0^^QkNiitT?0T1b30z3S!$+p7Qd<^TituluW+GXtrQmHawjQ(o<#?^a#Psx z+vCla2Ozs+erJCHU5*Y<6yYTvx!n(5VUZp6Ig*WEK^@o*_p8;ooEb>`XUkf18Das$?4arpbx>LcS7*bF|!r!rIgW$M2NsjxrIjn066Hx(tZ&(k-!D4 z?JG^b*mvPV8DxzxI{Ahj9P-kQgv8(-Ph?RlDuLEIDHte%D69(N6kg*CY}@NeC{sEJ z)t7*Bts#@u!=ANpow{<>t~cmGqY@3km;JC|9-DAwxFInu_-9xgJ>9Oq6vCY6jdLQc zg270OU670w60{58U(7 z(cK^2H+Zz3OiSMT`=9#Hcm4V2@m@j^*sZa^r7}uc&p4T#jJ=TWxhLn*U%w~6*M6ks zg+ySFw zk+GiAyo8H13hF{40bSBJa<9;7wvAlLWOt5>9xod6<+oqKCV#1Pf(3KRywfoZ2_wIj z>(O7uJIcM3VtCdz;9hjO@%cbsMJ}4%a=Z7t{Oe8c%_;p%Uq^I?R3xctz`zn55!Iz@ zJL**@cfb;r(4m(#godu7s8B16!+B{!_Zgr{=g3mBHq17eAOe$AFcoJwyV7hyg}X97 zLe*ZHA5Mi6mEntPzRv{|r}uv$KM{x@HUBU2nmKY|}1{*W*S+i$S4LL_#o0 zK?4?zNIt}Qry2m16bWdN7Cj75ak9Y%r>nMS7{1y^?Y$4Y?4A0WMR)VG-I+t9eDLip z`1nA4j?8^XYb^+|$1=mF_$>d{(MTkq0)jg(11x%#K-?yF~N2iyl5`yd3Q z0Q8bH5k{fC09|o`4Za2QcB`yCh%RW1d+hr@y6;&YI#0NZ;~()_{^hwJY4`eo9%j34 zwFaAx(ghj)j8z~G) zipGS3g2X@|o<%GI)tDsAl@wmPiDj7rF0!^XgB+@sa&x_M-^%b>GYO zuA+6gsp~4O5Xoc#Tg+lhNJK)?g9D&~6c_I(jzIuOFhzikDyXmm3oA(c)LCeQ7Ik3& z@bnk`a{hPypOk?h*m1GlaFFgdS<3jWtx+0Kvp9kMwvL!9B00SAWxZ{6Bq8p+7ZG{k`$6 zJkyuY^}J{Q*_k|>_ilJPw3W1@t1tT-54COC;SMFW^KUCbweFUr?+I%4C1rh=!Bu;2 zP@~`l9Ar_78@2+WECgAZI5mYS639Rn6z370UrBKQQ$Vc0Rj)nTgST`A>)q#X`L5f4 zef#fQy&v5|z#%X`=CFbcHvz!_p@$Adi{q7J{RsBl9f|qR&*}fV&;O%4zjmKO=%_fx zy?#!JM8G0Q!9*G_fMLxPVsD+R2$iSxSM)FjDP$r-q(K0`=F2pL%zQHE z)1RMj?b=SZ+0?wabo#mTd~W2S-rv?KRI;bN1#n&fC);wVXHVzjU50^56dcwm<7~-e0_XxbjXihP$n|$DTwr@y)FHojpLW^SMvtG5cr4xA0}_* zef-WBO2TUQ)6*Xn4^3WP%s>6(V|}mwZ=dHk?>4QZOE{da?@p1ifHjDeqm1E*Hir%m zMG6f^k7=Sl2SpC{f?{+q=w?R3(NWLsNgQCAfC5@T8?|`*tzL1RS27;c9z~(0 z03G!Bp`NDaxo@ZaE97T0K#@mSU`cQ6?ZNM(_x*J4dhN^8&FA&D_?A0%)CF-V5bT61 zp%p#!$9nJa@tS&TKLNs~LBRm9yHA=HCVWC<$%1%Vb;;VaA=w|+WGbJ($31PY>$`rR zmJvPR$oZ)Jur@#OKfsmO`&WZ${W3K1QS61hy6JD!IV_$nMsRn+}$>!%8$Cbx7{hC^L8I&qp+Qe-EH zDx1hc4(6e;NA1?`+~?*7kLIr(wBy}tyjI(ZmtOsCZa6c`r=R}Kb+woSPnjqk- zyO-3PpJ+m8f{ml0zKh@_Ed)bqVlIPc!#-$CHc=v#u$V5`(gjad#C#ZZg;kj{+kk*= z^h3CEK-?(ls<<)}bHyy^0j@z|pU6&@H15xsYs(AyIgzPhc~T*|Rd%8|0Dml0y2ga4 zRQcLc@A^x#V~4Z#`Z9g5RrBbJ9O%(iS(DE6kxztZ^yEkiMg$9@f?7~bOh7uoA|kRU z0s^K%FlJb(bq9F@h*=N|`waNk-)h=fzD$Pz``h=YSw{Eq5=J`=6QWcIqO{}%X%&qK z=pZ0k4xYvcI*NOBiC*4h+vMsqbGJAU1r)+fRg>)F*MsD1bw`#D+O1MviT3>P9;xpO zhQ;q0l`RA!>otwnOjB0{nW(`m611Lvl`ZFuj;RYvvnrya4q8mR_)zT1)x28Jg7Hku z+-Y@H4@%61QG^&00{Wq_h1`ph4>S#~E zU7tzo^r|Z5!d zyT(BTo!3vT9j*~62XsS*a=ZB6hi{x~W#ghnrM3LP`XbLDPk6@Id8@YQ#^2f7Y#1)J zXk}PPbXv>jqOAno44s$dq4w=KBWE}DXWMqUGI8-_-(!msE{C`ddTQPDO}{JwCae(R z>+zGaArlE0AA~t)L1XeuyqqF#wRO)RrO3L)I7drD*Mmu*$o$;QXd!GNC zpHuDdx4u5uTpZoXwqCc*Gx?}5ZCFCxnp{}z7^57j!vZM?H_hARB~@B+v_bDM%K!-D z;{)gx?j;Vztx=J5q^*{iffGm^q;T)Rqb6ZvK)#sbtF>V{&uUls1#oqG#rNX~8aN63 zKKI^(j>4_$#cXj^mVQ|IXIRu9!ZiXkFnws|z#;V6WRJdWht&txPjim%T%dbiS43Rk zEnV2M8zh7*f7%zR5B8ze;6GbDx^%-Ea=HDM#>(E9zw7+P`)Igl+rAq(Ftcz&=FK|~ z=jGpX5`rFZi2wnCAd!0Lvsze5yp$LFc4p(acYXsG!B~pNgPsJ}oyh?@zfSK;{{G^b zytVCrL<&9-YFhqIN0$A*|7<6H7Tk>uT&ijKZOxKl9e0smdzUR~=_!k6nG|j|+2n|L zDL_$kd%;!|I^wImJWK1{yZPW-rhZt2>O~sj%+TRQc;qnw0w#jwpkV?wvG;P{tDouE)#iQKEcl_ZEpq59RA1M zv0~=4_+wa%lq1X8$RPBzNIvLv^V)DkGqP`b1`7gasP#uqip$RZxk z`i?_Dt8)T!a5a9tJbhrYSi*86cYf6B}`GVPR?1*ekcR}Cf+%{r!-7$h-T?yJ0r|^)tnU)2Mseo$Zgfj3s?7N zu~Pdb^S_tE*)St|oA3700@u52cEolXHKc1v0*&k?Ow=RN6?7qR1ppu1X0fmw&4=tQ z-F4OBSFX>&VqOp#A}&PbRa!m`_GPcz8g$L5IXezR27$bMDW`F=L2c+0GmltR@>jv+ zLfTDN%TXuxu!f_}-@h!D8dhA{t5Me_=w@Z1J0Fn}YzSc)ieNf;*2kM_K5z#K$8)(9 z>e{3>*O~OA@{RYMUwyPwer7D(c)ns4x*lS2q;~td-~RcV?N0*Nm91d&$=;7UTuV{< zYt~PP#4u>$Kp}M0NZ?f6QUdF8X`TH>{J{pKyjZ`@2Q!u5;D?c#B;q+rH2F`FtcvK~Zx3L_+R!CSz`E3Z^Xwuz`Lw3gpwd*fnd;j39Rjn zZgJxhbbtX11ENToLIWZeOdGS~cq$W5#D#X#UgTaS?~yD?W7SXTOyx%N&L7i#m|otl z17|r8;3_h>*?Hgny(2Em>ui49Y8eF}<10rroCClXNgE`pqqn$g0f|=|TtNuc1EvTd zK+#zw#CUMP#Psu`{OtFXr1D3`x5X`EcX+jFZ(CRwml{w%t*l``wydW_t`Lo4O$*A0 zprC?MRfmQ`&ES=mk%&bVH_l-yKu7%mhB~C|6Nn#gVxj_npiA0u=EKbW9CkmjEPSq$yHa;p;L3~&?SA{M? zy-WYpmAMYCgQprFyMKB9*O|W#TYs--p&=ZU>9#j}u3f!X(aaP!CcBL$z0ODG--rEW zy7k!=a2>Y??2JV+fozBqd&LX{I1m5}4o+YN2rC93U;)M<0F3}vJ0IiPtna}+Zi)O2 z;Bx!+yuyhYv0Gb?x4gthOAdr}t6qN9D{%U|Uib$ziIt`wIsW1XmO;H38Kmn+5kdMrX zMLUtLi*%u(o}8I5BH-C#shgw{AfTCTzSh-G%1>HL6X6Htn_iP9&lGk}2zvq7vA_mD zqT^^yZss_D>FGa8{V)3;t?_^TC-Z+A`hUE9{zZ?ax#O^G%%-{r@tg|_Z|iX}vUE8P z)b>3IG<6x-PB<>N)!H=H2!{AxjeYcU2iZecX`S&j){Wj@w!kjg%eN2n?SJscKb)ff z3atCuH}Ks2kH{qVhWBst*T=tyhG0+IXlRa&O?h zT;eSq2Z6EC;0&Z95B1~z!Nr&MQ_c({HkWgim*%^3l^D;BM93>8!ydgF9gz6XR0Bk+ z#*PG$SVy=HmAf(<&n5N9^XR;Od^B>!bzmurN*=BkzY`Xa0DuLB005*60e~(D0l*Xo zw9tq!s3X#FQ82f)pfx#Oe)Y>=wMNgZFbSXN16{xcCg6Fl6TkW0>+5qfYpT9c2V_^E z6$Jd&eEL78mHQ4;?etqi=5TnB4CJA67u@=GhF<5$0WJHJ>HqxlPnmJqy$g@90}jZc zhhRYK1m7k6vFteqfIU#!;OBUzzm2TRd(Nr2C|=`S*8%IDGqbVsz@d<;&#&KOc8>Y1 zN{$EeB>}i>tvXFc+L7$9|M~s(cOD-uJm%&4`S!K&lk!k!NOm~vy^qt8uPe0(y?V&K zJk;Tru9o5hkS`ncOl@rLF?4+L>c`)D{{8KzoT@>4cjV0o36b6ua~Og~X#ac{tDkr& zNaRQw459meW}nuNTd#LzWE9~9(E}`n!Pt(JCUpZ$?7AEaO-_$3VLzO^b#>eA!x~|s z`T5lNJ6DVImtcbf5N z5?BG=LJ*ZS=m-QfJ?*a#GPA5}&8*&#lJJi2>CGWMfNqH+Y#~dER-KXZ5#PFp0GUz9 z%GY*}J-9#yOBo2cW&8OE$9bD8K{td+9TqY|GUKw^#{(7~Nlt2wO6S(5xbHIA6mmN8 zY--98FM6t8zMwOS)5s9>?33)rls~_=nt}GB$k)-Y)0>SlShN_(7+^EVfFbJib93ga zxU~(hlLIsNEb|9^zpks(wBvZ=r|<`FJOID&>myR>qtbp3CoQ-N&Zn!FAEoZC@dw!_ znHdV8bf$8eY}N z7nT1x+&6OBLt{UN?hU}En|*{nEMf~raaJAriZp6K#N%2Zb?tp1;nG*z;J7+P&RGsT zu`X({CPqRMR;Sy|{5IWK8XY%^R0P^9e#>2|5M-QW2+Lre>^R4v8Z=Tu0CaH;7y8~c zt{U~Qb)y6>DFAt=1YBDYNBl5yiz|#Eo7g@paRuz#Y`|H?G_k)(FZK zL6Ekxt((tsx;o5d9eb!m$N7c6^>KesP~%QRZ-3v0ykx;V@$e2}5P=R1%60Hrj47wt zfR$(hi8@nGM76?QzF|lz^Tarm1AaUir$y92nu0mi%4p{u3slA^ElqLQ_tE?96FVOJ zaqZ2=kN>Ks*bMt)$7cbX%$TEwQWa-XBl5QoBh>oh1QD|sO>ADUHO*Sph>=);dyRM zQUbzpSS@;w3#S%VRjw|2cU5qjy~ElxoY-yyWk0xq6^}sD?x`&7WjF2P)!N4;s)E3{ zpZAi_Ivn?4`H$}(^G?3+mkVt~bN^v}->nonagIiqfv#^`Iy1S$P$cVUpr%_kIAlB- zNOb6+0}c>NsukXsxyBOY$`^$b<?N8Jc+L4q%jsp4#&}Nq zHH`JP;ToJycxQZrx2xAokAGtBY+UfxZZ8={vYQnr<3{YSkt74IH6h820?o{h|2=1n zg^uc{y$kC7S|Gt$wayrffvadCj|dz~v8kw|JuSfuI6e=r0ju)?)F>HPV}rj~juA+UCzc4<6pMC;?HVVbASthAGLr77-;6cAOAPFJ zSNw_JbFTOc8-Yk1)rNhOm(>a50G3dt%1J<^6PrPgYrw~}0I-6us8x3Dcz~x*O!OXL zbn8B)!BcIutwM4hpxiKx!N2T@yDqJFU>#^v=9fhv`hS6KZqMm6D@Ma6(hUYW|Hu~R zb!`^7%E`Kt=Px5$Y*7N&S z@FFii{;;pJ|9JWHcBcFW67T`hpB~W9%&Qh8iwh#LK)e$>e$4qB?jJYtmjcc#Ed~&f zB4+_3+t5HAc)Ws^ONWpo2CPM7w@GG8#{q?-RHsmK#U|)Uj0Gq{szz_iq;^>KsKJAA zI$W9Q-Odu9x#vUymv`3`ljv9^H80bz1H*_5_i_?yDwgAjk$Bty$DJ0KeVvk%877;V zBi1l2!`ci6!uWub-)PQdqaE)|crM(TSmsaP8dB5Q1!Wjp7ANPCU`LZ!19bTM?Zs0bguWqI5*YmlC^~S{q{UGZ< zZj1Tt7KcNp&>`|2$321)23Oe?%8PpTM%H`ys8jCI=_EIWD-}Hh2KsLQ<6nm_=O+Pf z)*k$XUq8Gls-o4^^Uj<4vX^twn;cFwq5y%l5*MEj?_GLMC_dzyud@}9G$5b}vXJH`*JMvR*F8-`NsyUkM z<)a+E;R!1alS$DhD)ZEsx zbVjm;0Lv(V>1_56$Z%|xu@Ew3j50mUv;?y0SY-8~ev|_P&x(E^Z^Fm0ltR|CKp34l zJ=GL76y2t4u9_e0>n-N(KmxGD_hZihFY&2~7&@roMGlrhW0?KsDn0dU=&k)R<$?Xo z5z@1GgSd@H241LOBM<@r2SA*lfIul~05G+}04hjn7Z*gNLksm&`l;u9E?h`IKVVmR zdb=tG;|C8D7_XO)=uIc5W)sr zN9$^%(G1~1)@6m}cvp9_FFJtESt}7*AT21*@WU=U(3O~_H(Mm#k2Wd{2#nI8comz< z#m6B-g)o71T2Tgz!sApUY^R4%fJvippX(nn_gF7)$6#)jIF|j~7+H69IEvE*dak!Es3|yHV zl{fa!N8ztpr)BB~DYJcv%a#JC-E1N5i5R;z7m|RbSjjeo*VnIo9>0ArGa;O>lK*?C z3_1$sbj5Iml$UgTJmz1PC(sNe1wm3Hp#h@ADdBc@Q(xtwt_!$pniJN?X;#*3`Q5fP zy}56`yr`o+poW{`?EjZ}^Zdc@{eD;c<-z^_IQh%S{=dQ@@Amu+e-3`R-}!mf`~G?< z4LL>_@b}r@34H!wewDv4pXsB&Ki;G6(-}m-T09nPc2#t9EDM%RNzV8t7<1;|ZX+u_ zf)a^WL?@UMm<1qxhJK`AMFB`3L~#pthw^5CkYg>dy?7!xysU(enQ1Y**#48A`&zMj#@o2rz*F06;MW*AmbFbG*OW<7r%e`K2G_KD^cd zHKt8s0hk5^9Ng~i*KhBB|K&7Khhh$-9VG6VaX5~ky3C+%e$?R~qxzoPGuJ8UES1O9 z)Pp@%;g}Y%OXYtDzC5@$9GcTI)eMvkEKX})WWAn=D+V1fUC5ZAk4$r14bGV@ly=U< z?)U4ap|40rvYntoeey!``*9Gra#RI&#mIJOITMywVMZSUs#~~8nxgi&|HBXH=$2xd+=JZs?)hnSO=ss-Oh?$c<5*fK z8XUTQYR4tsF~jOCr7oSl0Gdx=OLuL9s9@rU_pobZLTAE`}w6^iivB zk$K+Zb*BW2!n&woy9jES6R`z?DDvc_8Z5^To*6ut`RB|tvbrgnl7hw;KmfE=5LgX`AfjC{_pGxGqmClPLN45AnvHSWO-pCW z&+a`b5JHeirIs(<+_Q8utRGeb*I)CJ?1$0~Axhv^w za)0MOZ0;m2VcoLJy`5g%7MJ$RGZ(*liChn!+xuSGXXA(H0@WzOVl!vq>59lgdiIpR zjEJakhkz_06<&EWJT1d*{AjUR5)u?%t65o5JF1&8gPR-sxMrxirsY)0+KuaBXa29M z>%CY~2pO|#+{*3Jsa0bGAm!21&ZJ!o#B+{pjzx1-)}RU%rdr-qp;Z1>_EO!F$abZZ zz)lF)XuIw|dv=RfR!ROrc9;`#@?ypZqFgp*7|3|lTfbehEmbW@cRacERk!Yp(o%83 zjMJHHw5J>HMhtX~78vc?NhVS_%dX6Y{TxS9iI&b<>BS3$$Qn?CE9cqbQ|p!8bxEqm z(dw1a5B-eqy?anl59!1h5fpGp!3Tp91X~H@9qj8FXbB`pIzpjR_)zvdY%W*qbTC^g z9i3SeAI-gIbTzOO3_%KrA!W!pw#y~r09J($IMx~ByZ1Nu$De=x?iu#N-we4wi#`pi zC`}Y1QFTEwvrHSfix(Q{W3rakx`fIj`3~}+36r`~*8r)*U6~hz*Ttsg_!lMyZa|5T zmZPEyQ=ZU>GSHaMfW>2#SNW}PuFzRfL7azpFy;4~VE=Nu3VJUBtSS%|PO&9pc)dX_ zckR~;l#ew%Wcn!-oRd+L%drf%cYd_JLf=jG^|g1!3nje>?vqy#n^CtZNyXRCuyZ(g zr~8VJYvP#?LA25y77-e{Nr(#v#Xv)lF`b~|PYOADxTlgtQzNL3SF}W+Qk^tOX3zDi zMs(O4v;<^lcmg_I%g6!XpoyFBrnljZL405(A1Tv(c=vjh1Y(cN&6jKBYvA-JxBNqj z?-%d!n16F<#!hJ5Su&yNNNjvSrPh_IL%*57gTC=!5Ek!NY;FpZ00JWfW`JaIqK^T6 z0Fl*nF&D~)SbACtnnS4^JZ-M)IsrEWJTmymQLvUZKq!TTNwF6ccku7gH@Gp%t!cq- zc0c~F6Xu4+0u9NXSy9x2H~jMOThF7Z+{(q4@oRCqi`n!Rze^;SG~x2qMg6_M;MaH0 zU#@#@iHo0`iz{93&*HN9^xB*D`;{()={$qpxIgA=(SD|s#DEV_1}72_7%k>`qMH)n zOiO*989{`r3;_d*cA{3@6op?&ol=*K=qt&vsW-oV`-WF~sle~COOmZUYh*X}!B)vG zpYOq6K418qRa*_Z9Nf%$Q)5n_Pk79X680Mm{j9{!>?LGmw=A)Sib=yONiU8{?3KE3 zkU)2FWBAK=_w)jip(=iBjufS8&``kJ`( z0T4F!F+Ub*e_zMemtx@FSfWi`!yzaW71K;aW8!xd^F{|Fbmqtf zix_Ons$nV4my<2VHknj$q7sIn0|cnUQVhVNq_@z3ziR%3mjp8~;(?>0WySUmGpoc{ z8_0{@f*PgJh9EY?p43+^^P;5~We~y0q(p;0UcFk_(2l}Ya0W!P1`EqHnl7L?>!0HM zUi%?S37sWqt3be^_{3)m;4H`tN`8TI)(%3KU(odNnJx`Odx@rvWf1 zN=0&OqO%Qe6(A&`!>ElQ)1VDO10k_(t>c_jm?mI}dSJG+y9eT5#%lu}pM?(CO*PfQ z;a@GOPbXEpjBW+@0-qF~6n}W_BZF7~ppEx!*E7cgbVlgzQ5LF75AwI}e0EYQ1yC8V z=Yr3cqfI_KiD2sn8GHC6-cKF3M=h6Y8>0%W?!de9HueAE`p@tt`%oGK^MpO;+5?*$ zj2C@RUU!u&jUBLUd&M#4awp77+$F@*``yM{Ql_IfALlP{tQ6x~JdSozYv;46K|}D& zq-9W0Xkst3%lLusZ6x23PDn1EA|yAU0ur4!|2Q`N-S>kF!Jqax7pgr$%2dholruSXQjm9vzPS(YE0~+GL!RlW}^x<6hMDvX+4a< z1JFs=FA;`GmKoN(+9F9@K##~w!^FZaFr~>~GLoAn^8|jhlkd6i zvOE0!1?`CU-th7s{JEYgv`a&yCP;-yGLN{gex5JA?sJDYCAtjktwp=d^#&`RL6q%Z z&538%WNg?m!V%~uG#-#Y@3(FHa|!DTg$D?VYf{h@0DweLML-lnBq$gGxDrAN4G{?v z63w-sHMm&fz*u4vV@jpQ-%)f<>od6FV5h@t`Rqg8ik*1pSB<6*Ix)urh+WVArB8-5tQLrdwiFRzpfP^{XUh?(h z?RGn-xC$Fxba76Y1_EFU*e7Oh_s)53{rIfIKY79a0gdw@Fvsov?`Qbh9Zd)7T7G=I zcrI!QBvCZgt+&0Dj>B5DKz-!<&%_Ku1tn+E+aP0xjC#4n*2)muwp-6%k~2m<`fTiS z#~S8a22LjD!0YoXyXWt4j+hG*65A2G$eZ(s$LTjmj_wAooqg~5^~kZzi=LY5EF9M3 zu><{w{gju}eeVsW0T3_+fCGT&b3E^%By2 zyiqdErsnwuaJ*QnQJ?p#!^g`6pRLX2Z<&W3Mu>W&m&iiT{EqTN*;~KxBzcczuR)6|=T(Niw zbc)r}KC!cUR@}SUL#1@&-<4ZZQtSX9G<4AvtWg0nW;}|o@#yGces}l(A?9az&+7e? z)L)X05yew2!^m+ur|1p#BEB3SuiWnuXf7%shdh5q=$d}=;?Kh}Jn_bR^4m_ZOdnaL#>MN9^p34>wGMk^L7E(JtQ0|^ia5aJMA zv)IZVb3gGJ&E<7^q_=xlp_9}+^8y-@HU*ZN{T4hHnxh*_BypxkOEr+$VUv#C8Lpve#U^65{Dt!$}OhMOO)m}PX zc)#{sa~yYrY=B+kQT>;3j>Sf5v-(#d^ISGhNr&=evYI6;Z#dXytISZN+kc+^v+GNc0VdCvX0 z?cCO2T}B_Ou{J@+5w@$|*WDxfS+v_M_`lKo-_2xTnI2jS2N}_VwE*xHsNhbnV(GY{ z(DYW@gpD^y z`K->G*VhYolR>6*z|QHt=5QV>-(GH@ZHu?~B9l4nDPAtEd%ir5Bxth-3lvvs(=;Hc zbYCQT1}{%FJX*q_jNt&~r4BQqM^y~Yv4gtC$&CH&lXAkU?mos%V#?fnetqrpH_zT& z@a?e`e1;lm4X?rMkc!oOY7lo(Q6ASyNmr}rR3QT2V3m3+Yo^tBn;>aHaWc-2v-1pJ zZJY=eBF#L8w@}woVbP!#*uvZ?n`4-j_jk3e=Od!m2t_x^BkzEb%dS$)paD*x*p68= zaw8OU>$}C?vLrOy2aZ^U!FYkRy?0UWu#OFZ>cj!i7pn(oUmE9{ZyMppG?l~0@4ohm z={ND0vDkxrCS%F9c6y-M!5oi*7*Bzyo(&`o7y{8jOpG2!we^CoXh@*%E2PFagAmDL zBmfm$vBx-e-R{o=w>g89NITX8N@#*YzGQo0$j%=8N21w%ox%Ea(beGGZcz4nEN z^9YE}?oOeN*^yHjeddOq<_q@IG0w0e5g4k3fYWv!%8|`rPnAjmwS>_SEMOLe2YS)W z;Ath;0^Wu{g9|rUXNg*a95}{g%Dm@e!PaRrnpmco48_PIgBf)pypXL2wCHpG{pF2_C8~zAb+(fv~5>?RW z@E7avn>D>Ttr^sWHG+^MoKJQ`(siCj2a}n+nLp+m@f~z=IUXU$O?n47&3A2j^r3}i z7My0#j+!BxaoMz*9W#T0`=y!d;ZEc;%lDn~p7Fl;wxG=O^(MSM``Y(&!B6V9WA^E- zdUN4!??&_&d@)P#d??M|$x;I~1D9Pnj-Q+!ez;QPf!UuYDmAd>A+g5N3$k8S%sbl$t{AC_RwBq3GBoK`?Oh5GunRSdSGaF7H=1OX9Cm{4KkAO@R;FXKG2D?paEl1}Q3 zrU~w`rbhKX57G3-S%I1StWs%fgn`DP2AVZSzDUcR5Ub0W(};d{?+{}_Y`yoer;w5x zo@_2z%C{xU&1iVhhKmCX@})LPD9r+gi8M#aS}y@$q$_S(W-NdH=iMGopD%2Rk_q8G zrP9mFoCH_GZj}R4XhwQ-VT9oBh&Ndw6&30>UAPd0CWa{T+DC{#aqqE69HdQoU=RVM zfzX}dpoW8GGpV3e(ybb?((@eY@SOuX?wX%o%5M`6 zI{SCf`WktBZ!ll^CAQ=n+%qR--5p0TQ`mIwlsI6r-e*jL?s&x()n(*Pq&?D7uq%Jt zXdgT~xDg~~r51_XB9h=>vpzqN)aB56N>uWres#8|X>BfdL7bY4;sD?q=B$Hnc!1#c(HwJ7^6730j#qo7rN&|*>{I%#$e>4-2Rb!^6a zE_eOM&F9w#p>{jl!g}vF&nV3=g!+~0ljy>Kv;JlZHm8l4xlJf_q>C8nR1Sn!M3GQU zB7;C?AZ93)Ae>INkjQ6%)^)K>R#TMH93eN3f@&11j?5t@7%h?{Ss2h-fIt}FPzm14 z?_uw=`lm0G$w5NnXlS;jKYCn=!yd8aMclUUHnX#T+V5nG?}_M4MG|0NJ?pg7p0H-k z*P!ouzpu+Ak1JQnz24*g>OeHpd$;MgpV^+s>+RJFMx_i;RO$hWFG@UEk+CbJbPPPX1n9J*% zASKk;B=)=dTFNp5s|u9cFmK~(FQ}zuFeX|e9Vrd7__+7W`QoSbcl;WbBJ}GRS{z_8 zt#es3>F7kgOcwD_u_%XHzzfUrjVV~8$;-wt9rECM3=DukaHD81wd1H zQWLO^I;!KaAcRm_@7T`wAU0j!1!s5nz|XUvJf{2Xg587B6X`1VwDhj%>3v`Hb@w0A zI%qTx>7w4Ey<84FSEzftyRtL%8YHAxNXLem0f98BDT!%;DWC|jKgS^gQxKrcm<#}k zfQSVl0>6EInaETnFzqO6?5^c`>U0hU$-0trB>6FJIkjJh z1zW*NERrHtLdo$to>THD=h2^&ttjQZKJ1^?JAcHZ#+OIp?2UAl-Dj(r{fuG;VkgFY z-~yShS}FUOGlMfJNLGP%+~ptga!?odS-F>edw}byP50+>U;OHcgKjjG$YCFad0gaU zWO^Q`Vg^XxhwXm;Z~py~em}eWH8tDM|C8q@_-A*2|NBvVg$vg6maPZ8+j-_6AHIJM zeI8B`Ltqr=PQ!qpzEAQ_3L163L{D@?OZr~j5~ztKkx+d?O8gHRw2qNx`^XR~W< zFG`Yv2Ivt;ook9*hZM4$XK)SET&@6t#JSdEsIx6fxDm(X?)l6vj}2oGK{&3iDjxg& z)fA>l(u8L!0SGKf5W=NqE|<4?2{QEIbLaSfK4xpn03BEZ0_g9Nr&c`wzCC2U06(~1F>Bffwu;&39sO;>Y< zF+zaBvEfreY{jB*%l3`jBlYw*O84g*eW+P3qBaDCM0?7PA9Yywr;YYQbI)zycvzp0 zM|EV^WG0bGy3|paHpR{N*$@L3a1-5;u8z3*yce z*MpXWdn5^%v`<7-Qa@^nXJ!aWPucqX1(9jr*L5F0SHP!52Q+w~bd^sO2k*K^^>_34 z|D2tbKmQ%!{WZORqD+&Wu>*SI6d5H(p<=#9y4Pnp`x|%lyfY-=Dwm?Om}84T8ppz2 z;0F{t4MWbkY3m=G>BwQTZND)e_Ur$rC;2&C1=I*hh&LH5j08b1N*HAl$*k0j0GNgV z1{c5}WCAVNg6MwUKjz!BS9PlBa}V3<>H8+TJ+ z8xaNm!Z8P&f|NK|hgUM%E*0HrOgc3=+oOJK0%Jk7T#BiP?um9lY zo;E{k@qA@wLHL!9Lq9geZ_P)Sa{S>%;UD+_R4xe0-w|y?+q_uL(#6J;G9Wu^@ zK)v_s(2kY&F%yyTDNz^E z25Ec+uG^)17ymGA+D#`&U^4iNY|bd}@cx~AMm>V5B4$xfNntO0uw?v_GOpQx9RO&o z1L82K!q=2WXs{@9z`;T}lEvtOu1H)6_(&c&jLC{}N`e}I@8xeX846-31cHaW|I5~3 z-{*hK!vAALf5RARQ&sD|c`tam)>0wklF>)ijV3W%WVWdT5X49Te>?M8is71p;)NlN z{FG+t0|rX%tuhnQ%`kvngY_D6R{R^&yMa3KGTb>k!$N}z&mGu|p5>Z@#(Tayok6v8a>nEf@H z8-;-V$cZrHXEH{MTk3#ooU`HP0?rhoB@^Lff}CXJUIhT4L}A7fY8s?~D1^LKr3Q!7 zUIJu!6$k9R#kh%(S47 zsmO+9c;YUI>Ah-isAA1BE<^#^4~7TS9_0tzR}^Np9;*BSH750Q=24DR1_^l|1tJXrLV2l$EeGPaqtPGN&Tjzyh2+n2fl%9KVM7!klQHjOZKH z^d@=pN#ixz;E*9#0SN$5r6>a#QOx_0o00I6gTm|x zf7g7P4}=PdG77}2W@ikF7{w=W3~<@G!_V}OE*uH~5#daIPdc~6*8Z;XnS208TFSOq zsWKkfwXg$qXpY9ffTiuL7$l9sl!}_6nbCt#Km$MYMFB&}+ln%RB5z9p0InUsBZ+W~ zr^CP!1TYjOb>7ZE4p9Jrr05Ep@zBWAc``S(q7^*RiXphsS{M%dhx2*+!~JMD?BQduZpqqvHehm?Yx%M{pHUSW z1+p^d^*eFic*oS->^he)pNr6|VL3R@GR_N8LP?CIk*lr}d)ObudGWM~{3bMow&vp) z_svK5d&$@9@}^*2cJyGbN%N=uUhGr_E%P?a$NcWmt-9adcQ$7-iC%y^Bca!IJqGR8 z6S5^WyGl|p)fMR{M$EhJmSgb!k~?-CT*B-&ODAq|tNAq4B4G#tAvDf1F3alS+&kmV zrTClp>bKLj5K0Vc>VgYc0kXSD=ef=a(@d$b!ch>*stFel{B!k(%}E}1?_t%f(rN-l zzbJZwg;tXUK20+wSilrIvZO4;fTtr}BD=T<)Q=!w>Z70pbM?Z7=pmgT7$v95GTtTS zChadv<|+UMGf)mm&-n zfhsls9{=y~|I|3U=f?YeLXmbeBhv3YvnNjC5x1`A)E@`?$!h2`k^!F4ev6n9#@lwu zu6vER&}*_H$yEteCk}xcpuhxx6ChB6Vxx2^<=|25WvvGvRC&5Tf7{G9MZ_6|WPu5; zGN>Gi-MXoS0&(tM!tCbMMDoIyFn4f4Eh;67k}(Yhi&27_S(CvS^aI(%Ph14cnO$bpai@O$j1)SSz+RETbc#Y|LpdJ{?*`xoX*JU51;lQwmx-v#`NMWRT zCkodNVRv4+Y=<88MHm6f9nQ?cxT#9gD7O^a=sP%q;3?j2y91epI7l2auV}#PNlA{^ z`PIw7YR7^D)DnS!!B?-M0bE9!O#zbGZiYUyrmm`cpmFV@r8Rqlebchlh$bk|{Tk~J z?DD=3g9X;xhD@ZBNbED6UT-+**A3qC`rC1R)p!Z1Pd0Jx?AQWFx0X#v!z001BX zhKL}fCIB>`0+LEa(;_OWxFUf_0Vt)Bpg|ZkP|K9Kn5v{pP%st4UISMtnXEh$>b~lA zu=iF+cg0{_iK|HgRun_6_3A1%^9uJ*^yAwBO^mXhedVbc3)Yt-66y2O#)8`nw}^VC ziW1flA`r_gnvymr4|XIQ1v+lu#~B{`lRfH;&(f#KQo5rV7kD7YWbN1o>=9RvG z7yp6`{Wco+GxwJqOKzTTp6`4BLqNR0^Vf_Q@Ew2p1KeBLy{Rpd%(;teS^WyS{UiIkL6TboOb8-8YAEWJ#BA@ly z&$aU!av4O@ihw192M?2%qhf`@Fa@TGke{`aN~mXVc)E1mOB@WP?$cq)*ahnYz@Qd} z>C8L|0$rqsvjcF~7X879$*1p*_3HJ+f>Qa^vaW@yMkx2t0ngN%YYj_i3O~f}x((8% z?&-k&ojnZZwy`H^;3&2Z6AiJzOa88e`m6^Ab{NF~u%2P$D;>opw|9w7%aL2&iJkGS zK2cCzvvml|GZR45#|M8t%tk4XEy#@8$cU0In_WGkU|xs#>fmyGMGDB7>4W(Nq(6Kl zj~g06XCSTB<;$52`bEEmR#VQS`_2n@9&mw_?`|>V-ABO7wasBzP|MG|4x95QymopG zX=U^hg(HP$wzI~cE*x@}b5=d-iMKJ_b?w{Q@s@NUJOLY`(LsY|TR61flN!*^uj`Ws z&D`CaCp$vWGLTvbit?x-n;BBFCqT*u^aTFq?$J`jhHc_(o$c}hFd!hi?G>m@7WlFn z`-A?@<3Db9_a>)iw(y94d!O zQ7F10H2q-2sW?EWq@z4Z_E!xauy)lN#apVh5^dHBwEV6ZWMIn5_(mzcu&*Ggz%L4L z)pN0I3-#!d*+j@=+movMKrGKxjC~L?yULibK!(}XLG3WPg#-0owcGl0%EOV|wG(Cs z9?3H&p}QJWRBp#OS~aIFfNe`_JRD}tqq*^c(BzKOW9jfcoy>R2hCLJO)_P}C^#jdf z>2kK8Rs|nS;5{z7{<_)Nhvg79j2mu@c2=hxxsIebBHjfG#h`_<6H>vIl%JA*uAAk{ zt^8_a?QMc>s-R{igYs^3Rd09gR1gY;Mv>1v`Plr?J zLwxmi!Ro&$%AUQ|OPat4Cy1#VgND3dyrV>yoFJ{0w1FNu$%^_G{3IC2@#NEc z_%3@bG|Km`m`g-hoHb>vWjg^72EW2YY)uvU)}hE+DL0i8U7oK?s2W6{3oij|hGR+9 zoQHNYUClNUeF zYz+$~-J(m~VKdB2&uETORAll_aA3XZ-@crb5T_19K|Ku|>AKw0B@Rk1qA_<4oS7k> z90B!hJoKmTW3izMvjU5@XI?3(#ULkpqXv(bl`+DSape3>zf*R?XZ+wf4z0D2Y}BwT zwuMww(QF}6KodU=sux!-KodgZZ;f~ZCO87rr=8s_6^P&K?1X zQP9~oMo99FYXK3?@Iu>~xc>2C8R~Q_@@xW}DW4Euo8ax*%s{fH;p;lnceEBA)FkJ@Z zCe#3Gm8n{Q6tG_e&>8*o8DN4L@R@(gtV(BMe#bD@nO6Lm3;lii#%rLV2Gq`bwY20l zy)YZlCK2dE$(UV6eAArjLL*K@d`@~{pyST=ySXiu8YHGWiz5a{asY^iOS+Y>03k^Y z24oNsm_xyw=x8?U;@%ojpKud+61znwA~{1Dc=%v|Kg91&|L((V8Nu0`v{Xyx61#W_ z+)08pDAf>iVRYVsoZL{5@chXx?!=jHcW88qz=<34B4+Lv`U=YF3JW^Mh>~sId&x~3 z0@P-S2c=*Fw{o!%T(ZPz$2-Qya@*RA1VY)hK!z)m$QhI5)i5Aqr z3|(5%ouLL(c_#`*1Sb-%Pi$4LhhNFxeXf}sdaF@^|oSAND9=aR1Bter?z1GxLNI);??+3 zXmSkwjxLID;_}#2rkOuKcKzz!ibu46{=B~+$V+q`y#B439y*@q?D<}N;0xl92b=D? z?FBCM=K;UD@*4x=>)z$~nu1bYa5CyO?E&ZXE@VIJE8giMc{T~)uwD07$-Aue*)VqX zx<}mU2rST{y@EPbmSn+LN4_h+7abCIgT1B)HkhO<_Kr3sC0URGh5__3nt9oXJzv!K zCLci(v}Jiy|H{tubMSkzPz14x0HlEh%v4%u$q5=&h|{?u^w=23DsJs$;ej@c7lt-U zH7>2>3Ye4~7^7fm>IodJ1Xx3FWrf~J!AX*2JWlL_5S-L2uY!$TMhT?~sOScW(OK<= z6??ppwk#gN%faFn&UeiWtA^NLo~i^=YYiGFB3Unrb34~Xo~mYEZywxd@~cfJWcTcq z@s99(r@4pR2&%MX0JLTe!S=>3=3a2;ETC2+2#Z$>kg{U8j+P^eb-CqqeCuuBhOF{E z%B>AzF1mtrgucS#6a4EBzvr$gaa-MiH*Rm(Hxg!(!Dh=`*f2(oP6v0Kh0q~g!PKOx zlGX1h`dRpDE~{`Osf=yB)Z0k!xkTVvrvm{21>lQ=4#t}^Vzsg#zyAX5KeC4SZ_4>M z3x4kH?_-t%$ROv5d%W=whD>69m?RC?|Z_nhc*ZVZQ*tVaHBR? zXue=4w16czO5Z@x&jyKt0vZYdBqoFsAfTW@i9a8JQ~*O%K!YfiBPnRfiU$@Il-MAZ zK$@KtQM95;QvP zG5ka)G$Det2InHmq)jqnoC4F6M9&TwP#!20hyd&0l%9IMd)vg8gn`5mfC|iJJ-U1c z*97MzXNH_Sx?8#Z3bT*@>oI=9$7l5Ls<+YT6>RwvM_AvV&EGsrBl0ry38=xSA{ z(P$xupia(4JJ40i)rE3)!R_ZDS9RGv6J6Wuw=jeHFrQ0f^SI6RoQiAo9DET{=A7g; zjHxAK)dFl$Pn)~B_FIYle!s9QMHR9za!>M_J{@1a}Dp)r8tL7c@lffE1o0LFhH;4yd}!gpQz<2g!)uUDF>3 zt>k?0886l;K0p~F8@fii6G^S^HlHS1WAW7;t3ZcQIyyZz=G$PRDF4=6bNy~*V&1wM zJ>cudXd0fVD#tvKs@zuGzC%)F?}h5phK*+$yTwAIW`+Be6Vm5&J7&0WpFsy@3~}FB zPIxl6*lH%~3{ik7B3@k{gbsH*)d8WULm^^=jxp9$=nH4f)7}Lvj(oW#{ILG{rj@Zv zftfkmoZR`^eXs63_Lr8|z~t}bONhGDmAsSP9Gsa_g+>_KlF3vz4BJ4=@R`I1@B7y} z?`1DeL}_n{Y=2+Ie$u}W(}F>Y0p*CK=Uyy#J4eW2&hq)QJ%9B+Tgn*Gl2I#%+M{zK zPUKpd4XMg;ZI!pUpPAI|i{)P2wMHLi%s#`%Rn^CW49kF414D+wqZAy$QbPp90(Fb} zz-XpW+;h(Iuo*^Wt85SX z(@xVczF0*FByFe`K$fuOby?S~X$PAWK_mRAu0Y;!z8k1qxNFgj3IIgC1F(5$w%Bda z61`ZO!_M8sa=ES}nJhqwLtnVXe6!9`ul4PO+1vE)*B@W4#CJXZE=76pF4#!NB;3A) zvI{P}>?wC$52_qSXKbh;3G(ErJSm;6V-mkL)rn`PC9_p-ij{lmZEU@m^IFn%_vY&? ztz8dTFRBZ1@5Kp3pJi^Gf+->F@a&xJ;QLHf(wn4o0h7~RP5ejcYv+B?83!o<;{!~9 z4m^+$4#3@D#cwF2ChDl$h%cNHf-EWAtoK*RLs6{HG%ui+g@oE{EbtC=6km|i^aa+| zjq@Q|wSkGMSg$|x~0FOr3|8mg5vCLR=JAWx2leC z0m7`(0Ve^T17o-9h+6w_l+H$FGi}BV$>OB(6@H?#Z7*EI@66qr^es2++p{by%}z-( zvX^YW&wTTTJHDG4b~- zvGlHSDVjsNCQ5?9eDmHQW-J;rK@&i$b-Q}L^y0}&Hh1QPa^XE)fJHD~!WZQy*XJ^6 zweQp|tPh-h^`)@xbhq0AVcQK=-s9KYs>3jJIUS+601m?rDbqBa!UTg}2#H_u zt+-k=WoQ~Y53rFr32J%QGHvoszhQ>5V3pk0*bc%U5ZH+qHN_7>#%gKhyXDPzfyca= zWF{PQw5j*|*(c&pzW@B9*OH!iK?^AOCWXxkXht0%G`_G)AO~46GwzxCj{9{wGX^f< ziZ2}#WqhdyV#h0}a?UUGS#e#jufe?Gkjqns26a*nAE)9-T^7s?J}_?uka?6^d#>6o znVhG)Gnv|rL8wL5ki$2RP|Ko)n#8|&QnQL(d??^Eu5o}v9eIHaX^2u5S_F7whOcr+ zI&-D=lv6BBozdJf9E^BCiG@Mf(s~er#0bAEn=@@pMveefKgCj967jGsIW$NTA>iYv zcgQ#dFcujgt5{lwXsT#6>ml!d$b56hcG4Kkm)$=0tcgCgH|Pf#$eWnmowZ+34?txM!bx&KU1V70=oI0U6kCKwrd|P7#K;V#&Eh6- zBl>(9TC$L+V0fl6Eg==8(NoQ4lQ-0wfsr0*7=Fr;#Ux2^mUu zWamYY6=`J)A<6IXTC6ozB#0;mW@77t6Go&qo;8Zi`9`#d%Y)wgXc);oxr78PksXRr z6ez$1DJ>;e0@#l0^LV%>{`SW%AIaA*bwAEqo5DP)Z@7!CzHgoDAZJkucE-p>+eW}} zE46i*fJ~D+Y!;=CuMO3{spj|6#}mmjH98hXUcznCrw=o(!1cY_rkUs2@82NT$7ODH zW=v)97!n7^*759Cq=cGZQX@B_9~>_Bcndaw5W(16fvgJmtRZE_7F@^Y9`cYp^zS2_#97<9%;62rSkdt;P zwN}wIOH%m@KsaaB0c^O#`4IL`60(i^cxLuIw=R>n#pboX)=VE!H>4afVeIprR zZt4X3 zJ$Ls}F(HGEAe!blMH(^Dcv3*^;#W%_-Bm+;k=ctq!Az4%a>XSsl0oCYzaI~s-;bIH ze*5;-|Hp5G-cPvzIyc;~8vRS+e1PQ{to9%*u94H2wi(^yzH4vE!d7X)ENbwTGyy6fG|PAV`4NRw_CA@3iY+#7QV+^>E7N(q5G=@bEl}rh6 zKuHWjU?Fl4vpTm>I$@FqMq%be5YnV!5*#dwC;a{ zGNjypG;8ZMGoF7ttiAu|(eGFPzr8(ve*B>IZ~fEE>z|+ET8JnO(yMcoR+24+D$0yfl%^p-ZF+mX!00E#f6bLn@u};)?7sSZ{kO(LN zplH@oSl12LNW=s7MLZVPx%b-s*_ZKKnB?*JnNP3a#=lPcgx&rEggUoJ zvbgdUDKNl*bWo3Qq1{dj*w)|^xQ1m{9ehDrV2t-APzaR!JQY;3W~*pxg;g&KpWYom zJl_US_Z;Jc;|ch9`!&IXdAA+xxf*Tm8j$;_QXoo6(j$NM>X+|vW52tmrGgQ=SN5El zFOAz%=@hhb&&taQKm~ZPk^l&6fBmrEnzxqkD_ATf!6v^BGQ$Q+!r_3OaUglUQt0ug zfARXaA6{$gV;L;0&e<>sO2Og!il@^u>YFZykHFa0_fniW24^8P6ih#^2fX^tDs(NM z^l=cly@`l)WZ7y<&xkCG#hv>wG+&DJE;aK!+vOCmcW1BH&F^6Q-tVZTILdC{n5B5H z%sx$L5u=;uewsYRF{T`!cv8e`$r?af?dR-1&$`pujk=SRDLa!E+lHaoz?gQrl+Cic zW+KiT0ou}TtbvosddZp~W%U~;T$HVPt)poiyO7pCowrpG;9T9`R~1h-i(Zpv+iKTs z$3Lc90>FyPnHFD;zWLryzutXN*7vdHm;U$IOKvj-5V0tlQwkIEm_;jfpwG$uI-D|x zOa6Y^<8r}#)SAkvl}EQ}TR0zlD=P$~qYE{-4cqX1d-UORrdJHr=svS{IlDH15%1XW z{R@MXzb3xe9VIfp9AHMp%nWJZ8MU(M9WwZpo=t4fL9dZQ5sjJ00UL* zY775f8Dy0_i%#i@@)Q~lEu#t~Ui#5irJgHx9aMzG6_|zb{DQK!hRzIcjvLk5_9_-n z-|8*~mB@otsX4jG+?MZS8#S%r^`cQjo$68pXf-pO?|td)u(1rRiL&0SM5oUz2-uZ1 z_nugb=mi;FXuIuHMF~r}u;86cM)$Z&zm}%+=OA)99UVOY*X3@YRop~{!=^zJFs0C( zO*FCyO0hXrh2TbND=22Co}95lxAS;be2yL^%fM6l!bQbvz37&nXo$Qy{xX=uJpQoA z$tAPBc)+^DPk6?Zzo%0h@h6A>>cxY>f6RM%v;XODUxb?^B_gKA)_I6E3>TYTWqV7}sl2%-q!dyOhpRZhpFp0izp+!AJ+ zUYG}(M{K~5V~V||`>oNRj}rg#U_an~f7G9Q{Jv%W<_OY7l{H~AjKYF@gXF+sPMlB+Oumu`jivi^vrn6Nf|Du^v{K z1Hm&TTN5DzHPOGZ%~OW&zF@dBe-mzY=hXeefI4gYC>Qrxzmy);n!b_HcjMw5`C{lVbASUsXNGDE^D_LI|F$P?@2Xf4xx3^}=kv8)Y0+RZ>+` z%(-s%?Bp0i;1adq4p#;lnCP)1PHq&EN-(VClxMS$sv54HY&gsheMl0U(~bKRLztDo z%t@mwiN`%L8PB5Ya#<1(<8@Gjfp}&g`L|cMZU<^^(KGYPy3?!vT^6f{6X@^^mcc6% z{j=TcxQKyo#%0PC4lvLST}2Ln^+*_%fr5b$5(M-n94Hx%jPM*U?OBmeh#7323hmHe zi?esY(_Z;!U#d57vY$|T{?>Bhc+A0x0-TLi zTncc<2!nYRH1>ws+BLYjH&cmr(G~!pz#NBxlh3Vq|HKG(trtbQ0!@00=-+m+I1$C~+m66L~5xi_1w`78=JH{f&GEpY6i$@8yenX#(u16c zIk6F)z)X(IGtw*>Z7Le!jMlkmPF+?L8!3;1EXm?c_A|wxGF40V*m;0%0JE|{CxhFW z`wK6NO)e96MPN!)qS-HaE5BJASg|&+`}u@Dkv$2M+V^_Pw&+UQ!kgRzrMQ-`fhJlE zq4D^k#N1L0#y~(MOUtIlgE9(+1U`b(ns)?~t`&epEuGkzs&PIPkzoV*GLB3wBGCzz zSceHvxQq=|BD#*!W>Y~ZJQXel6lSFcXU1lDV{T`Mpd~Jsq9qIY7^S3Hr-9zoU}6BV znhxv(Xv0CU2+FXG>;Q+dGZz<9iC(FCRu)%7(j9G`fBR(o?7ZI?&oN?_MdXY@ONYK+ zz5PDU5jl8|#8zpz8LA{#H2|GLmUg>1Us)DDUdwQ&zf&^Y2o@`Xrcra5g`cT63Yfbx zaQb}U`Wsn)lpXppL-R{IKG#-kPnptxQM%1EU-6A}0Oat|Y)h(%A0ApHWQ|!7{oN9$!H*jy|k8>x3Bv7$*a%{TsIr@gb`WOUE`(i z>1;GLsQjf&0$`Ud%1}ZOfW+4}XW)YFmAaZi-O|w1XiW-e^_QDXykq%6H+YM3z zXqvFCEp)eU?zPe}kED#oee6&6R6Bq}31-9AJnV&iRIc@FM=U6{<1kUcOAWt+v43R) z;O>h(3Zk)u1G|Vu&L%?=7CFo@uQbK)a-rCbwDK(^ng})u%D^tE$(j=A(G!emSj8j+ zsSpr|nBZi%Fgqy(i4mf4kde|Lj3Nmn8a+mZ1YuNS?8cimp-PAb1DG;#EbcAXImQyP zaFR_noJBD}!1i-FPuPhy58j4CC%-i5Ka<|(Hl`dzEMX8x5T0AwtfC6B>h=LH)4mA10xfZrGo9zPV zTCS|8!7#M4E$4scf8$ZuV5a`ig|F zlZq60^CD}SN!L1Hkp(o&MX$f`mp|!G^tZ3y{^eKGY9tpiCnG433Whj15AKfozkNCX z%WwNUa~{EgwxmZXK+F`;q6}N6W|#xj0kYsB-$|?YX|`?c4&hK zSV8@i-mit-T{V!Z>k7ta=FGT$0xz(mU!Ze*uU{EYNvphBZ`e$V7m&_HT}`MU-;Lq#wByjpcFM}{WU$~YR)8G3IYYBCJl+E zfg)5B-Cs{%;XHD#l=!54Kw5zbLYR5E07(TvfuyREY&~)i(h6e+5Hq4;7y$xH3@~Vq zR7s6QJWwPV;9{nwT_pR%Tt!^H&+lew*T2n}4MlO<70Xpuppf^OS}>b^3q)`s(KC z+r9G#e`hnlwS6B`AMbl}pYvC=Sbc5$@t2j?xSsFP=g-&K`)!wxN9hlE?%%h;eksvr z(FG(?)T~&`qTH5pVbuf}N;$Ov5*{2&wKl>~Ag;ohCk>FH+_nI%M5xYTGDD!KavUTL z0~8_xq6gARr?KXvnLyiMu_KCpQd&1aCj}yIvXZbRNC}~5N`VGNgAz0aBF3>F{pIBLqEM8l!MmcW&9BFxx{QN>#}stlaFkZ8tGWHHHaeKIa74XE zU184r{h8NqIxyuzB{W;`_S0*GY8CfPB7|~Pw{4UbuT)7dUr?+x{dd%vv4m`S`M0ZZ zJ$Z9M2>}G;00;n}gptx~5tM)c)B+Xsb-A~<|EWpx>`b^pCZvxwpMUyC!u0F!{_}A} z3!M!xaIo3hFE1a{P)&Z|ByVq}C!9dx$~=EI`djDc1_BT<`NKYbk_k}qIuO7Bo`P1V zIaYbo(*3rk7dWfP<8wF54i@VkyGMoFNi-u;G}6kVQa<}Uzuj|iaiqv4 z?Q$-&w$UD=c(qN#c!N}{GcwLI`z<^hn}zaox}7b-eUdO2aG=Ms_JwCGfgz~cA;); zhwfoo$x51nQc7O5)uRS~-z0<573g0MDt^K;bBx?aI1R@`T9mNCU!m9-H+WfIsWIUJ zc($8}&T8ubwX~FbSHe(sErAx2=cU$M)Ghp4>zE)2HLx-7_c)Iz+?d3N^8xY17PGoH z?Da7cJSn~%@25h^H@OE3IgD^`xo3SNOY~lO!}$jNuv1!JBLhOXH9DK|eUI{-_9AYn z&0;fv5G+zde8qFJP^DGrssZkR*2FI>zs{LO{+K9brUq`dPvHK^Fcvft{6@LcaSRrW zFCD9^CF1EMj+DhJ#~?VztIG*}ds-%KOgVl$IvuWf%=#z`zO#awszh5t8LVaoan3>P zY$zs=J}uV&)P3Ods`dV!0Jia&2m{yoJpy;^Mlw<~5i01Sse-ye?uL}Px|a08_zn1= z_q>{ClLvQi4e?us{Lsm35}VE~*0}#hABo##AFqd^dDXugr8dLzi`HxG8DRW9*klN# zc$a)gE5TZ_;2p%YlO6z<=f(#FgpFy+hvIQrx?m9PnpRFqU9jKn>}NN>bu-%6q7gDF zD$y@1IM6y8>qcdZEa8j8I5B3$QK}tFB2yL!0;m<%V@B%X6~bhvS)8%|=I6K~*BYpd zaysq<4{cd#pQb4VM%k}XI-f6fm-X+!{oGH}%oQ^JrXJ3%|TxhZ(jhb_^-yYO1sRDK*J$m1FBEI``C&lpA& z7Thp#K}v%cDCv*Lcfkw#ttqBC6~ts&aralaGgOX(7V6vzC1lW(GZ7G_M2QXtAQ244 z>YTt5MHrjYpr9gJ&t6wAQ$w3uh0%Y_ja&ThV#1cJ0eLF*)5=aXzzL{Fo%Mg%@NuIU+8m5UAPZ&2GkobVZ%tG z0RU8lXbDIO%t(!d6HdAd2&0aYMb3(LNk2TVmrhdJi@V@E;0%8Z88#8Ri!yx8$K>!E zf2X*(`#Mnw!mn%-@C1$!hJV>!o9@#K2pY}>YY{V^>6TJ?X5GuuW-(lsJ8*!NxEH?k zHD6mrx8CMK$V>}xC{dvOKp#@mm==VAu-^&49X!u_=1VN(VxS<2!ac}PMt`*5%{Eq= zbDwl)svSHElLDo3S&@8!bb0SYeL{~lI^J+T9hws`oTBqcD<;?J6F0+wNhb5pq6ck_ zyyQIOPBtxRJXY>NsW8TT84%I@KzGwm*_M9ll;}us+PXCI!&P19DV0bqPi~@VQ(!4! zJc6LkQkp|@jagcq6&=7pPKT1zi%tR;Y9TWa{5v!WTB}ug`{w8 zQLetAauR z`YjzemprH6eXNp%lRv9xsy9@*n>qKTERpjXddceW3}tsied9T^85dLPPYfrW3?cYC z@x+IppWumJ05El%a|bTHvUbV)(%V>VCUC{OV12Hr;}CnQBM)Yg@n{X};EPS#(~=M6 zMv=qGq+(v|&cm<`8zdJcc$AA=FxT9Iv?n6Gc)(CsEiE#!fGD2|jrMhUz}DNbssU|b zG=gb}N3DUmSZX)a8zo1iVpPr{0Qsakx_>eUJu9>cF_cxu10p3`Ce$^V;u<31(6o_1 z?xNRtKB$XkSGf|W<}N~IR=CLAnGTn8x8|y8i&$2%DHkAu>5*z+txVfeM^uirOsBvl zq^Hqv24gvd48BlpND3O_Oo{;xF8+tJed%D@b~pqhVY4MDU`;vO1{CtPmt*Et=rfSX z!(1EO%DI}73gE>)T%+Nc{(29z)%y%kH6938aigH1WzNo}A)rFZRk@mV^|L{8L_-IfedyRRpC)2}8^$w&i-h8~&IcwnEq za5HcaHVSTS+YMMXaTTrrQ~>UtknzQSrTr=1B`sVWDyt|_OEE3dCXBmdT(}4~q)_Al zF!%53XVH#z>`84HldZ2fAkKcXM>;2T3bVKv>I9x_-Y-^?iRVV>DN3T4WpI+gwz~R4 z%?3IEE`$Ea>-Ft}`qyqqB+8Joq-K`GfS_W*fW$WhDec;vOIIX`Mg_}f2Mr_uxOh=E zjw13(gP~V}fez@QqIr#wC?qz5I%16{=n`!WD{0uJG^9pb#`F98f2tfm`Fg!Q*`xh^ z3+nsU?vr^%xs;D|8@otH+W@qW&hL+&uSrR7e#BuXxA}eT>me#wkUqV|g}n)@Oh8#{ z6rpq$(3D+C!GWY60diM)twm~zf{v69aso)Ys2{)rZ~_Hrha77>=kuJ5LvMDbZQOr9 zpk1VUQ1Au`na?UGy+AVc80V>z#!GqLoXoq|4R_l+aQim0o}B=zODZ{gbWx{0@GR03 zS}cp}@DdkN5hm4_B-r!y-{;}wmkimXyRUE==;eFO-QMaD88rjUx-ICmJp0L~Kc8vX zw!O1v#*1DlM8y?|fF&LXQi5ztKIVqip(ejyf|<8FW>NgyZCptkEgu)T}wb;dhph6`<{v?WTovvIgUGIZXaTe*W?M_a4T~Q^&))KJjo4a~x~Cqkj4gcY>};0yV*r zritNKx__dt);O8A8)AL^{^i5Z;k$ePgZX=rXVlCNP{y$o_^a|FN*z2g1}mpEj*G;J zy8tL6B?wVcq8g%_b&hz=iEGp;a`Bnqq??rC{miD%W+|XlO<@USZ`a!rpcPA>f(X!x zNCXlY$ctRCni8u-m$P$`i%N$>^ZpohVBOxxPWHl+Lsh?BVQl94xm_wZ1p~ETj2rge zy!D{=n_RO9PjBC`|4ZV4D!8k8?d8XQF#9?iU+1SjFCi=C`iePMT+WpHIy9FEr!Kg8 zuXgdtJd5|oupH#==Xm|StziD(Z+;HrkPL7Tw7f^(K9yWK^Exj%POEoD%i7l-Y9!d(TMPx8%RbMcY7vzekrwM4qD3$|BGy&rx zS7&WTlK{a&8(DOEnhpa5G&5vC=|>?$;xU6DfnrX~R#NDe0HZDb7lHAC(6rD6XB#@c zM%Y+{a2=%;^dMB_i@%K(u-wjd+C6!vwP+;?6NQAr5P$&abdEE>jb)u1DMi`sUlj&$WE5t!ypf(dP^GwlJ!DZSD+LOW@|i9n*#-dt){H z=;0!}rly<|mBaKH-U_;?Bqbiir!|Joa;w&>#eAVDgxLlQceQ4E%%;vP9B}W)0xVZF zn@8_acq`>*;xg_Tc(9}7sHWTV-Q|5tMt<6z^4VY65xIAz^)vS#R@gRq_h%G-KmBn3 z!TReubla2SU;JQBRm83d0m#`gk;}j4H?Q;?M6yK?G8XXyx{_}!SrY?$M&0p7pl~dM z=XZb7f79B3{(slCvMz&Qcdie8{QUd%_w^KeefcC`HfQ}>BCEGl>F%6A)I?|+gQy9J zZC&e8Yr01!2G_LDSE{#vTepWE{3-oqA+LXTUc97dLx=lY&HlEQ{jsCX-4S}k7RohY z6^W+PVBDJfyjOsiUe=r;=RK~c&z#tUl?Czp*g&FFG6P$nPJM$yRTgZvL2h?vzx6FY^UHpw7rm}D0mNBx)-7JMaywhBDbQiB zbYW3y4M!gS_Vj*ww%@7v*ama6?q{;TqCuUy4jFYyr$S z@GSe{pP#c8R5HJ6XQ=gNAh0A^Xl*0K9#lxg>8T#|x!2U{mGZot`&mPW1sbcuL+)`ZL`ZzczQQcZAs{@fm-{5O(QiE!}vj+8&Q8q}5SWv(a`? zc;dMS!-^qH)bN#_Dp+Q1aD`ie+v`_1LHB(of9^;+c!fc!VDgw;H>d-3C`3+5Qw8unC`PD7TiPq|`9vO1z8>RO{qL`OW4;>qUVl!f-RHA< z`v4_OxSFgDNC}AIYN#}+;e7~=Xz8%hFev)cFu;SvVeV?8b8z}HISCHMriocHQcddF z>oBGbiX~Yu*4%Qie~~{yg*Ea*xzwMO1vjz)%y59aazMGJS zK|8X+E@voe!>kI#ONm;GuthD$5Tp<|9wtx$qYGw~7IsFg?@&lW-(pq)R)dUVLLFfx#CdNa|0&AG{Q2CV-<5XuV7GRomR(ey; zKh(RS00KxdNH8zm8cX*(@q2$E!P)9}<1V%RXKMHke4#Bu1;Oge zLL)0MGfav_Nr%+Kn-EkTYUpG%Hs?ZURu#Dt_*ex(j>Iw+_a?UU!X>`rNxG0v`#ZW% zg!Ji1l)fe+oeZ6nn3(Zmk3c7yq5L{dz6?_kbc=)bJYDN;awee|XwGRr$OtebHQuuIJz+Gs0!E ze5ULG;9$W)*wQk^GKDp#`{GASv=yf>--t%5ctC@WV|M)vM1>20B=Q#>MP57eD>A%1gzH$-Mzw`(|AOl$a zm7{d5S~d(c))YI>O9g06Fp|dA?2uVTXHhbX<~;s zkz-VtQ2|J#5U5;&kx>*73dxWhRsdbLZtGLUkYU!#zI|#M_Jf@3u4W#WR$sWeKazs6 zK?qrhn%(wazkk2sf6m#ulE^a5G!10vDps3J5t*?dYVpv?+`=#PbcQnwSD2lBa&5uX z)wiMrz&vPp>eEA+Sd7jTX;Yj;TNIqZOo}GPfF}h@*D$dH&583JlmJ8Vl%0<^HIL?K zGq{iJc+--}NAqEu(B{;)i8ZrF%4r<+m2x{PPeF3k7}GheR&cpS3utW{;^?Klggf+T zg}jv_z5;0sxEevKTbhNT)PF6)Nlu?pZoJVr2{djPPP02dG^l3n#_N#5t z5E6G?HYrtRV3iy$$EHVZx8 zd(0iiDP&X%j>QNg5Ghgwfdi3L218_qQ^`XMbnawAHj_1sVHJ1un$|3R6bt|@Yl)mv zuLg^QmMIj2^}~k!lAVZo2w*nM6o6!~Z)y#8p}k4_zTo&8_{Q*4qL0HS#Yr3{efEAY z^nJ{2IsRSCem*GSlc8?kF!jHaK0jEp6Df4_V^XCjm1Lekl;VJ0g1US?q$3P8i+ z#u8h0s0=Xa6UX%^A0Abb5903NJT|Kac-bP>8H9T@hrGGF_)6gZ^=gGxIY=3sSVa-r zu!BK@XSmXjtO1b=d6+d9(#H9)lnbG|j7{I2rzwN9(0^r`B0G)He%l3Qz+nR7j+F}2dF&{(Wqtj82&4RobrBJ>Gq zZ9icP!SQhvM42I)LU5~X?Wt^Q)m}zZpR*V>D@#rZ6S|5sU#~4GJ$ylyr^V zUuF);boDv!f82^~x?}Te;~!y5{Q}adj_R@G&{Oy--n=`njBn*di3yPKPS8Mb5Fl@Q z?>0v3^i{TYkm{mQdNq{Mu;g$GZ^{b^QP!Ob>fDCehVr%OITTB4lQF+^{bsLco-YZfqKW!9X&_V{*>9P8dj0umx2d-#O2XDN9Aq+3b)_yW;SqDt>oFC=3bU)h0b9B;YEB;Kc&}*6RZGS5J!+GY+OT0dCMw|7ggZ5@OO7WIc*dEje3@5^pHmMLn*Ym#enQg+haS@f_k^1k-c2}fk2 z&=Dv}C=B8d$5|``c09lDk^&9K)h4VOh1nX+6!$8!5ia}@1b3o-7(*@0K zD((Y0Ni4J-fDv=;*C50D2f9K#qaOt0g61qm3c22h99_eQ!VI8d+ZC38J7xilsujlXRn$OEe{57~Hpr$VCfw50lf*;&-wlbuN0RR91Uw=seFF?@0^!I(g znQbbYSiGy*13)Xl^G5C8_AZueZ3lysQ_PEYx*S9LLcd7oUc zspg$-?fkhs*VlXf=)>3hm;H~3p8SH(H9s@`pB(|sXD84(%d~8M)zxV$Z#SOfb4MQN zZ~xIhUtHfaF5f5**QYj;o1FZBE(o+XauXIs$R)_LRXG{qWoGh4jIrrzYL z`_6kNW*xPAcZ}I?{fw!PYpV)ZYuS9BGkO_qSR1Y-%Ro~))r#r?8!Bog`p{@q!J5-^ z{UqtFn>pe+z@C)kgW(ZBo^;>Hc{rH0mC9(uz$%rtiIvtRO~4$}=cuVR-2$&@bC>XR z+3|4cwx!jw{Y?*XX6D@Iqs__R5|3!`d+|LR?1l>4d&{s!+47H-4O)q@4DFx8CS$WA zd0CTKNk!M2n+UpU2{QhgH9ZgCCSwDN;0vMG=y+_$G9A;^fph=i< z%DVGX8eb>q)91*$s{DBBJNJZ}meHge{V05$fI{>{jP48|YcuE7?%umLRj!Q+mHlC} z9I5_{Np^IaZpCC7!(nO{6lMhhPp{bu&zalBGHjJx!O+IEx-jNQpeJ1E~N zoaI8!5t0>B38=S2V=^x7XNu8W`OTdukITcV$ij9AhCWZ#V@G9FX7#^Y{)OpIupyN~ zuoM@nu9Z*{q{&^6t(-U@14B;ip=SffO;60l63#b*_vO;5OwKX-P*5PeY2?~?$ zB1Iv?%8>S%X&{o5i>Bk2+-TTvmXw49R&MZ)YGTd7 z3p8*EXJ8X}m3JJ01&WAcd+{-gUCNg^ArdF3$@&^EI%kzX(>-ghsPRwvd(x(@)wTb} zFz=F=TJZ2sJAxdumzR4!{jvN5etKF?N}m-06kxLg0rIAS*|Oy})XeBu@#!+L z<%(=NCZpvw7ls5~XEyG{jqh|fcc0{UAP-lE2dp#RMT_vDOAu6&XDGaiDr9$sAKo@k zH4~|GCfP-2bj^xqhL*A~sc7H`SNsCDn4NC7<)qLjoG8t$d~fmd{qj}6i5es0iYox* z=?H4D=g^!>9un8lw@Rf$UV364HR+r(5C-=2*kY6s-&#VC7P}pc;S? zn^VvDrML(NG1iHYz)-|sVl`E%06btE(-JrZ0CZZqgjaIU4@P{RKC6qrPIt3~|A+zP za4`k`n(pGECR#KRT-i+^q`zCcm>3V*#P4Mz4!A97dYA`nDL}$?VrE!yW7kkdGzieJ zsIS^BIttq$5*o%8uXX_d36-b{GNX|s7?_MjDSwbTGJnjAGakx&8(0+Uj)K-3Wk13*mjjV|XJtt6ztF_;4?Vybf)rOZTI zjwb~}eZB#0a}6Db%zB9mW)tyVpoRm5XW!MY6>_4PA8Pd(rodJOIjTH`xpMOU*VHd?YW0F6J1S&I%XgQ) zFT5{X@hG0NfMYL6UvFTvn$C(-b>bJwNAvVXUNQ*f&Fn7^>6M5GpT#~8sAD-U&lu4l zrC0=0iSP;(Kr|_ry%nGh1;}L!CPY=hMP_0__l_E2YnlKGt__;mnz1c#3&3-bC2Bg` z%X`7v+Nr+b*gNxv zn*Hq^JHIjQhE{}jOx5M36Y#0Y5Q-0>ZVJolE(B|_@G82+^qN{-4QSqvm(Fv4k~6(O znol@8PcXEb{*L3av*I^P43bLNsT8Ahh>%gH5E6lbums#`G>#S6cB&qAV7()%#;lmK zb_186Oy+m+)js3zxVVim&X=#kKqPH#*v{a2d1bn%qT4VmCmkDhFat;`h!~CJ(_VqG zzV9`FH1VCJMHqIg8Iket;I_7UTn(zjZuA;K3vF$rrC&;$TzPMA3E=qhx6aRP*>)0t zWuJ24`UDK9J#XM8a%s&BNe^o{z~gspGi7qhi4Kw{Q$C_Z(EokMf0F(~nkU#q4ZWTq zwWBiK2#@g3PXA2!=PwZvKVY-t}fek&Z?j*#eLPrg2#6f(M9H8B@Klur1S*FK^z*)utu; zK_2Kji&&61w1$KC0ZkE?4&$73`DCvV{i3E#HulilJA2k2ngsnU`)%g8`6BzC?NKIz zCbXnM`bL(d6f6a5C=r35)qMqROBod`MMHr^1`=P8wZrC&PCl8eECEi}LpeWkp-g|- zzm*qeP4aRC=3rX`Q{&-Pb=Q>fjy_ql_hiq@?&&R-f@w$~fVH@9g0Lr zw)+8>Zci`9{AI$vfon4$4BpDlSzS3{u3s+SdAzyu9K|7L7`-zR zNLa%|mvp8@1xA3xR{~%SS7Mdckor>kii7%kx4M%zUSNTR@TU+%N*8KHG#G| zMz&?> z`XRII%HYk$o*4@HG zg=D^uH|0DI!Bb~VM+^Jh+7GdY(e3+KvJTDh#XK78b=(Sz1_ol-0;%HE1aj?@&tI3G z|JHu}N!Y)AC+B04uLgPV=I^cM^$Po&U+|Wu`!Gc`Am7@4+3`k ziZ)2mYEb$$Q29c(Mi9b}qIcuHW0-@8yU<1r$9S+U5hw{DkfbmICNQDJ6|n*mB($_$ z5E5!gE3PUmS?1>o@(OR@cj1eBaW1p%n+)ip3|K;taSGTFZ~zdF!Zko1r!`*BUK123 zO#LwllqyLkzw8t?CZv52l8)=pzVqtAm9`E8&qvOO?E#n7&dYzU zcemU*#|xal7<*H{{=)p(=if{3y+*#Z;jc&H{r&LE{JVLQmBibpv2T}w8LoT(uVSg> za0pS&nP!;7L84n|$15M&TYq|7?G=7E^ei!vPt?ilTc*=%3hk=e`QH1siCaN`+&h`br>N@ditG`HCs})bj=jS0f-*Z_n}3X-X9Pf%QqkmggHvSW zLYG^X)T|jm5ruY)71SvMfrbEN04QW!RUK1ZmW5o8uVlgD$dxAdv)sG_U?f_#f#WhT zY9we>+-KzzljINVkx=%c5WouJBXt_RDUtY#Qz69vm% zv&VFkagl}~$Lo2{M*obr)yNe@Q{z2zOWnsegDm!WV&B@vL7#*oZKql&BBKrlu&9u? zs;{gMmR13YxUrQL4wAKAlbD-SsLT+LT~O^*Tn9Al&Ri{neTE1xq;>LV_%CVO3tb=Dua$PyWu~{fhwaYDJDTJ3NW){W<3D28*R4T!^-Qtxi$rfu zT@5$P5h!n%WDy?{zX!%YyQUO~AqS{fG@)y&TdY3Xj>=qq9&1R#j_8`Xyh4Z~3B%Py z8<0>CHdvKZ`RMwi2X~)6QSYENRQAFsqiu@mO(IO%@rA`S!^pTiVMiruj&lNn3?NCZ zRAj+}qmN%!pC4GoAwoVF9UYG@tZqFQH#t2y1P6@8cGF;t?J`%MsHSPBwZFw{nO5`@ zA3gnHwwTCUlah137TaZD>sSpd&B$VXcea z5kaPRk}C~rWZroM`k;mgVbcja?b>XHcm&;|jU*9H9F7%jfLjnDo4vSKJ!dN6mKIbX z-$4Njh4sK^S3K}lbp6H5k(ADih*FoC++wSF;U`c3>OQ)Ql=Jl7c)ctN1gOrb2(+O4 zNL2#sOwMG6dx5OWd~@dDCZfoh*urnC+==S?>&xH0nC~`0jKwd}37UYIoEM$}c;z@{*8O1Ly<8Xo`ZrF{!pfj%y zp$vP2y|$(m82|uQkkfatVk02A*xbB$SM;*>#C1sb0XxTE4`1ZXfm1KcqVR|4oJg^B zYy3E-bw*s>mbaH+(Pe&bfZz;7ZjAG+(`O=1DhvKQn3a^H~_pV)CG zCH>^tinQ7{d%OH=YjbAny7(&c{iGgw(TL4Q?q$4Te&v)r>5jRKzs&|R1A{n__`feb zuQtYXRDO8pUai4~HZwQ7md11Ih;IzK#yb9jB)fH|BA{W;j*_IzqeYpKn;IpJX(09J zPBcpw5#4cE`xP!ttrI91&HymLl}+<}RltY)@W?XIB*!6d@*?-1`9nP{B8%mKG( z58vnPKYzgwWfiT=BT`C(C_@1W4JfVgsyBVNj!Mir4W@^YrGRzTz;Twzwpzjjm`a^> zh6tTl!8j{Vk6zZMGe><5^J2k39Wy}ifK84Jou}vd>}-gTl6W&i1FvZW1N2}psK993 z*dk}XQx5_cwT3+&j@OrEdCTaC$MBUu7)=teCF|dkI7SbWw|{1UQe=2W1^Az5mEeCaiY;FExHV*k@kwd z6aF*U37M=!!sTDV56geTIMi{9hmnG|*ff=-q^2@ByVeOUAUc+Ise-ZE^`^x(Y23S* z%tr&iIcu@y2Dd$3qK=zlS`;W#KXNY21GAB@ET7*`Uo5(GSNvSuO#ba>OC#MQk1}Vq zp_-3{wiato#`5e)zHnqV(FpxQ}V_Xid%MXF2+Aq+3)t^7_$_sgMkvp%T@i zr-%$>3Nz*$#l7jqxF?GYG@KmWN2dzqE=w1!vIJx^lC*yuz!e5dsI+C~c+u5RH2HSS z;cF)DMdK)Vm#5=t)!wfA_~YQ}U-jYsSeldK$#;DB$L#Q7(dRZ?>05`YBTXdkW9@!M z=S{#_c^U7uPH%wLSjW-8NWw-a093&ZLSxKbeAp@>wHUU0VYYJd3-PG=;k^Hwe%7{n zTH)&!-GbHT97v#(vJU8^B;Cp!v&qhL4%iU);o+G6t}ty1^ja>x6F0Kdsi6eYu4X|pM3F;Pvb%$T1+cp zyI43{0hCo4i3?@Z-SIXQbrmu&6aqk9y#PpWOal!@w8;@exGcAEQ6|acB?4JOy5^>A zz-L1qc|PjH_rdE799Y#Dp<)nYRZ`H47t2fTJUzB;stQ6QrbU!dDF-4FwawivR-KNH z-|oQTFb}+8MZ-sVOApKaL@qs7`~CmB*Vo#2_O0Emxnd5^6^=Ejg&mP|X)}zAM<5|* zxbaZx7@>QQB%@lUHElQqX3!E54s=vDL9f_TnszjM_76@yyWj4S!>o|^T(^u9aGbX@ z=cjJ=-I`UIR%fUIaL*nVBhZv;?q# z!vPkQLKQk*kq{v3XmC*C9EU?W=r*#9BzHs(J0^lG(JL5DE#z zh%5nvjEM{Q`16nd?{oWK`O7cA`0^=vCJF#RQQE2?`qHpgCf|O!znJ&$f9P$8$7A9W z24(n>!7sh<7o&J%Amn>|*y$&y-d^6?N1hwy<{D`;7)%7A<-vaB= zRmaggV>?d2_T$X>*zH$`FN z+0eCi^3!_<7Y=X{shY?LM3W__Mf1Ab1_&RFD5S%a0y~y(qbcB;Ox8hmOtyQJ1F8$u zYnE}-mqcuDE!%Dp@p|@0#LqTbMI`HMD3QY@}tX@l??kVPDx$7`D{`@i&urgDU}* zv;~of*sJM-=JKV|9YRd*=g45NZSP)z+4Ion=4H3%(h1k~_nzLn1QPF@`Iz2@=FVt( zZDr@RX|A&P4>r&*%)#f(f*0fx)&KKD{b8$rRFv_2Y$Fo(awFNzMBOAELl~(xRgc6_BJUc21sbHgmBinoPMBATG87N5|=^ zy=YF>n>#Wfq&1bK4d^YMh!?pU92(+O5lT8?t!ZaL`3O4mLTIE+Fxd)fSCZBB`z@8! z81#ig{RDa%!;K=dPH!JJ9ae8!Hkve*%KD{Q2)qBG{$gO)!?i?;wEw1|ml8M^F+jbC< z`X9SIVu&po@w6!+E&H&o%mef0h3Md3t!zWg;t$cFu`+!njk*xXz&fW(k6*dUVKFY7 zGmVaZ(gJSjRn?6r1L@MSgcW+G>4Gopv2v*TE&o%ruZ>YbzwHaH-vWwa;WNFy%V`r@ zsQUe*SuK*ZpO*P}OF+fR*aw*NYLb zVVI~82r7VdttC>NJrQUcStRSzmJu$G-358#)K?e5*7?@OBmK*!mzY3^EPSr&sA>iT z@+eJc2!<5fx1O-UIDrE)!t@}Jt|JcW72##EcRy#upw6OH2#Lvrxm33L!@jvKr#(ER zH6ao!HzMIwgG1sO{EanNItL2vlsS=Dc>Kw?)cttS3&%r07X?=6J4M z5#5x;R!gu4G_%_uK`%uJ=?lLJe?Sgf0!a28f@tcAZPFRrZ0h@Fx7#pQ3Vy0#1b&Y? zCt9!;l1+xqWlSY7Sp$m097tGW!X+w_j4U%zEO8_w9weklgkukJ!35nx#+NH+kE0vB zm(8gShx9OuWnbBHGRs$9kM$mvA0%^!I`NiYrO{ z0xln+_)*yW8rjC?FnQ&#$)1WA3!Vn!nVeLE(iw2f*-QKqWW*O^qkByV@~2l^*O>TS9{&s`1gu#022KbgI&?mVO7rciU1o+&-gvz4*yR23MT^3 zbrOpHeN6VqmZAjY9)eP*QF!{_wN=rEXa^F1fh1_kGcOC4tssYO+lFHFmO_ib$$<1W)jDiEo$HM}+vGL>?5e&Zzr z410Qn?Tb))wNi|dcW_T{znqpXu!ckUx~5u{!Px}5@)o=qgA76`&Cee26%(-2M8r?P zyHPT8t{${ZQQJ`<7ItwY3{L>ydvS`Z_;&pDo~-JMB-bTy2+*!%yXEl&+Y{wE63iNc z1>phX9lhCX`}rJJ@`~$gRG5St0|N^5C|JR(dS7!5O;W-JO;+#YX zH$4W)pb{su0!gV%0YKp(gsW7Hks|02Ey@`cXt!uHW{#N&xR)GN8PUM!mgu4+7MaC@ zXwED?#}5}PlB&JxE4nU%Xd4skYOMMiYfN3%(26?;s<|;TwuglGoE&{@zeOZ0qZtSy zK!wLSR6Hf>mebli@mnq!l8_7qWH5vn7MqEo3?*wrglOIi_+~CabJ~E6*>YhH`gy+M z&%c2Gl>7hGf9+4MyvuF@(x1bS)7BCbwA@I7HBKh0!_Il3CIcv#4njX(L+h5RFQJHz zpwDsq_eT?p4uv2UE&SlGlbF(#dIc#cq>i_sb$e?Ofg6{D?2I#TMNr~;nait{j`Kov zAiPrzXDMyh{uHPU7FNb57e#IH{@eMVLS-Jm{_DT?isUJE z%azB4O1TGia}ulN)nw`H0PlCLi*cu@rkiCR3ReKD{&?Q5?>};-%`w+How&~gfv{f4 zzhoFN9=fq!nCukFYD1k+X(1qaDtW^iH4PbU3=j% z#N?13bKUp#s-@IS>6^#aY$bM4T4Mm#rbyuP!r=Ngd|c$1H9@)z`nG=yFM4tFI3r@`-G(x- zbTlKBP=d0VB*AZCu++DWYsE?mP>s%YbNB)rY~}kG!^0tx73~>fQVlWgncS>OL37dVb9T~ZM4#qQQ%8-E+1bO#a9rcMCTyTE9OxJ_5zN?WCTrfI8rNyh9 z8@8}e+l+|aQDrzLQffP@AWU#E2*-7M&}j0+{5pT!$G7+UnV-?{lLN7&hMO29`bh$= zS)d;%2UmnA*XecxqcOTm4Bb%UdKqZcm5u|XVNn#A^mFTiD{Hah1CAXeXyMMh+I{rn z<)1w)hkH(px*h8+!@1P98|j_M2^TTm5Q6F{9aHR$kgiV4iW;p(Mo0-mDg`IRIF-tZq_OQ(&VVz^u*ycDTZwInP&m$@+Ta>I zK$k~LBP(&@>wns>_d5Q?pbn0BG_5Cy7w>aotGpo=(} zG*RCAtZ3Ar?6u4TXKpq}-I|E2K`oU+DLZeOHPR*&xDwUr z-Z$YY=u@+=M(2BP_j%6!ot`^3@-oo9R+D7UQNJ-JXIh(euKi|iT;ft6BW|m{eeqel z`~H}ZQ+?*r?{SUhx|J`AhrCC&!f=QbqOo?aCZaa2fw;j1*e@Z_$dSM_SmMGkeWld=NU4kz;$x z<3s_GXbjG7I*Zc)7oXgbpt=~4#;(ut2@;%m`d>PM)rglcMRKwRk!r0G%m^^;GaT30 z-dse$h2Vo{3w<&PE|ddEqz=T+Qnz*UN}1*&d9E)btmNV;+-n4+l6%Aj&}a?uWT1kD z3MtxxK#EBqKolTB(F&SgAAc7=eO%YS`ttq%SfQ@Krz(Y9N0ZSfK{HQZ=pX+j>e~K` z|BP&28i6tV_DBav4$R>+HvnOG8Yn12xb);(J9<3U-d9oBWOd1mkWwKPB4cGy~{r8{&-M! z`q9ci9HMnzdd}u^@ay;EejC4CZ~lj${`lJYtsE5b2vz_>#h;u0TYv69^e8-beR-v% zTXoov+Z!AOS-73p8zzVHnt3kaZc90j`-%owMueKuRz4=g^19w%_1n2+A1(tO5?@Qt znP9uU#yYC+teD&b%s_>#E|09UN5)GJwC-`r3na7LN?+GUdgbpQ_m06oZ-W`)L__p= z$$dHJswyYl#f(48{&}|lhka9sXa`Nd>F9p8cVY%4LC$4MR*pF|*0FETHCvG=VAIR; z%UW8OFCn!#D3ct36|x3LGkQd3>_LH`Tgc-`_e7x(!2xZ~in(?hFD1F=(6`b$iQMPBFN=4c^`0N) zo%LsFE{Elo%lWc<;pgxZomnyup$(O=q_jIvzikDVGQz`(G@Hh#P1nE$cqk2|t6hre zyr2j>L7%j{+CS747sG-{VY;$yI~Z@($I1p7bf3`^TsmU_hOgx#ig^q0La7vh`$aBC zEFD^Dti)#oQkJ3ZNM+z5?J)=}6;`eKQf;PqaD#oCy%2n4@l%Xe^R1e4CprTP z)YbHY!^N~5odOQG`>e}w+!acoMiMKoBORJd=8V9K_@W|s>U;34PdkFF=~CYw@AT#e4xQ6EL%M4dqhQ+o|IEM5=t=Lt z>g+lREXsL9Ojq^S?$vB^E-Dva+*I7;uqZ*RS)&e=41O%yxlSsf#gdva73-qWnKYIH zGMR+a2|;Qh<%x<`UHH&-edO)B3C9!Xqqeu zm_Se}5jM;@K&Pe=vSkl+iQ^_4ZjVwG0`v_uM+OqvbyyBEa$jOe(UyDBTf4lZiY zc+%(M!p^5oY>bH(P-tv%CWGvZAyDQ%peR;aQoCza^MOf8WhLlED>$YJGAr23h`>~0 z3=?2MENBpkOyIhLm{6RlasJ|PKD@~`{%!EBE(40?B@?S<;YGD!8Y39?g<1qhFf6da z!grEN5s1+PLeyD)s+!tS8RDfMeysU1ZG5R71~`r^xd755`+`7|*_mbg{R!g)f(I9T zLX#WMCAME9vfkr!vi$a3oKqV?#rUAH&ztN ztxmv*z2Ika8oo9s!AWB3U*pB?6P&=pg^T23Hf6kDhIo18c4h68Oin^w82V1C?ziBe zo=Ae8ES4g5(I>vqB{bY|LY$`}oe%{){JxQ`bqidK?Bwmp*Y705bqr|mSElj4?49Yt zPj|vc!#6v8>6_DqenT6MlQIk|>80UGT$l@PchHg7D0nHTg;PAaBz}a&G8nkR;E7nD zuk<8FHb)cWTY8IL)MI`XY<9wf6^P2^ys+dRj;9tu7~ZMngh|k@Wzqy(_{2I+*Kol+ z)HROVk5fHuMDr-ZbQG=(JP4hnfSO|X1hobzqcdBggqj)g9N{n{ zSi~q`GAD;jf;DQ?(TOC<(PT;JZ&>+>1K12GEd@gf1fUu69Ox_hHveQ8K?aiIS_4O_ zI5!>I0e9G#Nq*9V?7I6JoMU)e51^)%&?yCt$N}g8`gjMKmRkaQ=^uIufizJb*d#91 zya##=#VHA~p`Dc_H_WjBY3`%ZpYEFb{`2@7aewD&xNh0~{JMLb-aqc|gYP%)kbB}g zi&olH<@tu3b1DT)%f{2jJ#7#Hm>WVWIvL{Nup%=9Zk{+5JG2wO=pE}+atw|$THZ#b zkb{n6>UJO-$rE!=pg&fnvd*$=G7NYH(-^o8FTw&*YJ_*6pIpTO+{w$|Z_AQ4izzy; zU+X7vU1$~BSM|E=e$QRROVDMWuc?+g&FP<+BsK#&$iV|#t{#F0WvYB}(J>5B+QS;` zBkdfl9`=?@DFYwddj5O*=Ip)oyl%8k!b)L@9!&KKQ6RLI<$jLs=x}Rf9s;6DG^oU+ z6ajmL$om~|ON#EY_(sSMmJcgu`9Y2`)P{REA7kfSa6e=@?GB{I(v*z`T-N}jF6gMI zx;@>G`!+sFTyg(=k2i5|LLz!pT-Ph$ho_lu*^a$dff?uh%=ybKmE-3)8s{BJ2-GC2 zcqkCxWWG32+>4V0k~-f`cW<;_ygu#xoR*W#$xdFZ8OdzGDAk*4NdQ>Dg=WAeFCo-) z;}o%5gUh7!N|MpR?(kx@e-jiP02&ocXq0mecSv#GX0(p}DI{I7G$)n%g;!*YQN>^z zv0-}QY(I1FLM!aHF%`SaZrbuIyvunJ zFXifsPM*1{4IJ%fme+wZ;O|?>d3iqUy=c?;703;P zsBHHet=5_FFaYi{8_rjOqvh5%C>?1Dm#}SBs3R2{aghT(+i{ijqA0DL1vg;zOTE)M zP#gOmv%}bA)IYy-KLZ`OY3eoDFJ{Cvl{@q0;M(oBm+&M6%R<}+tw3{d0FX$iV&u0A7FU8B8VP=`ds9pdYAGyeTg1z`@lMiJTP_iPFDj5-E06>0g zOh;!mbS7#Wq>)MiQ8WBmf9qz-sFIi~^9k|^7Sj%w2#K}gN}K7-A~~askF^vMm10Lq zHv98m;@F=M#?GL{FP4SX8348mSkkB?q|^0h2VE0UP~{)_@O%Si$O!zEDc}=;Fkp&u_yT{_OdU$ z>=`|Cb+H{8b%F%(I*3F>A;Q2WZRX`g&QCshX1~1b7`y*rqaXI`ODFhNap1Dy*_?gR z$L;kt@JoohhnBZuC;T9KQhRvsGGN+NqvfOR+#r~8T>AXnXNK#w&X19Z_4g25d(_Km;zlC$0s8fQ?ZejEk-2%mjK%TsLY7 zhQW;Mv1Y7}MJ#2C6NOmVF`sFZ$yA$yA~#Qs{vBAtWHFnbFp31tkQ55&)f8uN8-YT} z^>j1xK;$ps)U9BFX^jub9Hau=0(jVauBDayqDRaiMy&MWS2KFZ$TvbAA)qS=uJ4pw#_LS_>VC?Gu)4#f$k4u8g`Sih2hQ40Z zdsb*xkD8LC0D^y30yyZfFW`JEC(p}+-08kA((Y<5dm;Sc7>u>8rmuLa)brr_;otJ- zvV(T>>QSk#ogaQnm#fc~{Zx?SX-4Ze^P9rCUMmXvJT?d4)0N_VBgbCjO>6Ps_^|;z zP~~Q3Ltua@sH0ir>>>VHETU-UxF#u?_!C>)~5F@+B&?H{X6pNUHkWrR7-O;9Y9 z83B`nF?O>iO{lXj%(ynPr5~G40|*tA5vZ3{@J+4w5kAhU6G20 zc2lnk;*;j-50l6W-~wI2t@UTw@0VBOx`Bc~<#*Z)?Nj>%p%65S&RQqNaWj?24A(_L z4VHdkJ!V;2*gIWIsxr~cJ*#vqb3L*vEp^ogRxLy;418-`ViH!7M@)*9-TEfwU@5n1 z`+#c|da_%fx_p*j<7)7Ji)y9v*DFT=OlSQTzo^X_(I;$FK@cl+pw)3U3fw^+ZBTMj z0^_~3Q5o?>s0XxMJy4k0XfEyOuoh#aB#bc`Rzef3lv?t|XB_2{T7h&BMgV#;)_j^^c$21KM_Cfi%J z?$u0JfVG^|?wM}e1=cR>R)rNr71Wi^?;z)-v20E@4mWdWVg8<8*{1BBHJ-rc>qC4h zb1y}tE9kPe{E94pa*L2<3E97hewUt+QBIUziJJxcp4jI| z{BJyQ%9zQqhEhZk^5}079q3{i#M^ve8!y*-FKzc+KMYex#F$`N*pA(yAqI8Aa4Y2y&^)Q!_K3(pDAjUESXSp{9d%r?<-3+mXLb%U#5M=~kt5n_r;&b*FFOvY`(=VE#K zNyTQZ$Y5>^ngk<8bA*DsPC%pjVQr!YBmF0Kg@BI92-s$r6^H2;96^&I);B405PFg$ zgMF@?%kVB}B|u})IglrB!Yg*aW0v=i7uP2|-iZEN_&w(L*TeTY_m9zk9{KI>756PO zzsz5b=Zibj*UzY(AK{9^fRIQEx2wlI`!qznTAC`A2InY!%Kn zJruj3rO?Xj9#uF}2nWs(A9|t&sIdqHu#2v`R!{}Rl*~qMl5I&=#~J>}Z=xqWf?5UZ zw_YT=g(JnEzFN=cbc>9_IA^nlAF!5x@Ek12K4KDWwJ)18#bUV=&zYZ>R3GoYJGM(z zDbOwTam-xoHiT?HBi^om`A@R;>Sn^GIGms2B%0qEGnCjh&zIJg30@wjVR zmgQR3M;a8&v_>)Jf?d_6agFsELIz2Yk9Wmh&`+)2_-ln_Do`NA(^{gJ05c8fiMN76ZLRRvL5hTNGNpLP5EZZm+EEs3C18*cS=i35 ztMWVTM~5_D**3Fu|GdoEI!#}6-xnc1Pi$x1MIgMMz~ z*=3^s`8^G$?$kb`#%ngv0lwfLmwk@*-2Z&SOYyeZ07Tq5z0ffsTE{w1=r-n)j7|bd zRs!BUlT_&Kl6*iaa}cqHJw+KE^xWv3@(GG1?8yw6+kt5Iu=jXYGi~Jz7jgLQ`TOzs zFK71qyZxM+eP);Y5SHuQE3C+{YHQem_Fl`{st#mF|?}gvI zahkpU_U2da3r)>)C22Y9Ui+e_LRxtF%qqH*L5yk`!_s4aBv4CeP_|@A>v$y#GB6Os zT5$ozT!Bg>pdenY{%T);2t)lX^n7+XcW4sgqnKe(P$&XoHdhSxr9sqHTVhnrTP0&TTQQKp;zo;*RV6Y zM%f8S01%21sF8I0Vkdh4>B95h2Dn3R$pwfdU~$x2pjkn|>3`{;=`e)10*5*y{Y<{!qOXzs(#=vMY&nf(8$%4&pd6&-YH`47=K8Iz>b|FAlLIQ>o^yA_<(ut607y4^c9LvT8WX~wkVk5lHHbco}ows~H1jsU`a9)f@&tlywm_D+ z1V&`ammCTL)6;QMH`t$`O1XhPAB~MGyVI&Fuwb_Z?794x%K3rsQ|WDe~dTO z`c{j6ySFIRZjQ4cALd0R(|TZ^EQx4#rny9-f!_C1e$*11Qb_>>VF3U_0$C`Eka<+r=l}Ek&rjv>Cc+KR3JY3vuLY*KfCUfzFa_wJja?R?-%ah-UUDN&ueqsHjn*f{I%6{p1aR0S%Y>m zL1;56$7PCgi9?Z;5f8>zMD5$734_2zFe*cXA!ZX>zKRP_ zTbMvwDFogj6J^m8LbRk*vGP^$U^;AuX(rx%744r#(PEa-4CL5AYLMNW2NfEFR7s4o z%9o5J@63-Q%8)zQFggJc*zc@h%qS9ZhM!R|U&6CM?Kng2cmT#dw=e6RgYP5Y?pALt zMA&t+#h7N%g@ttP8SJ!3j76$XBw8Z7YVb_?c}{1FgWcqwNIWrT3+&-GW&e56x39ls z4JT%NJG^scEmKAm#Sk zNYXLJVGHU|qhZ4&{=Qpd7XZ@AUUsD-f&%w-4LvmVyUf##dKPxB+NvsVCC}&Zec@6- z4HR@~4Fuu$QTK4toCS`|QEvb}LB<7TRF?e8XIXV+{Yf|5Ev-@Pvhx*j{ zZ+@m|UDvyYKAt&T^>5sJl&3;CyL6`90KZ%~8)8+2b)1lB+)C4X(3vlTNCX9TeqSS> zKl=K$%enqd-gpG(Z#1Q<7+b#;v)V>H7qZ%MBAMW&jJRshU1|UR>(5=MOBD=OAk`#r z&-n5dcgGPRvT{q=nga^ZC9iAS;j^3~oFx>A{Ki_K+d+p%83L$D*BN$FlK|!$7v-}D zt|^#v>zqMGdO9m>HCJJ;tXB61Io20AolK}1gEC$Wn9+*?Bo0uW)D%KkFmVCHmUi8` z)pMe4t0s5PFIDL@K-9{$T57^dbOTN|$6PgSaWdE+lUrv1l5>3ZOZZf#UXD}*uEn)$ zJ*9}oQ8ZNBHwnN1V+e(mlO65>s%S14<0gR31oD&wn`zUrtTuc%tNCw2lpn|Bo$8Cd z1de)Am!BVS;B)+nwRo0S+C&6!1d->34G!z-pvkG7F!85Ju3P8(Sn$ z$4>l>`4kMER`%l&@OMnZ2>(uNRQ{2!tHBre2UC;?mvtuX_#&JJ?_*(U- z)=P=V4aFweksEtsXmKO{XOa^^tC+e4kS7m0BbEd@zSEP$ zyBaiJFrl?_j9iP@iF``{HhMrRC{QDOE$`yWfaTe}sKIzn|93Fc7SiyQsMq0k(QQFH z3!-7NeZ@j$`P;~13A$BilZ{lXFu>MrAH)_zap(1?YypQPC%q<#w&r3St$W$dR)|fw zU{AI;a@kw2%9M)|*P<7|rmCQ3RcbwEMijzZQfO&mIK*k|bmX=&yfgNzQr~Sp3H67g z630>wWPrB8s$^HRnXPVscuYIyxmv7qfMtzl$lQWsGFu@S%OE*u{9HDld4i#EPcvY1 ze5NHoBw;uzH4rdr6464m1sX$%(^WmvlWz1(G3+#ujj<$Zb4(CuVPBNo22ln3^1pAmPMz9!TF5GQ(*b7?s=Q- zCW4Km9N4g9NIH=`V zr)@`tlF|3EN=wr&Swt&R0bGI^BZ=5&875Zy3Cub>|31PQUxItB@V$t48#_lg12(rD zRcE;giwMiQ*}TDMHp!=mYf4w&L8hQC!aB?4815^$;f*~P7hwRS)p3Kj`eum(-r@N>A0N%Sd}WY)aU^AX(!W5f}%f8X#=7yne@POdz#cuR2DJT7*oa@>4KJPd`m{X8bn&c)!x7?~#!}TeB6-Q1^Ucvpp zy=U(6JHyND`*z>NeWX1b?+w0p#{kW}OSjTQm6Ty1JzSZ5bhvpTTCOKcfd{7N+BRuk zsxJb@k&$9#FUXM(n?QFRDkEEIs)=dHMHHDZ&XE}~W>i^?WEyDV5iPl7lv-(kh>Tpw z76d@+2CPH{&;tG6N@acJJ$I~2X5Sej8|PrCb}hSjdcu&nu7bY1ENCsE`cZk4v(1k^ zLj-~@b~o%=oKH22uzLY0T1}_C{6QTCdOc8|LGuJ#TM{so{Lzrw8u!HMKuR ze6f49x>dP#xY0h?!07>Y+)>t|r*)d@jla z;uS(DFu)oUV%^d~V&Mqdv2QlaMnw z5ojVn%1TOWo^OT@8VMT!>jILIn3&R8aegVyZK&adofa~5hh-~S5N!oDK~Urn2&U_% z^NFzbN9+f{A=1Q=Y{NFzmFx;CnKeiy|8+h82`O`J@%#1I#-0eS7*yuY4_XjNz;plr z1SSXyt)LBb99dGQ?>p~bU)kqdTAtEAGiPVrF4ovsYLl!XV)jf9T->cVtU0Xs{HFH) z@i*76qR)TmFXr3K-n?ldD0m#SJ*I%Lm*-riXtN>^BOJ8x@(Dlv!ELRnjua-T?w5bE z^_->edb_pZ!v5qLJC=U6`p){rNd@fVqYoK#OX+3LAKml(_u9(3Kkxf6#+dhz)Pbh%}=)R&}#AL1s&8bQ`WPVi-p z_Suo`3u{uFcS3ph)w{e3xBv@)^nV2uEM!Qr13Iu#gb-+Oc;t}jqivsE%tq+Jpz|K# zUCrIc$Bg$K?vwohf9Ty2ZgK}%J0lM4t(k+5ehIzC4~n#3amOHCMDQk2su?U0clGLENF>#NzKPu z&RVT4T{#~$Pdb_CIqpW|qftl2rB>KZ#Lys)`x4+1Tv`>QjyX6P7Al*Cp`$>_gU$XT zb^qE?ZmZHb?);iXL`qodtaL?}M~-o;`Yd}f`>?HaAVau>jC$a9${f;Q$ZKVJDcCrj z66L8a+>55?i6)C9V0N5^8B0-@h75+kc=kDWuUWsAuP^KAtwmUXbeV5mKaNt_QNMrp^YmReFq9q*;Fo3i{3t$qfKahD3N#H=H$*>=za7IavQIgo zJ&9%OM}ePJgca(_DMa62b!PT^1_{z2hKz zx&|PR1jsk`*khtjbUd%@W%7VClRyUu_*f|G#dS`b2~k+KtJ?%WgF{A`Untj=Mz{~? z15#ccE~6X0C(Yaq749#Q7@tmOw%}mxZoFn;tWW{V0|qj2ULa_<2(JV=n{>_X^29|> z3!uqBfT#=DpjmlMZ0uygN$@2Kv@N=*EMQe*TH!8U48m$@p3)y--D#pEesW^%nN^3- zZ()R=!3lDJPDjLfyvj0{#W!)&YHSx2L`ILdi<~UlYzttyU>F2b1At&BBe&4Q+eDBX zdW&>m999J|llj)Z@t_8Eg*M6c z%(M54yR3MqW>4;j8eN-zm_zW+Csp*0OQg?8I%z)FQ#!`49S$9#91Y9%3CTA?+801x1SW$pScZWnxW zO8{$jFz^}Rz@>Gl^>e5D2O3J|$8JTVv85~)7c07lO$l_d)u5DmoOG=>(j~Zrs;+&~ z(1I9{Ty_#USrTH8t3d9+GIbr(K5WOTL&di3rP8|D6>pzdGEQ=}J!;9mD%E;MLA3_T zXrhjNgqdQ9xRMC0Y$2tbST&SjaMWm|+@A~_L{P}!4l!^Ij_3J~ENDW8Efla-Q>jKm zJvq5I$UJM;7IZBqWds<^aDq#xQK&XJFo=`Xrqfv@Fqp@Kc7_^ypbwJmb=HvqOnbNh zg=xzWaNyXq(!buW+>*CnepTvs02^gyaC1R+Yil=5B;V}=lvC_b0Kf=@niPyFnzV!v z+Nb5Sg2+O3L5s<;tq4Of7fg*4MzZ2ub%<)cKF0oh_x@vc1VGKVk~fq%FZ^lvsd`Ir z20Qar5mXEV{Sbd;itfTL1!9Opfa>T8>;CZu_kZQ|MuKX^Oz)QevX}p;>#;JN9muFk zYbtK-G0RHvM9-;f5>!Y!DliPPp($o2SNAMbx-&cT5NFC@V+QKt=zFxaxW_ub-iw!? z&n(YsUZ11+Yq_T29~QChK(o08TS(n8sEq6(2h$a<+>Q}W1r>#~!8e0ftl{coxg%RW z{KHkq%^ydUvt3}GuRPtabe{L0`sn}iiRN*-ME+Tsdr^YR8e-42HIwH4Qa<^C^1;_N_N4W zs%SMKaJw^J-t(`+kH{k0>aNOxt?uG%Fp7pOeownkw7B9~1YpB<8Zho!Mi8N=p7o=o z?S}wE@?yA=TKIPPQFPo1sJZ?QYy1Rc01mj<($BaDtr=Y)p$-FU>MQCIVgQ=?`~=~T z)OlV65In)nKg<4u3bqReofAXT56&c&R}gMSi*|c~>c&d2@ZQpAY7x=6g29N$WEL<9(_}ye14WPdisuJdD^SBa2z4uDN8W06^-qqwru-v(cGt zGRg7fluDqkkv>oN4E~lK?aucSkO5)TQY{-=FELCuu-`13+h}i>W7sTz&h_3szea9Amhe#Txo&J(9JsLjqH0k|00;<01gVN5HNcVqs8+fna>6T@ zgq$bj0_0St+%nev`t(xt%2h6d!k8Jf2b0pYy?Of@pG9|WI=)QKjTZL?z&qi!)oohJ zUNdYq4)sgllWeyz*DzKqYgPv6_FpPfh(PsVpiO)fq(#V5KAbB6Kz12#nwg4EECv2x z{n>uWCgiXGP5E{4Z-Eg6-o?Zb(F|DHW3YfZGZly=n~Vts75||SPyi4lW>V!_Vy zf`9xo-Ou;)hv47u_y3!a+o=>gC=Dz^r(T8T0-AIn*)(ubCFQiNFRN3ru+YVOy0hzu zmZl>rCJxXdUQv`g;v}g>+o>v}cy+Julk_NuGr znNRbP*|_o=UJN22st|%C*ZkD}kdO2`nb0<{@o(b9B4f}>mCm<^H*$J9CRW|hI<6q{ zwitBwAXLsqC$^hFrc(yaOy&MUosVr9MZe70T$D?2x$L`|@xnG9s$V&G)uE`#yw3z0 zt`zHsd496iI`*F*-*?ZG9YYHekp-EtQmhLdn7z$*JBU@l4nDYhRj;aCz!xYs*O0B? zLRvX{_+*KQg+u@`Sv^cMKYagK|1n%85s2idS5bxI(gsKEE z1PiIKEHJ{h00Et%j@);|ITf1Jvqn7c&=3=3ATn0PN>0+Y*Ci93?#5ixC$9US_uJc# zU;Nnijn}zqH;c`~N!bo?0EP4NH?LneydWV@dAowm)W5(}BeB&lKdX~w|5x{~&Z_PP zY#m>PGRxU_m>)X-j6S*dfT=@f*%21hd=zxFAL_>Q$9=xW6w5iRTT4BS`2bjpa5nFd zKLii(L^2jHkKQpaD7HhAR}Ebg zwe;{m;W+b?=siJFbv~va%|kZ`pLs5hvwxAe8yvYf{r=k zlzf#{ICN4#a-7w}PT66I#Twq-0*_ZzWT`!YdNznO%&yU0OiP;2F(_j^uz8=a|5V|@ z!6aoOBm25C7TB0B3rJK_oi+;7y(N_cC)Cj#i>ykd5G(~7-G1eT5rvW^)Zvtq$&eOJ zOJtv;DN4`Mq2Gkarg>YsJ6d1z%l@+F)Pl>|v{)fqckuD}^28s*7N7g^XB9CpCC%l^X=>3bj}ef0N*;| z9(L$FGko)s+P1^YpUp0zEb7ymUozlahTrHVk=Tta0!X;59xXrbcp-P)B~J$tilZqb zbP!o($|WKbfI+0tx71oMfICUbkkOZvkrv64G4az&+ooPN71^iWG0R*Q&FK-@&9jn$ z+?{x?&ndp3Ib@1O!n%Ih&e! zW;h}fX2~Vg6Pyu+Jb1}^>#>@OW zdv?zT9|8mzaRL71@Q1HOUm8XoA#-Y=!J@V%wq_{ zeKi@I*m#@e;e%YTPNP?0TGk`Ol2DkbWzX;V>h__($Ne|!yQ!bTl}ovi52R988$8UK zcU>>V(83S)?-Tw#{+KW5w(4hizjNb&XU+tF!F=BO2`|c7UEJMZWOH76)C>dw&COV; z3tPsB0S1zWo{lvKHLNqxEPzX_j1~c?fGDj9VPB?axthEhuE}cTx%57w3Hl%A;*YdJ ze56z6FB$mtfUqMKd7K0cE4Vb*2#I(?KSyTbf%eF2|> z&zMY|^*J72bNq=n{ahiTVBdn{m9sJ=O-;#IY$l~`c;oqYuWs~*~3zZ z3fK?>ko3g*IA=272J;B$!w8!XGTBCSk3NJ72Hz`g4thf-NT*3I#2BDb0@#VPgC!+g zr1jAl1%R_6@7Y&HX(A0VW5b#(PLv$x1%Q@#z^e>13^bOlLAzo;*<&Fm>5srnK~yt} zbdzrW`XGLrU6tlyW=0|65v%<1zm3MWHkOPIizK!(XTSZzP7A24It zUe29^C($|*9&IfKAz9Z z{h=Dk*8^z%$3QYZIp@01m?vjv_V<_T{>#(zw5emOUL9L;OPhqE0IU|ULhX?aB=ti?!0vTASr)#9|vOl`3K;$+RX zdk4&cw(f?za5_$%V^CwREYtCQK#2>VPJVXviO#d*5P-N;u%F|8yt~3`Ps{UQ=LUa0 z+N^LrkFJ6%f)qSH^suKB!!?!eWTyNsFa6BKPwPBR<@*rSg^2xrHA~DfG}Cj0xKh`002T)#u$W%2?!YrY&4YU zule6EJ5ru6urmk}N&T34cEOwCo&0~#?V&6_LjjBu89Ue|#p5-(OC4Q94$}>5!fOcd z-*PoJb(ef6xqlTL#ZCZc&)8FAd}5s?Y#^x+Vj?d{L~GUbLtG>k2~oESQSVBv*$tg_ z`tjZVo?~A4J~gf=@AFxn|A8%bIKdsDS|kMq8fgYO5(p}alXG+ge|Cuaphoi#PPkwJ+|D)<5+RQDWT^*2ZJT$^;rtw}nLpE0f@ zm?(GJrE&m7qzD&~5Y@dKQMwcIjqFNW%9^;-!oAr~rHUbzW;LLg1^@tv0007ovJx6( z4FM2suoRKcC=^Sol&Wvkjv+E2Vk0Xa5dq*5SbC66b*GI+IuCA7I>t@DR1Ad1`II~B=IV9rUuGX6r$687VC%rv?h_~03emKiFlTk za|E5B?NLJlWXAmLUk?dr^T7M#sRuEa+OX~KkqP1*(E5|m&U zMT|vz$WP-GK?OW<{-!^D)v@+E`ER^F_Lu*M>Eq*X|K0z|(&TJv$Nk0?*>yg-DD!Ec z@aB4yKm6r9>)ZE#?e?;EP=6n*B+_bW$vEASqh^_tHVfb&=Ws;1J$W>hXT# z006KJU`UjcCag#&K%wpESuu3*pgq&{hSF0t90`rk98Q4C<6rA2ttZDMVSE)C-f3>f z?v58W{>Jeiojm_NR{ze*+fUCLsPfphW!JWPxgkAFzMY9VsA*82vRI#26oWPaHkuA-jKMXZx&Xw974YYkP%%%jNCd?Bm{bt{Ewz!80^w znjt*r1I>&k`6=JlVROdNyxe#PG$*2ozQV_gqd?E&9NSGX(#jJc+wHksdhhG{bGx%& zKBZ67{ptly({yp4rgejgg8Ss@ZDBnKD)9u~5FG7ajK#7WsDMhsvRP}s3%IymQunw$ zIj^Q^ORLM6@aqy+e==`cLqCDHnRc+;pr?RpP6fb1;qZ=`VyRTBsbT0hmxe-%tm)|#7Og8WKr!}m6WGe3ce15O~RebXQ_?vhh6Hxp_t7DS80?Si2 zU|vGVNxTPk$)pH4o(=axzI;IHE+}cBtXSC>lRw_+lExov<+~>OK zbQ|xQkCIUJ5&O2wbzq0i@F7K)a-Fr_Eo}&-Y1A_u8HpP}cWu>}2u1FI#yTPsD%;Aa zyu>T-#^} zT$clS&NT4pK6*UG%sw#$C&MA_Vn%+z*Ku*d53{*vTztJyNw?#0q>D1bN5-&~Z+)xh zoEfhDXRR-F$+RwItyJd;eV$g%3vw#XGujrx zivOzl8}Iow|J~htOe&|cBEYm>o4)P*2mnMkY3Y$UL+ z^i~t^Gwl$X0p9}vXaI6Q6HZL^rO?h0CoCM$*PP)1yr0+i?<4;%7jP5W#Z*CrLy~N7A6OP)HDth~=Hrm(et? z-v-DIUxIpkVzaegjld|{0^$pJ#<9r`Rglt1Z^b}OI1A1+SgOz1uj%C_Jb7`$ZicTB z1`}|GipTv1Y;$%ASPvNS^78b{SuXXyGHeXNknMusvnYlNFLg2WJn?Sm0w_26o>QRj zXSB<|GL`Ckl5b2yVa4lE4TID+e8+W|D2O6XN~#ET3|80DHMrBU|WyqZyW&2BW+ z3TugB2$+XDj=jKDOF<;Ko~?(&zbzI1FRfl>`6;lIrU1 zV_EDW#0x?J;u9J0ECzn})n3M*8_R^;H?#*1>Nqij;AtkP-^{O8=toFF1#0CRW<1{; zJA0DTOvbQ1fX!-nLv}u{r@;>FEc=cMGW^Hs|8tNU?7pdJ?(W_{f)M$!6gqdpS!@rlycfsSOqmwLHmJxN&K2xU^`1iY@7`5~(z{iKbCfiRG)}?}y?e z3EJ~h=f!?|MgH@ZbX8X|r}p-7_ReGeOgxm=f!7W1uheo8touO!*48e4zKQ3F*tAyU z7hnZ%fBE{4Z;7+3&IL4IgZzdobqDY<_gQA2u4TQCR@d{I^p?9{{eR>?<=e-?}btgn9crbr!^q z6!6TGMTFnyIj&}ezH>rpV4%&u(lBaAF$Spcc>QS_ryncs+%;CH$xx%Qmyh3V&~q!m ziAuh7f2eebiyA|$l(#m0L>h#)O-PH(+o+WT2+-JXNMan`3bzZ?_Sjs1VEH)SK^qv= zHMfQzVWUj@iK3wp3`LcWem2i-*WM3V>P%Fy<$zI8l$O)B3FRm)Q-EUS`Qp|U{0{bf z?(|i4S=X~NTI9xSL!V~NRyk2tPl1l>-;u+O{=R9L4Ujj|SPB$RhNLkXh|mG0v%)bZ z8mb&L%?6-=1i>@SdsU{e1SPbl>YBIF3}o_??AO|JM6Q-~ zzsQ~W4d`emuM$&p)qaI%?$zUlfPG!^wY;Z#dxO2)Ptcqmmb%wj!U<_K#bzTrrXn3` z1sohCGn(vgdvs=GCd!2E(fu6UPsnQ}B52q%D|6YSUndo&;h66&$DZ9cKX~WjKCcN= z89t#mxx?(Mu!JM$#^qD^s(rB2&YETED5y~u0|6}xMj;0ch9Y2wyeO1}jYJ8%B#~9^ zMl);!veWB(JlEZp`xTzY&Lvm+_DoAo&4zjZeLRlKF{LZPPCl6c$wV+X(j=6L9VoDZ zL}LK>3RHj?VaCCk0F)L@{8WDa#~YrK2_eL}#eza4JFLST@R!_ocAo_k6ToY>H+ywnREY z68V${K4ev*CNKk0ssMl!6&s)uO2y-8-Oty*?;q@sQ=h-!x8LRanUAbUfdS_XOA89M zSIOaMzZKcUGm|tEDoP_!-cnXdsbsWrpUsL%`pgKaR-|dQJuXo>HhK=@;U)9XZx4H0 za8#HZVrj#E;w+!K4O|D~vV!~2lVbDPhie?aLXh;oOjA$4i zsi36GG(`gd0R%Jv5dYK#4lv|EWWX)6qKqVofr(WW87w+15mF_DBZwps$VgggfW=Y( zDX5cUWDr47RT_zna|isCz@hUJzaWqJof#q=yk3Hn9b}MAD&YfNcI5QPR8XvFI^sSS z^r!%6CJHq`3J-iWk_N3&$EZfa6uHqL^xdF3MS>7zp;!9tY;J#u1E&HCS~|U122QC7 zS&^2lEu)KOcK6b4QegBp&q3v;|a6E$JN7Igt>o3pkm9ru{&Lp-I)sfxGiHw8L zh{7jvA}*mVz}+Km9y?tW+>+S>fF0az3*ho#{#Lb89w^9^G8~>cGf~sEm9`3hRB`P78^6!%0Z&WEFHH~t0098lLYaVtkVq4PA>@FWw`8SP?`{q(K#UBR zn?Ra@^|6p`o|2z*Ia8fmiKiZfopJj9>DKi(eup_I`gCw7Ki@q0>s%VKzpD4cO4dd% zW0z5s62K|Sfo5`KMaNwpbJ${5V+v}d1XH!yRV$?-^zo?+_a>ds!`1!7#2Lu!YYmUy zjEc{HhE<#5PwMwsDK*{mxX+YA;L7=$p5EX}ck0P_vf&9^K>#R_wYDc{EB#a^yuPFA zF7XO6pHRejDeGyhSXnGuZ*%>@Pg*|b;~DQg$5VT2gWCOhazFju$-HSR1TzR4+x^M2 z2H|0yeO_GDb-bh(AXqrd+{D3kCu14eJ+DqQ!{e~UdG<8lEdONQ;(w>Q7t=-FoS z!qE1^k^Y%AKGJFmFGZ#u#L+P&lrK4x1244$e4|N-EEbY-?}|Nlm%%VU9_{<$UdQP^ zv0dt(fJx7G&|r4|<-OnB&ff?=I~FQ2(mq@-hI@eCwTQVzEVP|o(7>c)`W~5GLMO?o zjq$fnx)Bs1E@PWZ@)gSjSLXon)6-p!; zF|)hc&EzEQ>{atD*3}|G@gnF0>yG{fH@v)E^a2NA)Rt72ti}oxY?D5s9^6^oG+VIh zg}p!$#dI)-8|?!EPz_q#%4)hCboxvu06{}Kqle{*nGn+z#X>Pu4uWN$y{2WtX6*%B zljK#6N+3kbfntG2@kARC38;5i?U{TaP zA(!wJU}}fl+17N!A}5U|JqgaU8?poF0npd}DAV_Q#)%hhV!O;!y=$cs9mJr9CArgNdG zT3)vOo~~)1-@rTO>eOr6bOsq;2UW}C=~l{T0$`&`?J_kcXJAih$I{zmuT1F1JnUE? zzE}Lg3;VC@eD+*MCJGHjwJQj1$&A=sU>2)~R*I>y<21vJe#oxbvMM>(S9R6yN{Vqp zKQnl?0i5X(u0^AU;ePKXyOO0+uyQXU)d9_zU63X4b}?A`%PUN+3T9vs)T&olyKuQ45q;4xLeT7jKo35qNTTWVF8 zpwy-HJhfmOyu{ekxntgE*xz6AUni&UAKA^!1gB?zhVHH&U zJdzfrL)e?q1t0Et_+Df@AI;3_*(MB3{Eb-?xI5JOG1QS2Y{j_Lc&r8aT`It8=I<* z-``*M1le%|OLF98m2nZEQ5U+oeL+OL_Pb^alrn=eIUiKn)!{msonv3zC>Kb}W(JVT);%4{(VcUmcR~VNF4$GKc)#49Ri;ImH59z)-R3VZ$M5#ee#+18 z%k&-BbT^b=_I~g9eaWxKuj>8P_HjEoc~a_lppbGoR<=ZoGzMOPK1R+cW z7agMx5Yk(`9)0`6;(B}It6zO`_*rl){{H3v{kG;8NAT(BEbDeG_NSxN4@*fCYC+5w&?C%%hA#>h?9%(^%#Zdz zE0H!`w# zzw1;WbiMdN3-1!LcIX3YqVO?#y;*&Fb~EFI{uz=XDwKy zW$0`j*EH+tW!rYrCas2^znv=O_Y#;9%@eo2m<#z=4ziHLh9fNfOKAW!5P!3f34n&ttd7f6Da?Sjw-1E@?SN(gbCv&xSL`*)ewjs3gZ zU%&3t;t|H`S$#c$#q8|s z_P-vdu&vbh19o5W`Z9SOA0(){eubQ|7NMfOwyoYgm$W{1US^)*IDJX!dfMZ7)#&SK zPq|;rIUVCC(aZS{(TVxmHV%F|SwGry?$57mTlh?FxL=gVO0|y)Z{|1i%j^rkuJe8f zC-~}hj0b=6xj)^x$pV%X-Vn&p3V;ZT%E%}QC?@h)UB<0;l+HAS)aIEV#J#`I|FhoE z9nR9}1P$%Ec=IFf1Phu=a`XV?O%}zpWTO{sQ~{7e6;c|^Vph5sK@~|D2;g84K_+>` z^^NoAxwCm}rv`^s1U42-)STT_Rmf|eh#;m+a<**lY|4vJ4r$ky3Q?1`SGH0&*=b?B ziU+L#){o{QMv|S2|Dl;qXLtRD{KR1x+jyD2`ge?U4mP%cZUq{nltEgP&jkGe4`(&L`>E--jX8*q9^0N0V96n=sTTS%;QF*u$Km zxT0(r=n2sqyTm_~IR;Y%Dx1U0)ldqz7{(NkwrfdGkMYxgW9;}ylm}>%n7~>~KXrdA zj^W4jBVkq>3Pt9bCqD(XJmi_3>O>k2QEk^5Tenrse#ssGbrJ^dtANUj8jg^B@gzVX zR3U00n9#5pMz;o@U%&mOetXkM9>;5oQyCL;T5sR~{nyN_N)Cx=|jR!ez*U&`E(1902Mxrnbblrl9T5<6bZJhyoWTmS! zKuW=`&e$i0V)>%4C7P%!_9S#Q{$ApoZrA|D1s+%4Rz^m9_bgOuMdybwP$eyg7T zbZjp8hV_H8GR;AJ#P~?fA>9HydbWi@-t(KdA^@-f1CR-TfCfMa zJgCNtZ#qK<;{4$)?`RX%rH|Rp>2kjx|NPgW1ag1?b&Yclhu^dQCYosC>M(sglNR&oacv~zSZeb z{^eB;Dy_U5dNjZ-xd#*d?)7!XE2&klXixrFce}k(>-!0 zv3S5{Yh}0`#2H{E+N#VF)oxkGlV&%y>dZ8cWZG(tM(1z8s2uNKc2x7;I3~C-Rt+Uz z*Z8?g+G1Z_y;X1Rb3IDi9xHh}H52&h?YnATWBS2K-7!z8Ti4YM3apQG)o!+XC1`G+ z=v4q&G9E}!0tK7$PE9O;3zXIby09M*j@~v+hr%%$2w4m<@%zk!K~Qg}=txa^Z=7Jk z+V)oAUP)gRTYK*3m@J*0`GkV9EGkAF02<-Mn|Ws1wD{Kfxka8XUz7r9opsr@-JEHJ zP>)2;Ih^(YQ$Vc0hDm1<4I&8T8s*DFmRs#O;Y|7J%6^z4B;^rh>CWHkR#(;jZ0B~L zZ@KgNlXRSW+F*C(|6Z5|fB zlxC^XNuMqLsQ39|?i99EhJ9kQ%0sTQgX#LNuPM_kcyCRnF@5>;j_ z6IQe`N$EjrG=x`RN0z+OOT~eTK1EXZoR{|;HtuK1-epBy%y&w_Aew<@K7Id8*I4Eq zh41*cY&s_0bjCxIFkPXP!K8MPP(Zr(SsoAMv*6iwy12E~kbsRyL;%$0uIMZpXvw2A z<3}msalRI`QKbu_9Kg%EJ?F`%JqmynFl&<77IR=5T77mmj$jU`Y(cb(3^|+SPE!|2 zp#^0ib5czLBpXstjS%%EeabKC#gD*JntRk;5%Ux~$Z(1gMW>9Sb?Rn2I8BBRi#8O`eVpMiQ#}b-OmI9Xr2zU9*s0` z;2Oap0!ly(#ySbSS5Sw7P;k&J{$X0KpaIA-L9`IG<%k9%0pOXAD3A(ox<I8ECM@ zv~KD_&5?CNUZkMkbG*;p4ez1lv-b;I4RZ#3`FRe8v}jZx(dnqH*-J8*G8R(7v^yBG z*iHHrExGb=bUb01nK&cZb_p6voE#WW+b`|Ai^zrae7%(>QagckiK+dOYjR-fvA#Z? z!DMHbZ@O=Ksh|IgpPbAT@kPGmN`IXc$cwi`9CZk85qdP%Xm8{q=|Q&uozf7Z8M7(c zgXT{+N0g3cQdwkUjn6cD&L(|XsqV~r0sXF3V!>@gy|mXK&$pL&y|!6F-!~%`)NW+o z$GttT^!$r?|H+=O_!@=M17!(f6X6yL*bWJ!(jW#aG<_MH(>Lr(B8_nkxxi*#f@2*6 zoJ5i#CEppwdNV4ZP94!E0b~GUn8@g&Kf@<5#1IpZQ^E#IVKy^`lC_nrArC-X31rX& zMhB2reh6kD0<-3#nR@Y`e{Jqp=c%^b`x8mt@o{)s(SS+CllzywcwjRzGkp7aQ^Q7`nYrR`?qoULV;l*j>Nc6!^DsFm+5kF&WjkB3e3V%Kb#u^0hwkNI_~EW&wlx*^z+ZbLp}}FsCGFQIkb=GT6+F$tG}c` znexZMnkfiuB1I;Bj$?n7^2cCJq@fe`HS>zN|CH2&ew>A;GASWimF}>Zf*M3Q!I2nX zS~QGNSo{uC+PDC(u%r?WCDXD+uYsckc^qSN;IE2!(oD4+E`z2pbF~j&J zJ4`9zZDP9w3*uQ=?+`3j47WPVtvZ5sKR`-QT&esrnyX!`qo=`^C8>PO#KK|6=!mp! ziM3Z?n`DXEygU_MdNijP9KEg9@+V@Y$r%PP(BZ z@7iX|k+e;D@5%*jFl5j{J*Cd}Lws|Dz;Tb-1Sb>bQi9`4YK zvJerM{RZYJ4}mM!s^FJI=(>P;qZpg3s|-0)k$y&S_F z`bN|$ooif@>GdG0=&b0ZrOqcF@+BN&`xC$T@ynOyk^yho^{Mq{iP9WELlsn^1-wUa zu!gdnQ(zjx623e4+NIvihNYKOxkW~p@#pOBS|On49GUDT7XYy?=N>%k>6Q*2L2aHj zk%3I)(Uo=vPNL6r@s+Pw5~eI6St?fIp{bV=yanu*&O!>c!%>8Y*}6^UYA&G>wu*II zjX2a`Ddx0xg1^B+|9aC7F`;{%OZ-I6eLde7g=PDmTLECq1>RY@vd0JV zJ~fdCGsiojGf=NVlirM9zgP8@zYdn!$Is62>CT)QeD{3)AKywXP%6V9f>hNhphl`jBMMcAlhO(Pe^tl7bDh!O)qS4eY;T&beO zsn+CSq!(3T1rihIcm6^?#YqTqHPz~D>QtWz@WA*h45=Cgm};!pwe`jd&AH87S5heG zehKQVM4+jgtg)e~cpbu`8)0OIi!oJ(mu)s10Z2w6Yz()@C+dQ1-O_eiyb?)S%-V5z z+B_Gw{hmeTuYFH`yv~i^i|RUz;#x(=uVxE($mgeI=jD6;@~5}Uqh{bpsV8G1!4t4` zG9ZGcR==2HF^Jxpa^KJDef-~-q6c~K0~;PWQXl{*09LJlU}l6v0x6~-Xe6~92~mp; z?M6iF(2UL*mBw>pH4oAxb$dBcrc;T}mMp&A9pzO?Ye;ZF22%p<;Cu+GblfOD=mLc% zRaEl@7GaTy5CF^o1Pn1Yu~`Z(0VV~2Pyj%!zZ@Wh&Hs-MLcVB{fgej`Io`&tXyjl} zSD&q`Zs-q*vXO!ayNGZg0?0S_Pdsi00cW-_T=xh#yiN2{`{nHqK z8P(f*?G!hO)E_4xU;zOYnM8?pm9N37(J$VHx67X(5m+?gR$KpOJ@SZ%}+m(aiL$3#zMgj^PP&S~;)(2+xMyWJ18IJd2&jH<; zFA3U&dwislGy+U|JH&KFLSQCH$&>x_t7G-N*{;PH$QuY9&l2MYLsNCIX6L%xteYTF zV}!hEsJN|q+|dYX$3AiWb0OC8`Tg=-SCq@&8;bzy=W<<;ih5iaO$GA}~~G;D1eMXR!1^fb-0 zOUR=^hX>`Nn5tBW8@+TeusJQ`JS-H3P63iCi|xfrOdg_^G-p|ieU1^gpSuOyt@IAD zh#KLKyaGM`G;TL^xnouG;+GqE$*FD*?4a@hX#K9c^@!QM@CAvzw3l{fHrBf{?%neh z-z)u`jc42Gbf9dhVWB7jlF0~+YClD&rb%RHWi8)UQVyVsZteIP^K<H=Rh z;g`p-wBw;**H-c;Ja$G7TDX$(2V2u^s;GdHLIy6YuuR> zYeEVY*vf!5sDrS_7A|g(K^nT6kQ?XQT+basm&jpZ4N=h(1Lu?7=JT%JQ>f%tr}QdN zf~OgbRX|+Pm>%La7zT8IS+Bb)NCte1zW=`#&#@a_AMJ%f(q z_T`n;>f5;!(vXB3B_IT1h~($|pyBcrdt`^6?PbzMC45jX$0{{d>b7upn3xK?1WKir zOQsxvsJ2Log>9$t3xug!%ZkB1WKCCU%%bh-;fxErr?#+Q4jd9%k5#Ka_P}3^qWTaYqQvcS9oOKu>X$>SA@|J#TlC3U>s{}Yb!9D>Jf#97yBRNC?5JM`M zVE~G+8vs)VN(X5<8iSD%wjpX+Sey@oP(4u8Y;dI$F#|#j^am7a<#)m9FNdFlmh6G3 zhj~z4pfVH`S8$5&*Vyynm(TVWFYkCyH5P=V><^&mk{EaH6&3a&CYms&5vWXK{7EKR zmJ+z+(g9IldJDz!79bFpETvC4%EJxUR#~Ne6K&u>)U3wpANl|icz2nLszxk zuXxRyZ+SR!NZwU%SsTgzuC!Q9APxt3fvDZFWc=13mh6R8MI8AMi;*M;B#s{ntG$J!A zTXf?Zai{NCJ`WOh|D5L=eurc0Gfb`*8@IRxn3=S-$8l!Vvm^$S*fwXnB{!(5`Pjz} zt52l8xqtI%>`BJ^1+9#=mQsW|KdO;q&J-wMCQYYoxXPGTPo@<}Qp^wsynl^9|8sdK z`PqJoPfAcnaDZwxr71Y6B3XD|($L zDf?AuA&sJuG7eL4X;(rv0;R}jeJb{{hJw6dzMs#JpYU_9-}n9JfYK#pwvt0wD1o)^Thr2nJ>Uk?7ZC~% zD2j%5z_xakdE}|TTpXX+*M4`88bTF1NyVL^!qEu42Z$gm7tpR!dWC1mLRt<$wR~T% zY{hDvia|KTbBCwRv{@y;l}o-LJEN^+7OPR;O@gV$pn|)SXRM`#kpTq~Kgu>k-0V7Q z1F3lcWo5Xj-b8V2h#aC8XJ`2uKtV&D1OSf_$pi8z=?ON<$kx`z5E)}bjH$`YUgfVh z`+dKk3txeEYtHdEab7!5=UM#n#lL$tNusN|VO*@-B3P~b@fpYLQ|^44UKY#%Q`OoZ z{M}|fzO&x;YTOg{2jiTVQ|1<&@%hA0nNRJ^Y>KQI&N_m#YhabTr{+qbRAy9%S!UZhPhP;j5m07k%k26$9`D;HSeR>H zT*T7AJ%`gtcDrMO zky-zokLiZ-3Lr)nN?qC+#ee`J6N}luRsSjMpCDv6dLys|Q_zjk-^}w?Uxx}{gBa&k zIWyHjZBE09D-W8TT#OBnNCkExgUDzUQcbC5?d{MB6tna$XoH~Glnu$5>21kM>_9h_ z=*onk3^R*q_29GhWZG#KrGXN4P1p|iM*Hs4R%GlYV8X-PLc4ZBM6;#MR?7o7I|XSG zHWuHjVXmw67N;cs?Xa_{1!?3$XM6yk|HtdQhEBZ5nVjIXq`yg!1txSMQOH0rs`fw6 zKhDo$;CBFk!T|V%`(ptiUBiMcp`<`6hk{p$1dmj%nkm#o!%b%$5?P^Gl_8P=@kjo0 z2+pWbjh)&uQPek1%fJiIQP%r=h18@UC z76S|b15o~S0;2h+qs%6#pfCs!PylAofIgW*P#KMON3}vwES+n}y;W_6i3p=5MFLY~ z7=~Pgk&iSoD6s*0y2pZF|KR@CGMZaQsW~YC5WN{&pf){v0vI}lZ7WHS7zW9dQVL_5 zuYQ=S6sea)@N+}kr}?2K9_UO59Q_|nf7Ja+VAzWm25%O*0o-d%K zf0=)C~8Gr$Z36iVXEg;Ru;WHRJO*cEz+`99jTH3W47PCT5v6`Eh_9p zZAF#9}+}#CDgklqp0H3G@d`Z>_1R4M!w}g&knt|E0lOZtQs;fPe z3)#GyeylapxU79{t!H)V>9ghgmGkirC1t58beKZ)&2UuO=_wxVlS(&Tb8Whc+9rIB z`11jMfNFC547VpbzlLWc{WYksi4$GD%KYK^?n!#UnWe@AH)yI&HSH2KB-;=7(&5k} zb7saQ-GohX2Tq6#!9``0KnafllSCF7@wP>q`khSDd||~mFzZ<8!lm1MJ0`-_5iuk7 zoerDtX}$pkkW$uix%y#Tvp@ZJW6sD6LBiN?_U^n;gSqmy+}-ge>~>B!gCk3uo~|TN z5YrG#WFWKM7IB%+KXR?Cqdud3NayN*@s)iE{^h^teE;!e-%!dE(I+Yeyb-J6&99CB z{EvtCV~}rP2%(W!>vgx5otc}p4TqM!irR&qkyKfz<#X?RU24F+(gk=&@_KH(D7?lZ zPWq@c!lggphFTuuHe@Mipeh_aHR==IB34~j>=VVUiNYvXOIK8e6d%teL$aO3*M7cC zMe1wfzF1|cYV;E-=(2@aT$_H-bJ%l=_VfA2j5TcdGuw;R!r3*>_E}(8@_3OEJJuc9 z-q~%IMV!JT9m6`FzRhQxk^mNE6Hf4;${6~1CtFvD0`DR#uyQ-FIooXPlUKD;-VT7> z;kVB#7rSvNc?>9jrNow)u{*An(n`9%mi4OX+SNs+XCm_xP#J7^(%cl392aq8ur)K% zAhH7pD#I{3hlQx8YALD(FzDUQv-*}8I2Yax=^3?sI*(M=_+DS^n(YT9s2yDX%Y}jE zI1ZedkZC_?KT5Ne>t@u0IKIvSeBGbKgM^7Y3x{Q0vc0YDIU|V5t1M2_Bn}TZ(bKFS zWl1)^8KOEgQm(2Ny>yFx3lwT;p+k~6t;%s0YD++eSRg3@`6jQU+Pe2Q_qT+fvJwAo zEf1QDaJC-TmFOAA=uTu}vD~Q2LSpR)K0X{ZlD#-C}PX9y8 z3%zFXE0OcOseePRl{*1QCOO19fg;Z0#Atg6Y1!&v!)?3+&fcEsRRI9w^BjZ)AStvI7iJYb*M_yL{iW>sw>Tmba~`5C>nzbo+f|L}vE}DzW?I zgFJbDvbD`L&Zc;S;^FhQ_9v=2K8MZv=E~?+`PMHCup&1S<;YWLI!U93F5`Om$!_?XokM z8@Y_W7V@Nj<#be?9_d4PiuG1(*%$ZZAX9$lCbeYj%3ftXE4y9xt9u==YcL|2i`iRj z2#eMcTeH8l&jYsGx1DC(TOx!CRiF$da5%yYE!a_@CJ!V{EP*D?6YHd2ZrT@JVz=xS zt=N(}m@y*<%%H=XIHw`h+&T=i!!)d3uFUTMN{_7V({CF4jdddlejbjb%>54m0^f)*p@z#kWE*TP_ z!f|Tg?>}B_%zgv^1Kwd5ZDy(|+CfcsU66ae*D?HD{_{}2X^U^mK+g2SjfH16jPr_~ zSQ0j&dBGlmm-oH*a#`&~e{KKQa5EUxIo!{i@6UJdTrTC?FaG`>d&zZ1T8hG=HQ@n) zp|Eyp(1Z5!WX@F37{MZV9eld*r~G*F{aQ|0+K_MF4{ki5=Y75yegv&6JYVWr?Ayoc zR;dtX^Y$rRsnyL7|5Rgiu8-R7%UUbmif4qRoyWz@!sLk94OWaCR^!x{k7Wm?v>8-@ zavP!+LdTg`c~twk4Dk`LHjItHj8rX@cg!=a5b@Tmw<~{Cd$J5x*T4XW~#ec zW%*rciE5%D5={d@0Ko4gX>LUriZ?)IifK~odDO8r?*m6bOTnLSm0G9z(>doOy#_v< z`!58TW)_|e$9xzRU@6A-R20xh&J~i)U>lx(v_Wn@eyptYwr2pX4GyCd^)V^W za@D%~mX1W1M@gtW+mNr>k^7px?>50qPdtYcSv{DH4k_Z-#5zdvY6X)J%yr<>&sgF(+3`L2{ zhX5$qe!iQna+Z0G>uD^NGA`mw_l)^>N7lWZ6*l|Sjv_77@ofDvJsIb#{pSmB zm*bhnSJB6Cezv>W4Lv4Uy$*g{k0=zh53JiR{r4HYKZ5&&>#~`1&hGI23is=BKaV;+ zp6fo>@K`-goP%w>&}&*cOy~~WX~&DK=T6=IR;U8M?art7^_#wQBxxQADqoB=F7cGy z;$uATn_YS^w}0E$zJBb8spo63&ces&U$5NRcYfIV93W-^wg!4b}m#C zJPNFClj5?{t?|%vt$wesy1nUZF$Sc%@wbLR$sr~3fMfRSf2-yLjG{L2(vooY7$#5| zMEN_6fhKA+nn?JQLZ1*IfIkN&lo=~&rCPc+002RALKNC*Z8C{PL*A;-rt7z;+K z(Sa2z$)z488Puvw_3a?h?Mg?4eL6wb*dNsxJ?`oZT@gZMIvmDl5QZP%NsUc9;n<4&fd2{ov&cBM+>Q$_xrxR329^NO z4xS3F$@E*Z4JvmFdFYSb5F$#`GFUy*E2sf;O~*-g%N@&}To1E+w*3r#%tR&tDg+YA z72nV9>&J!Px&PG{AK8CQoN@VbkO*04w{SPtJ$j0?U2dW}~5?vA`4*Fomo^4SqZ9TUe2;j-Vv5l^yaLNA>tbZ+|p?vzB)%Z${t-q=6ae4}O)= zQwUc5M%~3{{&R0fU%z{J`qbiF@fF7*nNcm7_w6_Q! zeX>d1miHg9C8P{Yh!HYiJOKn$Aydn*h!W|FV%snk!Esn_JN9rL004B@ISRTHtJjNc zPa|GF2HwB>>-y=Z%c0^#Q8W=yzec#~`m1|fPJLBffFt3@fRs()tV6}nLz&V|=RL*e zvWDmMebmo^^@s-sq@H1ypVQ^nU-JA&1gHoo3}|O$`*yxfcz9IUL@&@&qkfrc)ZG{E z&vwF)*JA-dcSaLpx|Uj8U?qu@DNBZ{MOs;N+4p_O!3n;Q4Qt_z_T}YX!HrylH-Q)m zNNGGe(3gA70eC%5FFSYA1vd4HhoP_;e=y#2zwmokommHO1|nPa#+p8=cf;U5-YEao*VbkNK^e;?_7wE~FDfAxp787xcj=;spRSX7WX-wAk{RRDVwMNoc zQN0c=ErOu1ga|}J0vnSoRw)Of1V{ovbi*4?s=`GNr_bL|`o0~+1pQu{zP z2HXa5x7u=UhMD|OFIG~@OimuF%chgkzT3^qG=0)j@`HNatOVOnb0@&Col*f7xd5I5 z7QL-jd+m#)QI51qlj0bUgkXfCwu-}HOQuR_Th>wS8Ql%}4!0yEVMI6c8|p^9@|WXM z*bF`cKas!8ud*Bd(mCW#juz4N*4`fL<189sg4Cf?w2HEcO$vq}EVj?Vio-qy@hxLW zYh>lu){-S!!f~@BI)S!X0w(eLw%q$MT*q$%UI8lbn~n6@LW0FdAM9?&qw81u#LzLi zP8>5TL1XL2pP+6&H)=`|DiJ|s&Axm(vok)E+W&J&KeZO$6JhYa0fujNyY z+)G2C{FO0rV_6WsNK`{Ft2`Yelmu+elm5X*!9upio=|!@kq$#Z2|z4FTwO(QvH76zvbdW(=K$RdiNlEk zFtx*oLrzeX_k(?AlVG9>11OLhazR)+Bvu|8qu{9qC$t1Y_B^BhCSIGTy*zw-X_u?A z6{kN^1?U}oPj9;20yYTI!vG}$P!bWZ%%&(4pJO?H2Z5yTC7+vm!mqe73d>6&7|<1dcaHcIoCv(pN2saRaC(`iyIxrQ$XP~n(2!Wz z$|(#qPn(~CfFe7i&+Z*?63S#WrN?^A?H3f3T|h41T5Uqk=_T6VhIso)?Wg3Y0V;OGLe@ zbGY>1j2+#Ct2@yFi#^4iGbQ$WyP~}8VWv57kigB1CYGh6o)$OrH{V`kQknsg$cp;1 zf>-hy#WT@gnq<7pwIyL7mb*b#k!#-QSbv5HSp3IX`4A@E=iC|5A^k!dpR04u_xW^# zG9Id6AGAX}1p^3{@=}_NVzy%%j$i$_pfKqic`M)^UZ@Hlp2lye9nfBiGCDt2(ds-jNH;EuNRWzk7M~ z=Kpv2ANmHnz}KG6_p$%^<*PUN3M52HEQ)4GeETtc`A$cif1l*LN9G?7(1ewra~S*r zW^39@t~OxRx*gEAItt|u88{euDe9cgH8C3XJN^+jSO&qhf^Vv_tp>NF32Ls_vG4(% zc}Kq(iT>WQL&pMLQcq6Zd1UE`Y~o&L|H0G-#95K0xn5_`hITA@L}O%65gM&WZ!U{g zC_O|B7*|GR9!I|pwn33_UtNEU5=HW5#f~Qta^L&iYDIUm{*jUjafP!k*IUryAHC_9Uw1Pt;i%-6(Y=1`n zesQpEe*d~q9ezu#GJN)L`TE}duQ~t}wgf2Kd7~ZYCMcX8I4P2D80nHE8z7xGx1s<* ze4_2P#9NkVXWNOcfGPd_QhqMxkKfO~hW%c3%(B)bX(UFCHJKIx&tX6Rc5<|_(V+T1Hxq#Aa^3qU;Dh__AbLB z-C>3ghk@8rrR~?5TwCT&+esnw9kXq77SgwJSW;YFY4ckZ5F=}2naTKu{{$IW3F0hT zjTlnN9-Z^7lPD+o>)AYs`tn4&ds?31uT%O01k;w|IBjR$m+6!3;XFLKm+w`7zvma{ z^uk;130uz}?LB(8^t?)zIrUX`zl`Ri5RO z4b^kSyjS_GPwZncw9`1Pa}Ld*q{H|$c^3OS%QKRwwe7aMyKi;de^L5wq1*ahgI;KB zVUS!mKi;{qyp{dU@oZAO-2ThYTmS8i4;Rb{e6w9nFUQl6Hfi&9J`bEv-!ntFzO(b8 znO9@`I;EE$F?^a^^N$tD$^_tGv9H zWul`w9%4P2=44w}(p{t)gtr>^vS76oEM3MRmwLDL2kv_YyNbBD%P0U6SUP|58=l|Z zUvPHTiN?G89=&2t8*RyUvCfPHcDC%3@ z>20x7C@G+8Z<`iTU z2^4{3upHQsqQd$!1J$QZl~)DV7z(5Tz@P-u000yTinjo9^+P@+N>S8(V?e}Dm)|?N`<59;8_DJCZeu)uAX7jbtUhq>vT#YWz%&(%u0it83L0OK!5-N z002M%fB*mh0V)_|^4Y=Tt`DDJ5&!@h{7C^y3IG5I2xw#$c15a4ja2}7NDyWxTBPSd zR+@++H^A849NS`(TwtWkz_ag{HFc`BG@ZAMnmKlJK8kEKY@D?*M2 z)6%6(l?oI>Edl-lY&WElWei~>rN}ZuM5W>Ii>~Q`XY=KtTuL0>gG53VxNaS$9eyJh z&)VA<9$z4h5o)8r?rK8>TywO^%FB!ze& z8(J6g`~iMk8fjR+a(nx=JrAEKov1yV23ApTZ0K$4^5c&DiFk`_i|&+rut#U$7s&mD z(Yd-3GwY#vkjKMKdwfCjys%c}bm0xajn)vXaJORwTO>NwEIV-k0yR8XuN!1RAUEZM zP*Z0x7L^(bTfv850SvV#WB^Ct2-)l?uvJwZr?tDZd|U;TFraovsKGzv1Sco{6z)1c zTs`2F-@}I5eoSr%F;A49G48o~0PDGY<@nXtSpVzO`@s2!GvCKDW5gCxZr1h%532&?SMx002S3B!%eUM8!vR7kRrb z_DPVHqwPWAUgYk^YtLHIpFMwM`{yKIH;iP#*L`DR zjb}anLXZ3C0^eUR=lYBD-~Y~+KYza!^zth{5i5*zxrsbaS9J(EsU#wIC9U|H+oeCR zBeeG#2VY-K_3Ouesmk*?y4Ry5<-O&wrkAJ6eTY+<=qK~ZOv_2teTQ0>-gu|D&E6T& z4indu9&@o0DDRFQz5LVj8hxqnpNqr*O~_(fxl)7}k9ZiZxLhT1B0HeIQSVV4?7;rj z>E~(qblC1K^t?9(?)Xlhac^E(&ADQxDJ*zU-VsJ3hCi%Oq{&pElw^Z#WT118xKedf z7*#8Wz0a|EHfL5UN5Lkj#L8Y=m%DOYgYtMeNBd+unhfM*K`Kw-tk!tz$IRCT2hNcQ zX96pDg+;-L?V+2V1u2gw58jw4l*ih$>HG1TZE==kh@6~_l*1kM7Z%17sSD}?@1p@) z_g*B90>$=jyVo0@DfA(R!A^+Jk85YtjNdT$XZj}Yt7jaQHa6SYcYPHcsf*qvV|yiC zZLO*Sy4mx|(oEf`Ety@^a9-L!k>KorUaHG zB&?{w#tmw_P($B#%`R^^S|Ib$0NpSCxd(gMlzXXC4tBp2-GX)8#*@xzaP~?tn3nJ` zowaz15C!6ZK3eMFLVXYi@eC@B0%^lXI-&}Ig9os|u$JMK`fzJo+@wSYP=yV#nR9SR z-e3sb$ZaBwh>4^_8YGfK{9>*V-Rj~IMyQj1iVY}bW{elbY|sL z#Y4D?OWPbm^Fv#GgZZU;j`Q7-78ph-vZ8R9iF-*Y-z2^>IiM&2PUUz=$g5D7$=qeAbXpzgB(G^^pf+9m~@>sSIJTTAslcUy@$% zhq)eS=lGdea4S6_z@~7HOOPrS=tU^GExsCaTp$C0_r?6e*On%T8tDd0lfe&=o0Q#E zp!0c@5Z8{XO9Y7#8hi8svUxe(wI~tK85-xMj?VX2w^1#rrIzI^XRy{spE7zjMoKp;UF z8LSAY9!=3^{dsl@P%psjt{y^KXL;6#jc4`Tt@ZMK&(rM_$F_##=SqZ5U%jDn=Hq!_BGW(`z^m^0*K#ZL!;L(ES&HJeqn;x~h9$6^^*>omLU=_1zhfW}cnSDNa~ zWEa)3=imN=A2wh0=czk-4v*$l@uK~qNp`2_*OmJ>>&JCdId>QNT}J*P z&6xmw2|4f2Xwi$=erzWF73!@S{n1kCivFgQ(e~sO!1`Bq!+fu#M0e;U|kI>LMEOCddqkM4&hbJVBIPOET8h zb*YvUwH{UoE=F}Novqna&~Br6qA`=nB^jvVa8qfCKycVv`x!z>s$z5Lm z0oPydf3+b7I`}OZ6kQ?PL1HzgGfCz_Mw&UXfjf?tE@T<9#q!}@Q^CFl;%o&SAsZPm z{Wj0_oUiYntlQQa_2}>I+q|dc86>)!x6;9G|9127klDttDK~&*&P;6P?4D+hsue}5 zQ&l4cJ&}fF+<~p!ir0Wd4N(&Efu<3B-0_tBS;$UbC%lFKtPP#i+>(L`of6EHqx8m| z-f(G!PP8*^bQ|uyZlf@ybY(5wQ0PGbNUjA-0Sf_v>Y+!!j8EGHULtdba(rzHMX;>byK6T_v2)8Vif$2KffH-XHzj*stfP))U$m zv&=o8rW@V#;Us6ig1utuT$hQ$$U3@Pm#2PCnf#A{WF^?>2y6=)tQE85H&=9w_0F00 zrP6k6Z2!7lACARda34?JpTBYQgYR!&5c0n%x%J+&xpe}8DFsZLDlklBWlWu%OnG#e z`di+=Z4e;{V1Zzi*?3}Cqe{c+@o1!xhn-bY9qXax6mJiM31lg3PjnyZYgosXqjWQl z06O4q*BenG{X+eqeEM#+!y891P|)=zE{xSv0_lo1s6v}LAdaymYReJ{3n=SdA^|oE zW;*d`x}kb0r9;MAns#a-Ik>}g(GLdEk3&tku?PvO`DUNznC8>njHLg=zq^0%qrVM& zkp#$8P$1`s!GTroL`*cHq8)l*gQq+|-~<4KR{~KZ04E_R9+)l&0DvqZ6aYYi0stKP zzzGqsqg>C}6C0f2E_;TZ?$JFe*JI+0SgTqig(Y1>(W;){Nq~U!42yJI5n{?%Qr$|I zx#j0Z3>8aS(-Z&z3IG6rD+mC900RsN02nUcXEsDPc&n_K7_*0#zqjz zMV`LhLwn5iv~77Ht69U&!*TIieTedFV>ac`Q-QjcueU^ia>gy(#h>7S)1$f z#9g59Uw-+@%!1D{6kXGCu(ucaz=)KvmZP~{A-l@k#Qf$|G6|Z1A9rimj&2-*pVRsX zfEYSpzu?pi57C5BnGT0k``@hV{>|lM{_5a*n-5LgzA)=%J)hMtPx<%td~5kF|I=@S z9@Sg)S4mGM=F>&tCunN6%k{C_&jzrGe=(kYKX3l~&D55v{W-$afAj1Aq4B4G@DpzR zh9+!iFYDKU!s5e|=Wsxajgz_Rq9C!Hkd_#273IMJ^mHO_u^jfXKDIWG6U~`x*;l^A z&zfUJ04nzl?ekiqRZ#^o4d76&88&^coiFnkbh27>b{HN@uMi1mS#_$A2AoPkPU8jpX;^Oz-!;;r1gfa}qW)F0^=zky&pzs9>Z_kpV-( z(p?Xi)7!ldt-k^JZIn*41IB9V-8FV>K*XNE(|-N>M5LZq?*~3R|MAiOHxci*^WT-9 z|Ka%siKGmv=gbYE>QaER)Trqu+8G7UkNBvkE`IEBwZ_47-T&$0U&piWuazInxxKqz z30Cv>7uKbHpu;p)S%k48?-@BeMbs{?$IQz)4t~zj{o+g{xl4Tuscj9nQx#c_^$9iS zYkiz+q0d-^SphW#snj`(w)s9d?xzw+cK&d1HLDMNWeL!BF5dQ{Zfp1c{YJOf*T5ps zy;G_pPC!xG#p<#xhcdCdhr89_)GUOuYEbVw?s5fkQ_5Dppn(re!G$gC14p&1yNjfy zFE}AZ32;f51kaHMeiCw8B8E^HX@XVILo~Bw9mIvl#&#+6HasTIr5U_FEkpKPlQH7k z6-D%i_C}|Y#7VTBS&XKv6*0}3z>8`pJYax=-7DY!Qy(ScE=HMi(26Crwl}WHuYy8UP<1!GM&pKB$s1Y|Zvr?3hfxz+swsD?un}&dP!KgJf=L+wRY0o0 zbehmrvZPCIfh$sZC2L36idi;?ZDXQ*w1Z*2>bwumIudP9hG#nB?L^DruI^GaD)1En ziXlg9$x1`pa8C@soluPo^3Bo>2vvbdpKC)hJzTq4JT zq`<;lv8n!z{Te1LAwOrHkupp)?{)B53nurIk&j==B@3qA+}H$NW6S)8JjpxXbsKp5 z=kKfgIs4n7SND^wIej4GYm&y${j>KAYPn?9MY6(!%u>v58dgdZIj-0fcH@F62p6ggKafLbr zha()83RwaR_fjAu_T?jL54p*{?r%>oKhu?qu01rQ=j;#kBfKcpTl(fLcdEBS$qS|c zSH3&(O)|xGOTmI0eI7Al0^Tm!&v$nFl#iSje#@vvPLN3i6G>w~o`RPv&cv2NNlymS zRL8(?#BUR~A2!*NYXUO9H3eQ@2i8f&YP%he?5h^E`yIHHtvHh*dVVbqa>?r9I{&XE z08q-&C?#1KkaYIeTu0)za2-@Ba${B2w)Yc9(E?UYQ%gD2LY?)n9^?dgsJFQp72!l7 zf=tN@P{fQ>Ocq%G?0j~9e~mj(I$X-P(vUMc=_tc9w3M+UE$Bbc5}qruU(^fkTQ4Dl z3RZR-2u^czi3tpNl03(P97!OOO+si=m@|+AXY^=4y+^-xKTqO$a)8GWL>J&EMh+Zu z!On@Og-Nrw%A$YN>+}sAcE%?LT%f2bThutYTz|HsydjDNz za;78XroV{a{`0#2{;Ot~pWkdREwii@yzBeg|9Vpo_^tl`=STl%_y7CQZ>P)4-??D( zk|jGL3iaTn9_Q!-t#i8VeenmZeg5r6ztU0tE9IGBeS7si^0M{y31)-}WbvQg?C*=m zepkD@q?v^>LcvlnV%!b~84h5mpw|TR;xST!Y(`*fFb=UD1&o_N(6bCInT6tZrz#@I zMa^?!>7#Tb*P^k*6z#{Nxd6l= z2nTPI6|tMe}SIg5`8TBFTa zvnmhJS?nEeO#_1z0s~1yBOMU#NFbtQdj9SjID(#03!Z!s+zz=VGlpCfMd!;kCt^($ zwL#jXWu}^(ZLFb}JA;f!Eo`i8m_G<_TBteFXz8|Z_qj!j`EUJ!*nj@xo1TBJ=K1vV z`QOcd{OjTejj~z5l_1s(z#m*a3 zMtr3T3o~J;u@`LBmOTm1&9vV?_=|Ci7D}RoORty$b*sn2YyYzQ^Bf!deWpPG{TWrp zm#JTlCkn8D1sk|8*LaG>gRcNgC9vpuKY!WBXz%HJetNyx{Z0l4)L*LiIj>327xvdH z@jkk?#-oFv0s(61wrv)@(oeJhZq@)#TeA{zhN2Cj1&m{`GA^%oI{kXy zvK#&D>)tPaf%9(1ct6S6`NyBn{^<{w7w_)Uo2p@@eTa2QHvFsiv21m$y%v67y3)j8aQ%3dG?q zjAf3$5vBbr0HZK~9tIFFT1UQm5~2lQUq!*k_)exYGW`_gm;Tf>C5Y~SnVV%IlGgPS>wfWfQ;u+dPrb|-M@D=zDe%8?rKDN}0Ia zpb8dy8Gg*Jz;sckR!C(nHL7t+60m@`hONCl?V>^6iwSZJ!A)0F$8zGG|M&at$DVMy z|HydB$%vvO4?c}5=`YC>6jBtEG9z8|0oR|ggs4G@%t!#_KmY&$P=L4w0Udz|002{` z3LeUJ$TfQ_iuNL;SJKKxLV7`ExJPcwJ(Y@xpc%k`03euLBC>tmfd~RAhyqbi>0-zAD@YY3ji9V_8RMxqDFUw)@Y6uSUVjQCgfk%CIG+)iIOm^;p#ao(ab-i zw9gps+2Tk&C18XrLL}x1R01lrw5E*(G-+|wSfeIbbFPkpJF~c~Le;gW(wQ1{^FdXn z#6nk*7yFXawd4%`?C_MI8GtX$Ddg+=r{jAS-Lax0KfnF_$6sD|j~Ok)kQtm>_5bv` z82-!s`t7Y6=Lnx%SUtp+b$2{ln!u8yx?s18!5ZYHPIezB-Ky%rxCGM}wi(6d5-WkU zcL;t5pYVr}f@VM|ZO$2R9kzIUy1D$wa7X+Ahw^Btws-(9S0W-}b|5!w30Qg->DOQH{5D$!l)j3o7W!0yGzJ zE?!M!f|_d0%`h!jhK=27g8B1xeL|$+h&jSOG2?TXr69=IR*`a5C$Z2L9+v*X1)&;I}aII_WFk*B3XKM4r^bh_r@V;~!^b`NU0 zQtfn(v*>vCMt}R<@sBvy^b9+dx}?RY{5XALkZ*8AJ@Tjk7qPGca8N~V>GV>~3^V31 zY#~3})AC&B=I;Xh?cjLpe0$=zdEY`<+lt z8tr_Kz>#f91ENh653V4F z^xO+#2x6KTJ0<`zSrB?*#lvH@fK<+a$w|Q|W@|`N9t)KyiFu!7&Cvu7I`CHZ%Z0X| zCt{NCwK;w=p7V`VpqAca_Z@xexD0;(!A)p34DNz3Tnpfp{Uw8C)YH0aM})B~qq$47 zHwD^yn)U+C!#bE8Y;N{JxpJsLm1fMILl4N-?%f!mrPy-GMoxSUYB+OYcex_dWUpa2 z?&H#$q9wU9Z3q+x@a9%0-tp^mav^GAS`k>%FBn|D5Uh`V# zk9-+D&))XHymKNgy(oI&1f{>eg@D1#VN!&ZJg&|dLp<1!@v5r6hWC$tY%rR-{rj}d zg_fpO_GcBzIl{Bg{C2uEBRcB$(ED(nqi@NVI8=9R&K0lNVB&y?6rJ6&St0CgxmZ|! zt6hcy&ZKDqjXj>;=AMj2F?wSs>eTr9rU+YqF1>gN>9camyUV=Svhqjm>2SvTdba29 zz6}{yB3M+n^g*#G&? zeLg)u@o}aEU~DD*^mCfY#ki8+a`vMT%5CcRbJh<};YrPj5x#_K7rLikW^T>^*lrzO z>~o7qvbQae(GR_g(7ER-p((nKEfjX#Z7ZZmrpsi+4q6H1LRROm_pZ5*`qDZ2gN$*r zel*|nmMwr>+(gR@E1Pqtxj~ZI9as0Qz41MEPepnoO?ef?nPKONtRc3G=gjs1f1#kg z*N{vid!aOM{hmmvGt0M#fmtNLS<_&K@F1b)b0|I0yzd-w>7)?ifM14+UXYy^>WqxT zKu=pgA%lqk6eU|gAy}WiOMwf;kZTek%8DR#E)fp@7=bK}d8SUaXUC$N-F(Adkxg>~ zAz+dMt z$3ukJ>@Sz=o7RA_~^U)mKeZd`%^j8#l=Hz;YB^&R}Zf#HV0w>?1+xAL5 zqbc0%U&4O(1XuiRY*Y(NXJ;=;pFQX5%i|3{$N}JNW(V9Xs0}9&CP0FHmjV)Bbbdzf zsUevHKrO*ix;ksG8Fn=ui0*QShEQ1LW5+5_A?EO zx^AUNV>jDd+Z%N4ER=~W`E;Rv#w<}M8kdlQo>VXQmV^R z-rAS8*y1730jQK(eP)P3sMI=7}U;yn<_~Uq2lLxPInv12$VGuflMU#u<~Lni+fe}WMhuD2_uJlNTAgD zsO&sG1^b+ITNcGtLefD7@35jK5JOj24Xhh6FGgD)Y$DrrPy@f5#LK}!`WiHFgj@MN zyPn>&nw$8(FJbjA>CP1kyoNtzt7mOrAL32&0 zORy8SpqQabqcKhz+&Ulg)%jd;{%HTjfJJvUc4|vjCgicS8NevPwt@~P`9cA!mf87T zo--0R(#U)qzSc}KP7;}@8?pIxio&(gC_-W4acHt~e*)yqEPY*NnlmEDjkK^t)qE6r z1|{7Z->av=;py!QJ?DCVx;`8;n`-Y^yrA?<2q;294YdI?1D(!r(A4d`gOjT0w*7_( z=JNOTQSj5-gXVocDHp%v3-XC*M%#6>fcR(wn6h?1ncc~Q*3o55bTSEl6vjXD+v>mO zjA2OUgTR_sUw~1}eG9IuShzER=t|NLZIVv#HABLCuMdoq7epdeUAkxZs1j* zJoub`#NN^i*wX@?!%cDW^D!WpNUBksKH5RpoZ^q!SuyMhx`>;34gqXqElcPs&Nwyn z#L{TWZbc7#t#L*KBOO72+YPm10YgUd_ET?p7k^;nJvCD>sRE>c$jR|X_@%1vXV{3X zVM~|~Q_d?qW>yQ^r%iC)Jj&5<6)?`wbKbiPw^<|DvSyDt-Y92qjHy*;kxX)IwW&0v z&_kHbx}980_II_Vm_f_7MUqnTF)ubs*LEdl*SOM^49JVqF%O!Ui`06({(5lwU}^ z-0+pUvI^C7z+$u#>xF^U$)Ltu?ghSwx-X(nR?Ua~(32!M6<4zDOv6=4%R=nndU0!x z@~|u-3lwsYnNd}#l~{8kP!*PeTShW(zeIVsoO$oFBY#2a1+It^g|UkbVa2aL`tEnl zyu^tJAt(q?Nfof;sVS8sG?4!VDH}*5w*;WQT5n?u14WM2(h&>(&u=4{>^VWM>bWCk za2z?m<~YZU5vFE>DqllfvIoFRh}Wq}lfe~G+ns}V z05P%jO>=9=Zdil)1TGN-ur?hDOqwrwilM%XQrwB#!CD{|(NczSr1}IKv%ye9kSVvQ zd*rdzThsGD&u?GiRz0ukV_9;ol3>zUW76|UAL;h+N3Wy0j% z@OE`{$-Kt$>SsOw*~_>4x54V${-6rgcWFGFFREfFdO=GXz})PbR%UWXOM0_x6pU6n z122pu73NYA$%aOyWXdfuC-Ec-l;AGJu>_-sf~#27NF!BYTS0(tD?*b*)0!PBZDGaw z;$pQ%+4lMzcGYneDp!CusxJ&k1d$_k$QMky3>{>B%R+Joaoj*QE0twbjt;Kd=A zptU49qp(=2TQkO*#YdRtp)VEJhr6!?xPs|^$DoBb0aLLCT(OXu6*w&utC~BCx43}X zsbKB~*Ua7T{_dhrwc`om>J3b!W z?^e>~#moXjKb$oJ9_{)DJifG!Q!E*Lot8paCYJ>kHIB>A&2_h`?m7GBtOpNUde&hW z(fr^6A>SXX-(0Kb^9Qs>03is2CdkBCEOAr?%rr#~O+P1V3)r&%sKy*6cI3%|@92;m zbkTU|l%q>^?cqmXE3n@loPx}Skb(gqA>;qoKRn_3#%YbZC46xzxP2F=Vg+8AwBya0 zlbJ~D0MXjgtTMb}0QCb)f_V8b6*hN##%BE2z@{#}rcchhru1PY+|rAqHysr7ASfZB zR;Vff<$StqWGi!Z6#Eoi#SN9_Qr(h>BHX zuvL(vTzM^{!Ps?7+n?rIfEfp6Le4JC-D44$<*OM+k3++!!mCA{XeS1lSUH^W$s~w- zqeK>!=Z+G`RlW0Q9)a% zgaY97#(*R(nutP01EcLsTXW=EQoT|Z_VmDMr)L-&f<;yi)vE|;L2Im&0U2v;D*MX2DJY$Zt?UmZK9>VRenVUj^ezL zy~b=gk%(d?QTMqm)4*OmIdxq{1Ffj(i>zBw#|=tM1RxeO(lHrQN|j(P$(u1#kLr;H zc>x<|=Jw2Kn7!17^=ceVcwgSk^P*#O>+aII zSH?82kLaI`YFe1niudiXI zmwC(SMgpbmbzlr)uUHp4;LU%;PxXsPOVvpb?qr_J0-A{QzDfKC(m!JgfFj`20~NB@gNa% zIZsM)b_&{;SMK#ZF0L@j+BWi?oWcT}wrCu(dSKYQ%OmS%_X^q%`o;n`9bH!AZP1ri4Dd?!|-4)fxyMD zf$tYny9rB0W`2q&X-TP7BHjr?W1G`X*9ZTe(p4G_qJ3KcWRdU_CEa*6m*E-)rod9e z!x#d#dP-GBgy}JDFKkLnWvWwN2zB5H05=JS0N*4`Bpl?h$MQ{Fj)3eq2kYu9)Q8f= zfHF1jKJLTN`KpV5!KB5-lmOa1=(mYq+)h8Vewf+7T zy78C_-bsGVtV^Lirvj!2D_H^i>{SMBsFwIHk5%+-pc+bm!ZGEFu__qZ;(_h7H0nlv z_~8m|GKl70NLfxHhtNFXptIG1TJbWl!&Oph)fjCfGXg>yfgJ1VHBd&U%?sT_Lpx#( z5YI$EZZm-XyhfZ`^I%_m9zBDR*G2g}fYQb_mS{17Zb=jk^w<6J{X_Sk+}F{kJ`Vb~ z+87>uWvP&Gh8tsmOKEDUnOAH5uOr^gGU`hb2n5oq01VC6 z0)S}4CirMHjn1y65$;~6P4ILe>vwi;Nx}BXaPT$u1VBa3dtU7GUY~#d{;Lk;CzIVX zH)n>TEiH%C5Da@A$>!;R#^%DZy0Mu!Olb)y@POI^068;GCo~CGh`QbGJ@^zzqh-=j zLhByKX^xzk1n*V#q8Ghy`6bn0OVQF}Gy&h)aja~H+lf^TAXt*5T|!B4QQ;=o30v|6ISjL+GNrII+SsOM2PUWG!% zH%^25z^|Bt^mboh2YA+$4(h(vzjr+84y6@%7L||YYhZ&rll$XYNN7C=WO;uptY#1y zZJzagmds^S7o7s9bBx*3$j}j!w9>)@6_R4x{EOmLY@@hG9g5koeEB9l>QMT@+$vQdCm&0qqi4lt} zK@0YsnwU3xvM7&c)h*TR&Dx;P3^txg%hS&@spP!STPm5at8yw=$pdo%B#!g~*-)!q z$kJnZKQ=7KbGWiVQV1r@%5Y^Zr9>&ETwaQy%wZ;RLB(QQRW0wt)U)&YPo7V_f6aTw zv{EqYVgxiOL>DcbJmXTN0SX$0R>q9e)Ak6$ zm9m|8Ic5RrOqP4z`4|yMrT5Ccl;ei=7~1bAmOATbv;inb?{-!2&`3T|)GJNw)J_#Am@nxPIlNeiS&kpi$?B^_%D^Q8bs z!3wQ`iV|7>$&K;M2W}qw;6IN!_b>r6xbe!q9EaU=*t>SI#l{wLdyA5Y!m!1(T(Mw4 zmk1!Xi&DHOM1*GW3AR>M<#}tgZ9jjs`UH<{80*?rfWruEhisxC|A3$V%EwV6+V+gv z%cw~La9acbX8X;Zem`_(Z{(meghQCwD`Eu>p-V^_0l5HhxUB$*D8NXwRn*&#VRE7% z>R35sAx1GO+s%j^5In!z?N(E@daoXrUz*b?i=C{=-UNHzobwHjziP)s73qh?$annQ-4z@o7d zbFxK>(M_7t+93|bdiSGcXVKU!TZ*Rn1Q7|q+MMZ}mSzDG@T&ZCqpfY1U+T8Ima@kx zJgc}HPsFNXMj&}f^5_d!8;tDTKG>S)f4t?T>iGZq`rCk*o$k*?sePa+;2N4^&&;}p zd`!*4PEGfo9o3*yk_faw44k%}pj2MHE~*}$P3_sD0e_XR?Cr@PrR!X3l2Kw~9a zffdK6Jb0~0z`{ULQqSMNC!t?gs{S1pXc4%47#giDHeDZA!1H*!*sRNunHtfsPV4@A zNdaSE+<&NjPZ?0DzV2cr}fkXMm=zv$))&^7iY} zJx|Yh@twWJ-@DeQM^mJhre#&N8iL6I>#`zK-lr{kzBL5&;7B94rw`gz}@0~;G@Q~tewH1aymKTF!%Fw@qt*YAQa zM|VeZs$>;)K4FDepuF425TFqUu&iT<&e3gKdhYM)_UljfHBdD6{y^U^(0z`nm3YR2 z8+%$4mO&PS7t_0I`+1qVeK8qgG}pKa^diV1Cg391fd1kWanUH+@gnz5U_~Sa%M5f_ zk0Y;U3qgR}$UV^Kax6^B4$ytW9}6up4{_uk}xUwloqiSmE+>=E;gL=nJow(HOy76; z>)XYD1+ShLqsmml*0hAyfnUVnAJKgQcuq-c4sL5YQB$hsG@O83K{;M@T?bK9Q;bP2 ztKJJPy0)T5o9X2(;`A&@;#>i#c}WKu=T7ZQ0PLn=!1U({e&L+r8m1nd**3XQ z8>rOni~EvK4O(;v7+7@=t^upZ0BW})fEsOBfP?~8-RZ2vs)XK$ep#rosX`}kOta{g z?b6+>L{oaHLz(fEorc5r)El8tRv1V6K~#LH{L1il(UJ7Hx93oX5s}sQEJ8Wgc=>q; zk}=bJ`o((FqBts03S}jju9z#gt~-XO^VKbt-=hOr+gs!Fm2=!L8UqGxO?u7k9dS zXm?L0dg70C%VkFCC|%y0(3qa_b$Q)tAsHaZ{p;=VXSp$F zQzQMIlghRhzroc!1;-m(F;WLL6KXf|lCHH@toA`c1*9Kl2WSi?5)ygMUzg1~v&Vdf zpOSBm%X4IZec4`azvOP&3W91fYX#oeuUKf>-4C-kU7k_v=Y{+t9*uUz*X=^o813MI zM8%+52PURt zTCf~i#6W0EZu>{}=flIVpMHR_xK_MsWHv+pCe@!__5*@&p5Y*plUUwLv@{|n#2IJ? z6`nmiGLT-AQZx#9bK-e&hUHQgzyM+0o-s_4f9U)lZ>RRB%>QZpG#nTQG1HRA=nrmZ zS*a5SbVo=EmKl*^C#8 zX)KfDXX-OMwXtvw0w{jQ8shJ&X1f$W^unR#-L{dteYyRC17#=tR^Rx~!(~3!eSbPX zwY&#@Je>oSUoA^F$cY|DWed3(0Ej>%In#+Hb6M^L5k!{SLTrQ9Bhvh1$TVN@ug~B3 z4`}k)>>`|-$sq(#RPm4|!ubFtVQFj|^3p1unwA(_B<%-AQL#n|&7vatN^aT;w!zd- z!F$KHe3WE|egSY(gSJu8Qm=K_s$^EI2!n z)p*#eUs^`5N*J_5oyt{9@@i1dKJp5vH_?oJg^Wopm(^aGAeqylsa!$~loNCg!m18n zQ+N^^Qf)a1noDRku#;mo;Mc3XO8)8IS#9r@=u!1_j-uwB%dPkA>sW8Ch;CczQl|rr zaU*FaVVrNQM-8o}loH_uCU8>6O*`!j4{mRCA&8+M42{Zz!0yPnG$K2-&vn2fJ?E%x z745eN7A~;`90vLF5(kdDy4OUPEz7B$(Z-zK{RI8=^G&l#x1$y^HF!wXOen}DuwaH5 z{feCs6?Ew=plbD*CAlmNI~H{tBizWJPChh~pZu14Pm1PQ5_wX%Y!CAhq`$7Vx8gI( z5jPY(F%!X%T=67q2IGJ#dqE}6m&RfMgiupastOuTQ1cjTNKot>&<4WRi^wH36pUiV zhdQ)UFHxGRlr^p;?c*CZ5)or(>3O<#sX^57<*+@&)P9{$NH`8WU+94{+xA+xS zQ);DNt*zZ|R2eIA!vRotu#gPT>apaeb=Uz+xC2DUumm?>!M!&3F`U$P+lVQ{#fnt< z%}@>&ZZBN+2eN}+&~Pl~9=XGtREp2OlS9VKtv%ew?{3z2Ca0QF0z{xSvjt3U!#*M~ zo|bMwVT!P~3~e(T4im9k#4?zP1OWpk7TNX(MK^VU(M9q^v&^n9ELnCt-1B2*#0D@x z<5Yb;E&Kg54sHVp#)ePW&K%$?TRaDmyoBd0`7l3FQI5R9$mx)|OBZm8?CE8XUH51^ zhB4mL8+c~Un~8E9o$Rq@th-Ma51idj7JKwWB%8ikDF9#{*&)jqD27?p`8VX4$S(Buwj3JfB$AB8CD7a7ba^ZP-v|DWmmvGrMPacM^ zk`w9G-1D-;xEVEUT?zQMwnn41ySf=Anb^oN!6uf&<8~vXPh?8bSwK1Y8u4VrRe&$k|Oj{;%)}XeREKo5QP9m_u#u#E18#*wt=A>n* zsD}~N_ImzgPUoYO-5X6&RF$_wqQZcI5F~?-S17Lr+u`91^j)zav;YX`K<5U2^ZeyF zWwN*9*$`Y0=s{4#7%3qu2ttk^0|BBEB2bL_NGK?|t30;|fR;#LFNvUzhhkkT7p7MI zs7Q&hy?sZS(ZTGwSK34KQqzECv!9X&XC0k`ry8k1G!JV(GFvD{Wu+|i19!wRK}oR; z6v#!e2u;v*dbpcK8N?JWb?LU9yP+l+C>K&-q4pXIMl6+jB)i&`t<@egc!X3J1270o z3k?;D-}HtmR-uA3AqGJTW5qDRDtI8|qkOe`64Qk^f@r&^P)9YKqV)_0>Xlln^n7Rq z0PtLn&NBm#wYItm#@5MRlCX^-rutm@2gTvI{7>nXX6ryCS{1kwi53S#dBLO`a&$Ku zuRoWcVApqzDP*p?Pxqb+%>FAPf7$KAP4nlUbZTX`b8IFbX+LeVk?6li`KO(N!SoLLE^S(YY&#pc{)LWyZlI(4Xw{W`V&vNi^ zb52BomR+I7h2ed_Noi=2f_?ait9pLz51ib5t>TAzI{ncG#jTP@c@-;i2907}d>k3d zF6gLZkbnp~!e9u4w{Ch z>x$5t%$97L?Fmi4xlGPD2*^}j^ha$LTI41z6}$jUd@3$#a&kY03tD2n)P+gk+v@50 zwcf*rQ50&&F4FuI}|I=UUuS$m1;n*Nojgmt?QvD4sgY;BlzOAjHMp ztGjA@G`p>;EuZtkUz<9AWw|7cotK2sQnup|qC}>WjrBkm^fz2u$huVjb*J7)xpdT1 zg6MO-StI)|r-@%JPJchDajL?Z%>HR=6`XFEn?YjW1!_mNHAgbZbI9}EbaFlzAp^=| zMN{@dxO!8eO{7D5K-h@`I-|w9jT9(}^n)Cf12nz0y9mn#qJ-(bJZsyh;@m%Jna^eV zF(uC2e6wC|yRP%uYsD9fM}fd1kbn*xn<*r!Dly1Xm(D}nz(GuFX=T=NRg@R|A8Z@l zmU5EvBw((a%eHEEWfwWK_Vm7#qWBff*S!CJ0JBLya>hHF00f$pxk_z!J-NIsSZEaA zPH$IzvBD-LqAr9++naGc@DdPM3KH#rJBvr5D~GxdYCT0SJ%OlqhBq3|X1@-T6)TG{ z6vd5uKxQuN_EEIp%Gvm%HcH2CW%A9C@|58|~ zc9K-wxr?B_CKqamhtXHeWN{KXgZo#IX$1zot(!)J;mz>D zXz4(gaw~LIFL=>{xk|C!@LzZIm8IW>W%gj$ISLii`79j5x7BS+k)K(S^dGw=Irf0x zEH3U1E}aHek^~%pU+YE47o2v1XjU`@Qt?RuH_bjB6TyC#&98h!d$K1V76~K?_3~no03{%xaa#zW z+ZvZlSjt5%_YRol^X}2f1pyYN`C3Z>KgO&*bQ6I6A_mf>Q!lViE}qH+PMi~}#I_+X z(cw@ku{deN&Xadd;Q9Qx6#Dtyf!|hp7u46Lp8e(e#T&jq@4Yum(-I2(O#Vg+*&6RQ z|JeRin>ZYEPs&x2)k71q?983J!kanM5vile4|KFQ-3)|UqA3;HvGU>CN8LQ`W5t@DX5BFqb+SGBz=cPQOkdp4N_7ZPKm?6o9gq=qA1mqd2YPOiv{>!BTxxrPS@|ZdL8Y z?Grp%J-M#c7*Q&@b$6zamRh??D91oE$UCqbw)&}Ld5Yie_T>CzXa5<@^hT=)+j4>s z(D>an(^6ZXxZ++09YK4P<-xX=D4^UZo5HrK9csaBpU<2>+-G{-W7wNpc;{u+9p}?H zAjfAG6}PQ=UCEbZF=XNZ~K+?570m9cTU~Dzww#z zE3r&46+~I_}~K zX2SOr_ZS}zDG?zZ$z%C+%<58crhopo-}0Zo$HJY#Lf{I+Q@xzKc-`3Z(3#P(=A9zm z3}(Aq36!7NSi;p54XJUN1{G9`lJpjh6-%BUiCM3!u5_Ohv&pVWD#UUSo`FFqAaAGU zHTP8%xT(fo8A5O+bOu^jE84f(r@c>pVRb#I$bC4&_?*s9k6iLJ+TJmn>Kum23otUW z#NMut#&_+Yh?GsU^V&+y9Z-G1p&31VxhvuMa44F+YMJB^bA$LuZxIl0bwKHF9_d)I zH?SZt6yMbP^QwtB_V;b-48Ea9%6(F1`u~Zj)3mCa!XCP>h z87W9YX}WZb11L;G+hxaa!>Ej_wjxd36l#wAEd6IrwM}jeRmC~qZ^>JlNvG>fM+NxkouQ%T!dK*$HapK^&?SxGz$MyQ$sX_*tHq!V z`<9LfU&O~K#_2ce3;%8gxVC?-els~n5=$)UJH0f`>2Htv`Y+g9joAl2K7Oh`H3PJV z0t6L)iJ;U%-I#_zsE1=k2viq?I6`7MDLnw{M{JzUAmE3(^&VdqvgYkC6U)6N!%Ya{ zy7kp2&>=o!D4!8{PU*|OF5Qv8iOzd=N!5kq!m)e4j%z9kCYx+76HLWlIQx%KpRvp2Upx$o?KQF9Zg&=LxZVq#fUpaX;|%3}#bCAcCX!y-#i zt=>dBP94ADdT+cc^129}klKVg3}?xnM~@=TbmiLX8YYFwCvAKmYl{;{&%G`OJ6GMy z3m4n?$M=4UD2b=?d?lTKMwaYQ&0r;Ffv|dX8ERzj3c<;W3sD@#+vi{I?pI6Ul?fp7 z8$97d3`50JTqs;t8}^BVo(Pol^jly~h%}-Jm`-J|52xZghzLi)Z9&dw#ht82sY4?b zR8nek%vA!;!z|)fhLFr9K{8Ol5|*;S9O#2Y2m4q~@$9#UnP<*lo%18+`tG(mjWqUK zaeq4b)1TtI&9|OC@17i%OCDiS5MoIv#7#(tfK&yxVF^5TIJRC8K)Y!lrjD7<1*E)8 zJPcYa6`_-^Bx0IO<13kJQ;=4tBg2wfGv4H_LTj;l%4iY2K_meaD{L`xY#9LSXT_D~ z{#D)v)Y-bgC#+9bL6Vi@7-i|*#`>mb}=@s0WGn)uDFBBL!Vy(L!I}VNW zo1C|oqzH0(&|QpRBh_g%-YL5mS7tH(GIOry{*UJ8zs?NL6QqQz007g{dC5RY8X~MA zLW}PY+i3F7e3K0r91JV{+%n&C1a}3agji&U7~$nM5%dXM={gBS$Su3&8Hg~puUTaf zEkGbjlSJu35dx+3)wxVxy`5uE_WEgwgjLeuTX`gP!pgaFE9+62n*_1rAUzK8hzz&=%SG33JTZML8%p!a<#264yOpasmvqB13JUkw- zs{Rby_gjB_$3GuvT%DZ3jhM)S%9S-|dpnfITUq$}5qLb`M&}95t2hGy-e&7HM*dF` zt-&+U@!)uuQug{vm$_dzHM+LKa%2FZl2^wR?;fxCp)faS9#2bqJT?-o4fZM&!Nr21 zfm8HRSML*8`2o^gP38V}Z`r>R2j?{r89$$W4{j=sGS5lVzO>pLoaV%ZGl0|ncvhzz zKaewW%TH-ni?7xEwOJ*4Lx-bgIbZ8lWRH@M*E3q1$sKOBm|%0*R^C@1?(>IzDG!qe zx34BX@bfirK`Vfl%n$l=+aDfz`;%_#o2wj0Zl%eE)7tkms&|2u(JK2vB66g!{ltIh zEo=TiS31Uiv48%SuC|^>hjs_sCFCNOU19_k4YtX3xdDuTI~f=1=}*{w{cY>45y9~d zFR%Nh{=wQ${+cG!`{zxpbNh&#J`o#~6s{&zvjHOVn!RrBaSka>3cLD8IIpdYBN^H0 zx-4N>0}sV#Z1JTrUqXFf$}`a?40u{TotKIYP|O%I?UqMWB<`Y!Sf>fuO{?zatdfC1 zX17v@;kxaYOjnw=NQ-Wq4Ff;~6)K2aRMsNYUFj|q6L1Ovm85J&kjRk}sX!Dm2jxx+ zNBg-Vl2iTDF)BePEH&q%g?55WOTZK^#slwAADnlcSxG{5t z;=V=LnM``hRXS{AakXT4m7u{R0(xKhi@Ho+gbnFnZFP^Oq20KI!BY92z(1TGD>=<; zGcPJ|yQEVe_a#gFzFUnuq2W|rSFHpqV4rs+K`WO>uk#oQ1srxe8Hb8ERbL&OItq9; z^VtX^9`e;VHkz8n>zirToG}d~H89*_ksGs)V_ug@+~6bgyyPSQOkiVRil7h+8b;v; zoDO{^Z)z&zv-3-N%B`GkOthiG7iOgNLm=g^6tDEQmurHV^ya+-AX#KTFDiKAm&#%EGygSn8xj zm+m9B)DOrSed_S4r7TzMnlSG%UgbZP32H;-00lx3N-zR}iVakIa%`LFNeIPRtF6@pX?6es0AvSh!+wmb1vTfCs_e&v6*MrOVC>%5I{g$(O{Q6Gs zxEBDFLa*JV9oYAKUK>#2PM;0}ru%d#+_Bta^*Ly)fhGyq+pXi5Ts>%Af#4}+qUn&c|L7O@znz*!pe|V*Nv%AsI zI%p2VjNOo)TpC`2JDk4cUrGz7xj1O)3+CDO%)d}(blA$8tbjsMA(@@t*=do_bby8P z3O9S%Zhj>$@Bx=zp%G*!R+ccXQY&%uuiHPx>G3)fdrm`_3NM}}imU`{&LtYucpR@FsSm8%N8K}`YICB|0;Lq3w702Rl z0|`D5y+}mg^mN7rH*2-O<}(6WCrTt2HJmqx{F2lSq*vX0B#dHz0!MJfC;*zysK)(T zeydtxwCC(BAZJ-5GnNP~OFMw_ZWt2q*1KVsSO3{N6pLpM&2Pom(O&@qz?jj!c@5p& z;`R)=nbdwIFPdI^u_@KQM6e>T4MGN-00rHg+awZ5Y;hDbo5INs`H*N-&k1ZGZj(dCiAA8kHP+4@xAGqba@QAYoLTw@Cs2W zbd5p;jFp8*0x7`Pz&v&r7hE23#O6gMlF{v6Pj1;0TJ3~Ff-EJv)DsWvGu>eRNx)_bk^$%0gg3Gh}|V^GmNdVB}_d1e7vdS3FSX z%!@0Kyaxt_V$>h44Z!F{Mc=tO3o4)0d5w;#E~peU;{^DITk^sbb4MgaMVh%Hq)Y`Q zp^_pG6N%eeEJcVEqL!^n;ml_EMlUOlLgidFzuUauLKK4hXsldNVL`Ov#OVFKE`A+6 zrz2D_QrZ+=tP%|1ES&~~5@KjI;uySj% zY%T~uJkRln8j2V}Z7;!Bueah!yTxoIwiIT4r)Y}K36nRN-tLaP{d_L7*@v4qxZR44 zD0F8R%=iTarcFf~0+Nfm(YyU8qzj7;#!f@TfFYb2CEX5( z3oqu}#eVa*raKys{8i(*_g`fman*2k4$3cxzrXgeTsiEt*p`!YdtN178N=775*e}u z0x$*SBX_-Qi<4dw5TPIx99RgdkOd+l+-Owzg@KhM25|zf{XY9Y(!qZJZ~7nUe)S(a zY~$B#+uhgsu4-M4HlzR{$zgohBEm!EQ#~3GGN}ll5}}G!rI*M`7u*nb;adMhg3TT& zhxA}!GF3EK#5s7D`}3KzkjqJu>1r46|7sDj7LlY!yg0@BM1$$qb7dua=&;(b><-GB>9W>bZT#Y>G`I# z9P7{H;o4L~0A2`SB?0YsyzJink)hwc(_)cbDVEk(nvk>cL;cvFp8fv!KBZTwHcM72i>^i&RkXaO7IdoP@jZhr0W~`?V9&m z-iC?2drH6SpQo*OdA}|XS)cVk>~le~7sNr2N4@{V`ODX|*_QHkGpJ-bxF|U9?5E>b z^4(ywz3>0X*Y*^8`|V`g3AcCIzfenUUQ71xDwRah_z-(irL#V%v}yW2x*^_V8{Ybl z{R@ZE0n9}ow9(qXZ~biNg^acUnAV4^*b@qyTGiEQ6)lvrKioG`n>gznnjO0usf)?a7Tj=v))!<0#y&AnVj^lS&z$JG(3NZ9efng=0h5-(Q8sE?7N>zO zLP$kdla~H{zvce+y}3TP*)dAS&@P3u*~s0l!Hy7P6BACdp-Uh`l1S9?S{wuHDKttu zV?JNcB~cr)rL?984OSn8!}+1Tty&2m*SriBB?^awD2GV5gcMSkku$-WFlk-b9rQY( z9xQ-dXayY}Io{X&;CwV_x4k$l{{P?=FA0l}jA`tYaPJ}XF-HuD+g|$iABy%2c~0y> zL()iFM8X&8nr3Ri^ZwQmbC0JUp_8@|deg_|6Qd@?$5~T57A20rF_>dfqdL(|SBm@D zQ|UTC7~ts_@gt}mkil3%?a}TPz}22faj|BwEKSXsQam`idN?U_Q-VYP!n{y zCGSXV8R$SGGby0mVsHnVA)JKseAuzQd!Y!tk1yhVJiRk>K&SjxUgiSMfUruJ?f7>` zC#tfDd#R!s<$x+#j;ly%Y)_C^QubYLX6SKW-}KjD$&VwOg!wF ze#;-1%B31v1$YWg5v-}2@-SFHYPpKQLDL2>={3y=k6ITC}++!2O{c%*$(`g@X{a zhm_K~hC5M7AGV4DSA?|i)RrvSDQ|vg9D}oG5GR{w;iR(yBryDfb!NnA;U&^wXX61u z`L!8j745_o{hYX}AHkh5-+wrNOGWS`g-*!Lko01O%JMtOPycf`k-V3@WH~P*0S#R) z-G9pcIjk#<-l3l3I&fir)hRy?)V+V6j??~UJb!wh%{>#`?q0K3F;LE0mOymW26JZ0 z3{t>enz5X1Qye(#h&ChinjFeFi?*{2O!D*WiKe{oUGMYr4~ghvC`gjTB(AcH%Lozn zc3bwZ(V%1$?V0CX+J&AsFil z@y@ek0~M5V&!{}lCSDgc0%OahWe~4vV}r4T78g`@+MrnBx^+$Z(n_|?_!4TavEci( zJf?$sU$J|*bqX?*1mKdhsS3*I(GR+u@YQxH&X;-hTDt0TcLO|n6tn8mvrXPcKqyEl zy$U}7b*hGZd!lDzbz2f7Hm4W@NdRny6L{9f9+|!75?6rF4EI_}!HYiV%@coFG}H&o z1_#)>OZJhP#ftdQVr6~R#wTFI0Tjrh)Y7ftNQ-t;Ya6*?Q#O#;huima{k{_~NWn~( zT)k7Sc1jbHqmX_Ctf#r{%yN@vKNj$}lz&`&aw_HIdLz2H|A{ww@FiH%s zv+0e%2mm~h%m!W@&9D5h(2G}LI3OW3Qg%trWb#GhHxgLR3Rtq!rooARg3Dj=Js-Yb zzqrp~F}s6~2w2gV_zM$a6O%ge{$A{oSHGz66d);{6Z-fbEGf&7O-+2!Iyi6^k#4iA zcc@yCide})7Lcfeh~C7F7;y0H>=pLT1JB@@V4#lmZEg(9z|yao%izJb&iXVvRO#)$ z${E;9xvKPeuzntNqH9A#uj{DhHJ`ojt*~~vIt!r=Ph(&oxsob0gcPO-ZAzd5(pF1q z7TP=71Vk5=Y=sp&6hKV-tU+_IU)O*CmHva!{8Y}6NS-@k&u6rMwJ@B$-n$w$5IG9nAR&czLTd!Z1rM?#r85=yoJ+O<1YjgqTd0^hsnZ^bkb+Pw0!jcE zaH(Y?Sho0^Py#+ED?v)C%%xq=70%L8tNp=lZ{1woM|bf3>`qBN4OYtKa2qUkApwY;n2P+CNd=LipTqA4|hDyj?xLu zs970_F$e@-NJUygA^?dS3#v#2BM4wvzr45b9)CVyeGpzwF6}>^W5&^~pTB_wuBkjG z)F=XVj4(ZpFDrl9o+fyVb*;ckuk^@N1zygW?=u2^1>8 zLKI8g73Dqnzj^e(Ub)7F+h)gjP5f$z(Zi?0GgPqYJHNQSVL@ahbxk#&vFyoId3s%v z3E$YU71Vg4Q-`9Fej{ZREL|C!F|jcaznXIvv*}UZ??gTf4L@g}0pBxsjQZHEYsvTu zaAs=D-5;|>{n!a72kd4WmCd&8obZ)!C~9(XJjmbMR`0PKj$xhc-0jKw4ouI9J5V3z z15wsp!%!```(P?pz3Ivj-IieVufZmyuUJLlOF4 zz#z8}J{RTC;W4OJhpH>QNY*xMg>rC9!^x;F#b)!#V3eb)dNK#IrIo4Rlp@dF6F58iHby)j_UO#VYyS5+UwG!}wps{xiEyiNS=1 zFotzo2gyzkW=_Zydt_rb0;gwgU=SuqT1X3WdcBk3(&Ik0uH2>5h`c-for2u+^!mDR z@RgjLrfgRQ+_5W{0!Vvs@6wF{5x^D0Wq@Nm*_gIZT}?qb*JDf&+V&QA7SG3~8YIlJ z&ohMP(D$^jrfZ&49yyb{+s0jQ`p5scH?yNtKU7I&a5R+CNor|&R{=$f>#-x(3xfZQ zwZ$)vtMyppl!Y1_+b=lonSap-ZfL@gz-9rp7775YiYNng3l%B>xK$vQLWp~W$(BPM zPkrl)O8uU;11= z^IQ8uA1H>1WuT;h5H(3zZ z|7!j`@0D~G*U6;DVLd-xFHw@<5f@R^nh64G*V-Uf2r|nOyg|}1EV#rM01%d`v()4Z zl<8WVo*Q&CXJ=le2=#esol(QXXU#ZIG}edKQ7w!`AVxJyt(rP5BkMScs#NVXMM>qC z`pNID3f8+jjo{|PfX5rE zl4cdGK00)tb=JQAC2Q{CY#*Y5B)=sG8Mq7u5D)^|SW2@KeaLOQVx+tKE2D@o}C z-UkkfR9@6&cUK%-!b5uWf7)7-*{oE{K>Mfj!C2pC_N&ojqmL6R+uBo;TWP)ZR^e~0 z>zdtnT+_gn+tr4&dvB<~oAh`0K#m#P@85Hya(X|npZlKA(XU#1@)q~oK&p{#oA)2* zj>u{Cbz01a;~1K!$zrGO5A%(h-@o71*2n*shvMmADnG|-z9KLS%Sutr(tfn3KLOVq zc+~jmo1=0YJv_&qK6>Z#$UUx4t*psYIcNEdYxs0_FpCT?QY_r3S^tvor?^%cTyf?+w0&Y^ z@l5jzIRPpTp($ad&2e7%40{CsfeuhH>!AB}<}GSTX6h!y+l zr8V<&NQ2`kML#fy#sNRl+;2?1Np;org_Z@=63KHc(?|=6j0m0LNiYTof~!tFVlkew zA-?eqC~C8X!-%b0;|l>%0gX~PvB;v&pL}VR+0JFK{{9nPFlt4Y?Fx8MxKP)x|K-bX z$gmuCQ?@mGcjh3*1x8)PH!y+NSWMb%=>h3_0oFe3%{X7dISX6TaFBIn@E#Kt@TL*e zbV7k*po(^-*I}D>+gB7XWu4pONm$LTMOjz(!R2IjqNX)pz6LJ#?6Rz?{IRLCqp&*Uza&T4`s3h zF)xh2zup}-`?)<5IbuV0f0uQRe_1V6*gxtgu*?1pem>8oUS!Hm*f7l49iQeQ*X-K9 zYBw?-Xbrj=@11&ds;|3Gq~($2RX;!2<~i`Ap(++uYU4AhA6TMk`m55-$cGp-LsDlD7PRDLh+p;R-yYFT&QV?@fMJrI zN51rS+2eAKjYA1z7rlB?XEcHBsTT-KW1WYb2qcoQvhu3kLJbokGVUaR%B%(`p_ll_ zR(qnbrr6DF;_L`19BKU<_f7k{xXqoaFD{6zy#AA6MEd-MkYf6lCB$Ar&ca`Fw}38n z2Lk04UfhIc?l@pq1fGCRU=uHEyc4Ov0bS2hoe5z0MX|u@`I<`v{dKy(?Z3iZ@PnUg z(|%iC;$4U&290!ue#i1S&~s$)VS@n!!Cru`Pt*YgfVo98*hr!ey#?P-LI(v{N(od2 z7E-2kJfY!tQ5DFk?Y!Mn2=Jl-zObeNYtQ}-pA}yI@ zBZ-+t)o1bvT+Sun6*<tE{hFFwh4eYJ1d zvkT)-%UX)7TO9+0lKsj)u>^+_(9wssPiQ0(3bR)%(30`hBO1=(t(i)a#6W;B3$%sh znE!(ID+S|Or84Srnw(9qZ)O@$R3LJUSMv&QKJ4BXcdP(R8dk>0gmNMUW+WN`9XU}7 z9LZ-C&_YGiAao%>0vym$v@5OktQHVT+ga95C;>+c@`#xdUMD}f`Xq1qFLpmTkYVyLDDQbb;%cuNapL))B5W)S3lA1ToTG9?J$Y>qu`Z}9;`WY# z_S{WXCGONtZLTbqX(5R$lK=u$1p|{P0d!I@QlWF+hBG9u_y?F>^7Ho;eE+~Qkd<(( zq(yg$ip-WrVMD=spoAY8SCKji7{oAmc`0Ib-$ADQMtI86XH^MRN~kCY}G zD0NrTlpF2e-v2vpvxzl91lAffMG}`R$p+3 z%h*UPNwv9chp|x3Oxs&?zt^MX=#IsJTA-xXhdeMVI034m7zsGY)XZxaF@53!$^@hU z%a;Vv<9VT(fZneSHzHRm8^6u7Fus!`tkt)mM+2dn-A$}XxM@yp z&YdZfI<6pTO5p4$t0>yv+uKpztFoFQ6!F`GrXk6{D;OsBLuQvk-&(kvM9i9uLicBkY zMF^!rUEvCgS&U+hw1hBw>E2kz0pG&cKrE)abc6k~V8KfObh`ji{vhW0qt zP9eN-3Wem;RL^J=rZ8#U2qj*bN%we5T5WD8pD9?P+&i@V&X4W-dO@rUB5BsH(F`vx{Go~NcPmvzpJnawJ8DSlTd*EEy zwcxmsW9Y=Qy;Dq|-~OLH-!ii@d@K{vnu@ksmW8XwQu`$!pe(D$uHzpK_T^{&gygs^ zaki#x67$Hp4l^k3OD!Ir1;%tkz#5Q!SS?olX0jpZw;-&h6vF z`T6rtr(0@3&`a^w(rZv;nK4ZfEAUqg7E^$U8w02S3`IhEji_j_L?DjTw3)|$_w%p+ z*GG$a5Y=5Md;dEMPL!=O9d%YOm`)HINyQYu6=Ykfuvw;x*~li`a3pOZQ~@5$4IsFZ zP`;Nts_S_@d0A+g>RRR6bF9n+ZaYdEY7ki$>5Lqt=U(kj#^uiX6TXd1q#4EoL++l= z7Bn{-NbT^EyE5REs)K~csl8mm2L&k=oX)_7jlWKqL?lbNG9|D5Tt6D?A_&A{3^Bs>53HDZe5RLQ=%BU=%Sb1`r_t zBPfe3Dw`+Rxs&CTm?K3S=+vB09#>qcR^-FljzmE8IDNdIBkR9>e>2~xoy)vyvd_po z9(c>jL<>}tP;=%#gxy51f=efhY(xg6#_5D`i8 z9!I$Biqs4Sit_ke&Huix;5_{L#ZNuqZEONVIf9rt1jmSb`_dLE@3+c@2Vb8{*B^8| z;zur@B<(siJ((R)MBsZD68+OZ?h8HV>&F*(OqjP9`h!c8LkPILE1oZW)cWEaEh1=m zoc;ZIsKpPQDZ5M`%kI~I2F?4;veXqV0t#W9$nsr_8G?hyQzGCwMo^#nQ$YVtd7wjw zFtFZB56PZUFVHHeN|E*9#MFU)o11#Ao@o4@qNL@0_#`@>$4&L&m`3;%)wV2npfp@# z35(nmyeDrxYc=tjR)hyE<6@JjV43j{>gT@n99wSzF0Et=mW*qG(TDnRss|3bQ=*V8 z(W+0-f)@0;0>(iZl0MKLI{3f+YfQ&bK3~^?umn+Qglnj9WK>WEM3RlB3>6uArm-ep z`k&3Ax=Q%=-2W-P5Wt$cqjL)b3bq)ztI(B8nFgHU0vfOhMwLoKMbFRukG{R%S=ZTG zdiq_e#y~o>>_)=QPQVLuRV**+9%Wdo01t8(C~D>!^ul;O%`~~XVRNRtzB8$?)piH8& z!_%Nu#aryYFtuNl=)wiFG=VdVA8CR6yz9Ywkg!Lvz z_qTM^9xrtHTeF$$%FF9JuN&7U?3w!f_~l|tdA1CFc}vE3P}M}W%#yr{*U3}>%9Spy zu;$nYybdhCS(iA{mmG8fhsRG)-><&r%P-)uaMh1tRdyJBxDezN!e!9ae$W9kvB!3b z3jArbpg@;*qdr`P)CoA8&LdLMA{y`zKndK8InMVJCdO_xN(z-rTp&GkaewlRl3|?XKIq0MzL98bRx7_CO1aphX3u zyW5Mkywp$xq!em1m<~ocPgO``(2_h&Lw(e{RU8(nrt_BbbirkDJOVCR(Xkk4Td(t@ z&fyP+7{q7Zp#_q02Ykr|4n6=s>OBTzIVUcYFcjKiEx|A>;VxOZ*Ig2%3%V5)pl~_B z)!sAZnjp}Hce$%u0pg*;SGy@I-+-?sJc2N}mS>}Wxxb?2Ldw9XyPh9kCY*WBP%N4; zj8KP~tpVG&Mv@T6J{$j&8o3_kP}j(e->g137WG!@AH2|3=lZg|V0jj66HJzyWdjdT zPyui>pwuTA|7^T;0hN%HQofem2$ajXE&2`xz}ggN+|S8A6VlBY1^Bt|g-7yJHdtQ3 zYgsXShAgJ>nL7@7qnAkRI{VSTs9kviB;y24ARsbzPAHNvMlp~;cVG~fG%(%8|B?`54!P`I@0cDO`j(ZAJ=hCGv`2Y?I0LP{@}OxK z0v3sqfGo!0*D=dyHjUeKNz->CQmerbTslg5OF+aE&t~k5snEq`(5c0gkeT78`N+A5 z#+T!#$N8P~#cT6^uKc-^aIZQu|B2}UI7G$DmS^H_n3O|7K%N=nB4_KE!&LxSA!xzw zwB7P<;(+O%vq4#&zMAG4DZIcTi3}cime*tX!u-z7_no&u3(&N(gszgpbc~+{r3ovg z-2g0YEfvsAM^$YoN1<-hUGV#@lFdEU>mZZy@mZB8x^KnBN{Er8^wlQG1W%mpgqzXa zIvZ0y;bKJViE!=LhX-@g)Tan7H~5>W-)t~j9alSC+Og0mvrjA&Hq;(cDd2ws*g3%fFH8~n3uLdo#L=Rj{yWz4uzxBcX zSayCpKOh?_hA4;@!o+x6c6JjBsbJ|(iN?A_$eQeHp?-gB}YeYdeV0@yHJ*)T$J1&FJ*0~liAMWK?Oi0|Ux zsQ$MvIIEqBCKB#l2A_9x+I$Pg_eJ}F)KOaN7wVW&lTXJL-UaoooS=umPz<`kX*Lx2 zf%pPDgGk^=8DvSI#WLm;HZEVo{t-f?Zcm?;VPwr1FW%K2fC6Dx9BvNb$hPE^HTI|* zwH9Cwn(R!ha0`qAHxv-Y8RU^0kwB%X$tm*Gr11!WtjjWK2O9d|1CxuSV;CEVh7D~y zXn}7I_WY%L!gqeUze-~5t7q8v>7#qy3ohOIVsx~z_V7`S&XM$qFYE1Dj-~y2Bi%%? z_-wY9uIwyMDj;JSBD1)+SazrrSu>w~(%apv=ovUa62!S~I!^UQ2a(%L=%|sfFf`-x zqq~;_Ha8>Llko)819Yr|ayCf1i>a9zL`-Y~0RS|TA@YQb01$T|i8eR`73r$mXSF7- zCndhQbxn?koy@bCK@^?>2Dacp#2q3uUA6&%0r~d6S*(1E?**18$j3AOs`~Z|N8B>K zaTm7|6si*}x|AFFvN1aaPzJ)3IIBSQWd7f_p5Dl7lscs90GHD@(8*-gYQV8GH*rvW zw?Z^QraYT=vmLgI@nNhX|MNDpSnvX&|&XPBumPWq*1*D_TcRfD&w9K@# z-*dWO==`5jnEn? z-{f*sLz;3KjWS*4jCyDdWR&!^D(I}8mw8u93R%fOL!kgd03LASxQ5fRPY`k;0zR{Ia^5f}T4OOg6 zB}8k@B<%(c@D?-6l$56^k9ZVm1P<-6wfi}=G;75IU&yHsoI}i2N>P{wLaJ0KhLnJ5 zBtR_lxKO2_t5u@Y%x1%Q=gOW*+-ZS}U>F|XOMg1}Esi@D3i2$cw&(KNQJ2qVUiV5c zIUkfOP^wJ15)n}ZQqgES9gPD6+j@^Cd-k$bM^WRE%2=jHMFYJkIvkdD8!i|_q_1F7 zv?h{Vxow#)`wa3#ZDfH5q@yr{cBV~{fLM5XRW=;R?nuv*ALY?IO8>fk#LpWM7LZrQ z^RU0y11%^nfp60$$^7c!bwAeRbUx8q-1t6SCW7FC$m&gcy#RPpmH+`qAoDf{zmq7 zX_)Vx(*aK_$|H8DFrFAYj<<~Wb<7G7K}T-Mc#KfE1C~M~2>XTf7ME-(l&%6(SAHz7 zzV*8PbAS0)|Mly?G~b7~Jb?P7E88lSw{#8xJ!39Fr!efrTveyI@(4CfD>Lgcr>$vO zh7yMmWkkUer~pc)wa&ioSnShhAEfqZ!Pe+66zFDUa}>j0nMxoZ_g7obD-(Ys6QvYSWQsini(~nE7^oeb?NAd!L?7 zy-fXIb9L*d$IBCAwkQ@{@MP!lt(I?HU$yCdbH3@Xs>YY0c_u#K38}HUuCbX>Om~nL zF#2#(3<``$YzIsPPYhg0Bo$1s&FQ925v1&h15(QwFi35gLAsKUNMw#l!+54eq51Xy z>9?Q1W!-LbN?Aj7d>(hW9kiS_1963DL6RQ!!bCm!P8=&U>Im9UkeI{(fCKwNhXFnQ zbl!x=^FLu|UQO`_qss6;b2_HPr$!iuDU}e|w{m1*|KV}+uTMsn7{jH}u7R&&V zSj#7zUd&Iy3bsV2y<_|h@2xyC6W#avNM~}_y{0qM7VE{skP>w!n!N3yLHHmF`yqNj zvME4xq&8+eRoZN35T=em9VCS4il|PmXw=KjEW`Je&11f{{U<2#oj@*^XypLg@j0%` zr%c|^Si;Wxs**2HeLMG9n$=!+vrWTgqr_rQ@Aqo-Y>xSj!#=ikWMh$*7aMn00{uUm z&CkaEZGtCi8`EfQ`e6y~jL!qQoYtYUP~i5^+4R2lIXsg-@{k4Fkc1@z&5BZcg;#~; zk|cDX(~xO68jOis{QJePYIM)9_WlikV=HPJSdVGF5812dk99dMfQ(`UWJ+OVS{i2V z5P7qL=j*J#{@p+Om#DhUyb6AArPIR9_&!qSZX9lpd%rzNW<4}_xA}aqURUdFLp>lE z5Q9eRB=+FXD8ln52F!`H=l=S9=40aLy?CCj<7iYUh2^x(lHz0GwYAlj?V0sFo#*4P zm+-aiP7~JuxJcyuS6faX0ev*NRZej{6o_Z8>MV(S+9h5Q}cHGHy^I`mo|9_V1Ax%Ox+bbk{AP4$ORYq#Cw?v1*8x=ELgrshGYRq zF{rlpB&Sjc<&*Ml(Mldn%EO9tXwJHA0ejh{&e-mAn)fMP?rS$Whn@QA9=ffLSZ1!> z0iL;adeE%V5>-QoQE`>6X|1@X+-bmgPNx?~Nov1&RG57>JGgc2N_X|1>ZEsm4tQ<=I~w`+ z`-Mu=@fkGB$|^@*<<#dT!lQ@V-bwI0&xn+0P~auM3@ZwCsS1WPKoRKJ;;->jHEEan zSbkny&ofcOI$t|`U4Sjs0a<3`f+T`p&&iAVhNEk?sByj;9R;ifi)}we1x2+~91Q8T z2|7Us`7LO?2o#LkU$AGmu1=N~rx!^X&RS*Jm-n|4PQA~;U!PQqU_185<%4$hk_BpW-Co$v z@(ksaOfB2)xz|4~Z+P#(Fw|d12bq~=?$C<)r|{lZY}K?k<5$jdfrh`wIvM@88tDj-HUU^nBwld_9I1vE34hLJ#_3CJ!rddk}p zbE1q7z(zGTxcPyLCJ{YB9?Y7j`(^)+?#uXx$*p%=o-DmjtkhzlfrI^!`n=~~NdLW~GMu&_!!R!!H#5ftpjuudn zg3fV4WQjM+`%$;5ep=#%RB?})POuyA1&9l3$D}UCamB?i^{rgH0k&@w%)i+2xC@E#uE7gD@tQE;ckDnvDoOe+TggJ$lz z65jNd?Z+%M<1gs5VJvgd!6;%p6!ACyOM*7eOzY!*XDrhODz%V>G-Cq*Vm<0Wf(ax+ zV+9!}0Kjz(E2dfn0Kg+qpW>EOW~A!k1tLUHiQ;O|vOO{^)9BNgm3#80tiJJ8iU0uB zM#UC-3?3?gk`e*c-hQa=PIu+*?eza2)>+xBQAXo#Wp*Ifoz^gE07L*FPzop^q%i|X z(Eyb?knB8*BUc;cFumnNvaEwFY@)?>{w}^RVE2NgS~9k<#A%&tq{j-6O0TH_@ZE z_shTc@cRY7Ij!skTC|iPamBCXE~kF>>M6xrcu+XzF;@tJ5flt{6l8Vvs9u%^LRfhQ zvvr(uENHF?f*DN?L-JA3cn;^}EF5Rnj*xf+qiCI=WASviPN-RGBfy$dpGJ3FG`C9m zQdCQwasV+UwdVKYD9>p;>pyg9OyAvRA!g~mb+sav*?K2cUtL#w87%ENYRaspPMZ3H zr`w>q<*A5g9Am%JKkQr|eKx(2*AM*K@SHT-!?~Lx_IN{Jac#9OU7c+&cXW}O^|KbM zIPSMU4#zn$&;{~y9$zkYo( z@O*Mt$?NH?zjoJu$c`9)OLLj6dn^SaicEDr8L#EK=iYhx9ew^%ImTEuER-IPZ%x`o zfgxX$bJz@!3XcevV-B8TI#@!p2ed4`<5Z+6}m`{mNE zk~%kVZqLhJY{z#pb5EQ0=jiWWpl^%w#+=wBQ9_OwBU;FoXoNvH107biWD)|*2rA}V z7I3m2kMaCQz3i=97|;Ph`$61zoY7Y>`k3^AoATvqg+FP3?)i5z5cV~97Itcj@gy>1 zz*T}(iMHLJ*PwSmW}*IG2t~U0qFQl_*QeLe-MuT&IF>`Ne~9tmwC}C< z>f80RA2-kayC>#%Z|SzU{$b``+`Qyp{XZ_eciz6Ze$%CsUT{Wn&VP}tv29SCpVHHT z_@1L-T~OBi-978_1cRmDn|8skO0|)JTV87@AY@0(W@CBp3jA>oSI^KRV%BKjtsf`z z`|PW6@N8RkTS?Z6poC>w~3$vOFY9#^?jy{aC|5=O`8 zkp$hjREf!?1m7-un=Fdy%ugZ$4CXF4dR(aD2sY9*bXmL4uw$_P%3A*E;OEC{I&AZi zQ&-K*=exRT<=0oyF0q%a@O$WFS6j59?kDcj2@D%PK`lgK?94T((qwf9^Z^e-W?!i9 zaWfT=nQ`J(znqtx{lUo6k@!H1WFhzSXr`9mciW}bL*wHh6EM)s(i~JNsP8wsWd><| z{NnX=YepdH!%8`?JWq|;(rhXZl@FvrLn0T~G-LnnFSC}f&(tHB!y-d$7_>x|ROjFp zx@#U&xClmqh61_{?3&BI_Xzq%>mH`or7mOdl1JB;M|9bNHeVMV!2SuygV7mp^mrf{Y73X;o7}d>XW+d8J^S~(E<8u zuHT@V@?y~sjMOMtc8tfPJ8juqH7kK9;P&$bG#&V}*U(yYh?O!$&#O3?<@wSKD^eWw z9d|ld5?T9OX4i0e0XtKNT`He_+vPWU4;2Q);KAkDba!TeKYo^dmswn;SA4^u4!<^o z^H+DKn+pWDWf?l;7fguJmc0e9xdW~Zw7;ke$UqBB<@_anyH|BPIaI~bJZWg!K zuRUrd%&R%Kg;)Do$*aO<`F>wJ_e!_E*B=k>r~E*xs-QB=#yUlIDuqY!gUug4ed-@} zhh2X0?XLU&%_VJW?Atx>f2KN~;YUjO@okiu_8Vc?xcN^1g(U0<#@Zh~N`f6aJTK(6 z576`)m+H3OtL7jT2CsQ;7&2M)wqq;vu%_5bJ^&(`|ot%}JFz?ZW+%*|? zN%0yTmkuh8l@m@t^k=P%YwyWyr$l?Qha7Q00AqJvu1&n3S#HNY_f4(mcaNS6kNAwj zjLb_9j&2#)JnSEO*yn=Gn~8l;z$6T2%wkVaD#p!dScuQS?TgE_pBjzP~C-(uS6C;VyeK|}|9 zkN#$yawWe0B@7;t*e`%k;=7oRH%XJ!3pImL?$!%dS~!ttSeV2BZQU)&oh3skf&_K$ z*|RMtS%ATYCZk*xm4I_p5X4ZJ0UKd$low<=0tjR@aE3unrqEYliUvCoFhDl4c0u5U zC02+t=H$T%U@0$Sx&6ixXs_Cmg2`OeN&2G#LOGh`nILt{x(Xgl+l;@~m*Xf|U%EbBCW`#f>|1CT zzSYRWozLg`Vm1^*OQ@$a+&Y&g5?RHUxftz8%^uq&e&tWMIsJ4w{9J$EcznDGN%4YZ z8WJu$2^qH3u7R-1SlSjN8CQl%McJlXxhts_VVA;S z2k0lC&1;AP%J-hcuf-lMH)|UD@xjLBRrzSJy<&spx&xbAeai00bVYp{Eg=J3qo$!H z;u2Xi*{ZV2AkODyUA|Fjj3^^D8UvY97dyUcw2k<&N@|tPdZ5 zIQSE4R#peRbAS?=QbI&&q;QRh5aajE;Bn1lUeZzQ3IqvYnarji8X`#P@KGj+K(Qo# zay(3-#iW2S+2~?gJ8K*PI!d2LSzq%lDE-KfI*1E?7~jq4H@YRFJJl$WwA`H`S71C^5!k*#UOE86p^WwpOo=?*0 z&$h#g2hH`U(($>N;%P~Om^LDTL|)ocvmRYfHzrP1lw2bfN(hal-AaYa(sC}z>eH*C z2juJux6p%3HV^9~HgGuwvfz7VlA16`QmIhig|cG_9Gl6v0pMU$Di8<$f9w5Ur(ofK zfp66&eV?OH8{aGeurM4L_kaltl-1%Iobw)yS9!_Xv_HPjnB(_Z{{FI@NCtBxGl|5L z^hv=(0+T_(F9`tv10o3!Kp-X-0IUF@fD$#q|5H#rNC9|+^#5@W`GLanf2-nx1pp8L zKtKfmF-t6Xs;gSz`u`YOf5~TXfO$w*#sq3qqr&j?>_hxg`K|nHz0-S4|L?0Owx7E^ zv>gzxPhm@zn@}mK9f-sL#7_mx_$;pTlYp(qzUT_QM3-LR$2iZmb0Ito&v;YT>2SKiOYNm7Q82Vu6 z49F%N3cUM_w4$b2cYkJYLI4DO?KM$!mIJAV>lh*p`m+1g_j_D; zY4Mr8&2?D>rq&A^P2%+`NYAoA&i7?L|J2fR27Ivjhg9p-BtUzoKW=HRyr#!j5x_b^?J_bz{h=fpBAqK> zLcBiuBmL#`XPLi#r~l(e-@n(mqXu8g#WC23q(&P#fo*dvoiiN@oWXNKKEP$RWHKmR z;1C;`(@SjWMl?Gof9o67_b=MN>8yUpO+tgHV2;q~WyyFZUfwxA{Qjgqy8V*04che_ ziX(v28fhvFD@w#zvX&BaVBQpQ7V?ulMn=aO{q%8;{q6H_j+Y~AXoJrs;Ayqjk&Ok3 z(%zpVR=DX_niUESBQ#N%+;)Rw)Ma7?YXh|M2Ufv~vhRGaKrfXp?&dUwz^PGu+F2hD zPL6rpDl^y!69J_e7F5T3v*U`yy4>ijhCq)v$7msXPKa6GN-he5G~vJwEbr{(xv!W@ zP+F+tsl9a{wEp<+Cxuxz#EO21eVir~cvN-}6Ib#sR7w%j+Mbw|U@+ z*ML<@BMZ^VFWV|{eLAVa6B`Dw_g4E@Pr^H}Tsv;nXviPQ`h z2^uGhtArvr1l_@hMg@*}BUm|?5=lBRea8@F_y$`3{_OrO>9H*K%sHag)NmdHsY<@8 zlr*f8Zy%HaMX+ca$O8nr)Ij@%X2hEC=ecS?f`k!*V-DRH_wG-CC3Q- z1D=d>h;Oxz){oH=lA*axl!`;x&S`-nJ=|nFLarAALgUAY=)pT=!{nx8ct?C8o?#P< zPU(abrwe(ChxMq++I4x69|<;#n()ow+Fa%r8IYmX*dhrSsEbVzVXD(p!3$9)78xk2 zTo>R$dB1}>9bkx7Yiqs2PM1`2Yq86rSb=Lq&|Z|Dp7xCF{C8AT-PR`x??dN(LoMMg$~E&H|EyNLGS?Ao0WJIp_3w@9ppHzW4U% z+u!(l{o&rV*P3(9Jm+sXGnvp8Bm#SznoFZC05v#t&baKja#=LX zIjrN@Tq+|T|L9Qq=yo}6WD@CB0B8S6$9<+ADzmgJj<6TrCOgj;+wcEWko?SV`C}CE;U|6Ev4HSz%K>jUc8k2u!j~o-L~p;?=W;<_3f&}9p+(9bN)8=n(=#8+%i+YP;DSl`EteBXDFI^>g+KBu(w zX*b6*4-dhH>FG9d@afEx;-_fDi>gv;!PeFtA@`aAuH;5ns*;Yz^_zz-j?MS0bqN7R zN^C*zmrc)_Rk0C+e!)~%3Kj}aYnAs5e_Et;``c$V`;0+83#5Y?*#bG{y3!_z{M&8O zvK7*#MsmE34VjVJgvR|7)JF6^p9l{!l6s}^8;o#b@xh74*80r|^4bTKB!PJot?M|C z@zT*Zn9TE|;M_5Qawx#0#+RdkAM+%8d~KO2QM}BeeuR#dw=sf@d>!X02RktS*Wo_#!SKxApS*z<3Nx`Bjwlw%6c z*a_dTZu1PnvS9i2W%=k&X>4bs3Z2;7h}njQYi6^suT1F0)0tc>-+GQ_Jt1I!MzOv- zkoTxA4qcW=`;h1NQ@1ymKKktE9WQ@buy;=|)M(5(7r4w=sS<*v9jH}5RHxbf;L$IT zVNwA%ImgRP>Qz$^k=R&*LZiSYqD~nq`w}#YY=%>c;u-e#^JGwLrlrq#`b?2wnlF|# zY|mtetQ^;Vr^+=65)?q_gjotc3+*kpU-FLid9_`2U-#~PxkD^M*9o^%m!Ex%rjL|} z{dToRm^Hmdq;pnD+bND4Gg6Nnjd-0t#0MsN$#6k%$}AJ$m$SZbYHr9NIa7T6KJ6~z zwvylMz$Z$(MZSB+fI+~uBtxj**S;ng@e%>KK-ZN+@!haL->!vX1=Xuiuq2zYh^w)iHhgu2EIp5k28~~m{R#L z7vX!E@Jc`>Clbf4(`NNP%nE)(aH8v4?Awu+#htMQpp^u3zK!)CES;3?&blfh-a$!kva=$^#}M1cYCpGWh&cu4v|x+LJc&XLqeRpM_5sU?_Is`>Kw z(cWo_k=SoH-O;jNwXe{N*(}lSwH79P57C$}iVAP@G4gA%TH#pXERPTRe2=Wu4m*Hh z)_}cX`}Y;${m~I-pH~`^r+gk8z2$gT6*MOIlPB)uy{*{|LiQtSkPSWr8{bOq z9DNci@y4dXp%6@s^P5_qBz#TuRbZIYl1ss;&OHO3&Gt%{>Jwf!77-C6T#xc9^WXJd z7O_$zP;B0bT=#co?%At0?`7}*qUImvx)+dxH_z&ZP~)Ft+mMX&;Uo=?Sc5ei^N;kJ zUwxHu`SdEY-@g9oh>W?>cB^t<>i)wKcSZ^&!HxPovQG3WRPLqBe>3jVc@!(W0$`1|Er zAC%FP7)SCnm?RzT#*>LhZ%ACi@MIr}?~6S^M;a?-s=oDVbN?nSDXF-c?9sgVD}qsA zzCuu5R&vYUxsKgahRCV$llJRqPGUQ(rk78<;`mBzR-#8*NPi&Ew5vis+l~5Le(Dza zu{r&!3=0QS&IJ1g{o8ZhWi5>1bMqb8M$sPmoZ!#fP47sT`7bAdn-!x(7<$%kPhB9} zc{^EwVn$CMW$(*=V1$}joKtd6aDsqJeaT0$Gi|jxmTvl4`n5gB(UC%1%zXqL@4>Mh zyl=SKFw$2QsG<^kYtTejA)0wg8o9;`39z{4hKYAu?YB4YF3v=QF5kXue>J!AZgFTc z$qef{unnQRYu5igx$()U@NvzAvDl1aFqD(=`})iW(WBF`cNFVK4WF)^-_ViKnZC-I zU?jwl3M(PqZB$~!RVbKTA64Z@LPJ;4CxmHWQA`+Ku3QFY-uyfZ^clWzR;0vutFH3N z8e){iUcoUP zelM2ZbyY~S;S)&-)C(VC@(aQW2|Z(7}4jb)v7+O`%;Ub`-(OCr({S2H#QvG$iU zHiQgW8bjn|%i%wUQoo$ub8MQksgV;o$*k~GncI@P{Jyiia*V{{ez{uw+wRF(Ny%rC z-$MHbwdtC<&sQD`?WR?2PCwD7Y#-09_5HnrNAPvIuP=f8@zzyi?QZVviOnhl<*ohA zyM+Cf&MyZ~(VtRgk7h3DOI}YEMEibv-A*CoCCb11gyN%`<_G!LsZ~uI6Nc=N6#W|?G*y4-ul5n80 z$M4zGS2&kHeQyx{Pgg&O1eJR$72d-*82ae<4(5qtv=v2|UK8T2@Z1fGz#5(q^!mDV z@8fRWZRc~%acj>=w3D|y5#(vj!I3N$jqS0Fkv?8mqdWMfXXvKn=NNnUcAVM6c+wpX*ZPsU^*UsUf2=-% zEcMeVi#e0|0{}*;EF;`2@cVk&r%yx06TXiTZm|#Qjyzv$gV0LFLz{zCmKkTv$(v+t zW4G^3jAVu}E~awieU#g#8BX}}q`^ys?a@<7%-5^s4pyNd{@2wGigAuri^n}xZeG*N zRcZnxk5ERe4%7_cIYX=Wl?7xJ3;f6gz8N=IFGbJy5O@!ruob>D+@0}#b@sTyGli7s z#f`UZ{kPu=XZ-fxB!x4|K9ibYOzrg@d>y=gf3a98Mp3knB$hxsr0!>ReBUA1dHQp4 zi$m;4gc;Xn_`5=hbyunX(Hz9!}Ka!rUC5%THzRj}ZDl5cD0_sv{UJq zoY}2N;~>~~Oo2Y{mW7x!Ygq{MaC&>J)T%1ChJtJD>rxkSV*ZeKdF#Wa7=GPj*FMLC z4xPH~4mS~epa2qV?VMxFO4vN7#Wi4PA$sMX{e~JVlgllpV7E|c4g)*Co?P0iMD6#? zb=j5e$?tg4adsb1hc>pWp^0p8OZkRu{|!L+?EUP>FMM&`Nj(Eq71muP)|yo`BjNOj z4BPo!H=~qW54OYWWB&9F?;jMJcGwL&&MrcZ&)#%ldyjSHGKwV!<&iDdHG|R>rPOVdS3iF=p}o_$43PTDLUX@Z(4fUhWR9(AUscE8 zX5nnJ;r`;~(~H}@=f59EUBqTboPT5XJf4sV?)A(BKMZf$x4{2GX zW!yK}y%3+ZT*>3=I@-s%BBT$bFf>a z=lXqZSR0vPr=OG50QoQTkg_7_^l7M;#zvn-=kL#Ty{UTSIu5gQBC6>k?l0pH(D&jW zF#Q(Kv3_TS0Xv@#e7dlC*<9d!*l@HZ*)~&S5*}zo`Pt~uXt3S7(s%Z#MBLbGP5pYA zKwi4;Ldj_x#jz&aenzn6SmS(jfooW=iXVH>wnMl4@~b(h_vGUGk`nXh=9$=0)-r11 z^;j!`{|@Qs1p#+ctX<;R@rUS@Bf1*n#|(Dm@0|gcFe*vWw0RJ|I*b5`VTze#Jj;9j zFkwcCxhe^_5p$;QeS6VUG1v{Z3uemWn>4uFp(5kwup*(XypU`SlQdEwUn?(BUbsS% zVB5Ua(hw6wyZ-v)`xQfJ?rj&b@RxPb<|iQ!3`{+ITj$(DB-s;5m4QQs?-(RX>JMk}Ke%WOxgLmCt+4&5MP%Z-uEhmI}a#-*rvUxXzB*|*n@Uq6utM@fBWX}vL z%rfqgU=h}oDxwqZJ@Owc-qb%?ze@i8i*~p2y}r4x+gE=dQmp{2m%ofE?AKlt8n;YE z(#p7=iT;0Vecj}_S_c5Q2;kH$0j5nf)DPBi0Jp4+n4 zb}J$o)E2L`<;2D^9cc2x-a%^Y(0rjNZP8HWJnG%GjP?PuQ|}L0Hq%a&yQ**fgyDyv zra*MFg&{X850~MZP1DA)Ip^O`id9`|*vyu8z1A<(!Y^ln%KHQxDR;d#t(+(ZzxW6c z^H&vIhK!3)R(EvnWXHRb7>A)t4>C!N{J5TFWeCc-y1mso zyB{s~8*xr|D*2tE(gWvkN?o>GgN@3Y=j^fFpzv&;T*GIjpNS=W{lYP3cHZm~2|t24 z30Xh8VSMdPIeaIUCavE?(w+|F_N zxzH6x8(C;dq8w$LUgTtc?%AbO(D`BC$l2SA9|Sim4nYN^xGr5~N6%ao(*}-DFHij` zNKQ}B$3%bocziUxwE6L#9ZP7>>!};((mURmw#>Pm;gr{6XTL33t({uD8<=)_PIu;h z)LeHAJ&1RjpXoZBsx_#a&81> zr49A~^@$H-Q1q55)z#^Or=*qgEf)FOJjC zK8Y3gf@qL`lpQyHW}rGD%&@TZQ#}2hkF?0jYpxoIWz&2?Qq6_k+cY<8l5L?@rv|?h z%E+sSH|wu%UbzQ@09s+7==bfFTiR{VledJcS3wwIw@&Anx3{wyKX1hVeIhlK5>}LF z#AAlv^S{nB8SZzV)qYufZ{r!bxOMve>V+j=9H}r6=)&IP}fZ=iEekBR5@2yW<95?q~!6Wg{uO-d-lE(equTDHi$~w_j%Bx@)OBlabE{U+R@7_ z!ah{2&T2l$-X)dY^I?SJ1jQF5-O^2lpF6avW<%@WlQ;RWU{`{VI0s8?A!g`@NDV4g zT&?p0 z&GWL`t!f>qC{BOu!iTZ^ix1heA1l0ZuRTC5Sb1sb(-psQYjc~n7kRn)N!T&%-IYu- z2DyWcl>xK%*-Dt#{0GfSn%O-Ehm>PsG+c@2mXt|PBr-o{rki}Oc$Sd4=WNqbUtUpD z)Q}SS+BzcxpfR}F7MuTEIhJjAj<4wah&jjY5qqCY_Si)U3mkH&M+Lx9^eDVaR;1Yj z11TDHs;3dY#eD^23l`qfUw-)e%w^6$uXy6ulw!behILMrw`tgZrD(LF(KhckAM{4T zC(t+d#W7>_nn}%wj-6*#HILts{%?2QqZ^kWpN0Ldhx=%ga2v=05a|(A$llTRp0E|T zi>+xBUslBoHw-{l-^?5Z?OyHN`d%-swB3lzy^DsQsj?8Vy!)wQxm&Iur~M#9|M9&_ zp5fWTUrg8pJ?Vi9lpXB z59}{{@wdna;_lZxw--0>1KSliDgglX;S(8?tzWEi%T_7NgNxsMPk+_+p+id^s=4pH zPSu1AqG_+;oA2_?zFvRgvZm#DZ*q14A#L_#T-d9o&N9QN)nf*izDMIWjxjiI)!PgVkHuG~j{=|mdq5qi$p{asJHMe_O z=)J@)^z8L*P@~K1$A-NVYM3j|dX@Hk&Nw|P1CjLDf#>LLX&dKrT z^|`GZhmE7Tg*UskyMz7zh&wp%7C$fVUr(<8!}D(Oa&qwlTs(Y_AM=-u>X@ z0}!15BQF1MEe|($6ITS{f5uh+D=uLwsi%?}x~kHMKi(FF3IBN@>`ff4M5rwssYPLT zUo1?_MPUepu!DuW3Bt_U#MRBhU4&XwLxxR&`mYUl8+UsPQ8yb0XL}2Tf{CYzo0+SP zvpYiD!c-MuZeiwRZsTZm_u}9r%<=cxKUDuXk|Uu=p^rG<8EVOukPW95Jb4UdRY9m6Cm`5E63jq{@XVo++58>sM-ID zd3IYjYSI6G(mSg#c(_?0+}vGl%-k7-U@#62goBBVBf`to#M#-x6=CV*ig35KKv;S> znz`FJIsO+bnEY)O8%KAiyLU4a$2+bFCsSJsGk4e@b?`hLgwUkq&SbY^7w z%LxB|pvuZZe#wpEO&}qS-AhD>pyh4)9Y`l zzjTEC?L@PG3Ty6U=HX!B=+1seC2eo<=T*W--kkBju>Ipj8%qS^KS@Lojvn^*ObAyC zcMn%bp}+4mv$we8>g;OaY2)PKhH$=fgNLgHg7J>f#LWb zAnD}z$F+~quk7{~j#lp0 z|01(+H2<%%b91(^Fn{i9;pSoQ{-0Qx;cw{}{w2SSo3p)%&p(7l{7wH4`~L@)RR8pX z-@o$mZ{45Yk^V`}KZ3FSt*_8uNB*6h-Nw<;!c|T~S?TU1gRryczp~*EwIG54!SWy2 zu`nPU+}MRVoJAS_FblW~)c+EaeSQ&mWE^4i^8XnEWH1x3%j(45g#2B@oGQw7kol ze=%@$y{n8qcRIUU+*L(Kt3N0IDJJ7TP4&l=e{;M$`|QuzKOxPFpr`+f$scNuzoPuE z_c8se#{E&@UqSE>MKtg7NkIIMAdLSmB9qWRX#TTY{rgM+>>pL~ubb~&#`sqe`1h(Q z%<*@*hY6cHnfv@z3Z4J1#lm;h&dJeA^dIHxuR8zi?<)CsW&g)Mg6%Jc&i_vPUmC$( zZTt_ktOyUcKY{R%IRs(mV_nIKAT`ep{sIBk3=qAX)VRg6TVak4Y zlEdzfg`I^XhlRu6^54CB+1S}oi%S3NgD{7QDEq%lgs?Fep|)`_v9fq>>f!EwXTpCp z8(|wqXODlD{J*!T?;K(8@mB|Mb4UC|L`9AG6DfZ>$DfbS|1mPL|9MjX!xMikCr2}T z8#6l*>VE~SyS0rQ``;1E;N;e-4&w0PYHAU{rux(j=#Np=k>q3 z|Nq<5$p2pdv)6wz|3CLKadY?|0RsLT^Z(tf&-H(p|9Sa%c>nkO|372>PoDq(S?=$4 z*u>r3EF4VjeGrV=;?I~XjF#|X;E@b>|Re~cr4|6;$xVRt0d z|3!s6F!uL>f3f+~rP%*i-qBpr+Q#0T@o&<<`25F#=C3LBe+aVqdrJQ^zWx)D{A~z* z>N^>!4gZY99(QHZ(#Fxk{GX<}3zPq65%P~=>3WXpIsaS0@;^n53@rcDiRJG1 z|3-)Z%c8?So&LYl=>Kzw_$Nj^EnMCHc+tu7uZs2Wu<`!~f#QFT1{wYxK>ppj@7@^x zSHXt=8yf!q#rm(~zyC^L{y(_mKf`}~oZNg|od3ta|Ka21=KkOK?|;TpmzR+dWhMl) zr6p9gR0Wi{?%p|W`%Hm29YXsK>X zzqMg?uy0}KVnYzEw-5Y_#zWa1B^D&%PmMe}pTpVNu7jA*J{EqjdI!b4@h5?gS;u~P z5fPMMmRNr-sJXP%hPc7ck3qjO2#UUVXq{N5UZw8!<@8?H%J-`3!KI(*A89j-ZZ>?G z&f5r!cK1KD?5m|+*J>XiWxp@13n`o=wO^bIH?^IYOsW|LHoLCB866gAT+%cqLe|&) zdhWx{d{L6XQ@FpwKgUtR?kw(jk0*A!L>)z}joo(ByX9jfI%?!GP1{1bk8-`pUl-tE zMge70OnFz3&V;d%raF24p}g`J<>-lS0w@#IPi7=sBQGPD@Iy<2s3>gL@h7iZCNI5_ znlvU{75QmxkJ0yhbZ3l-z5D{&q?}A7$M16Fp^@71x*Ml$CtS@Dwfa<6LmR)GVlK0} zB(ZUT-oVo`IGvP{Fpr#ZmHaTq_3GnP_3Hw2^=1X)TmZdRBA0sLtn`A(djx zPnPn2Z^P%;6z%^0d=bwNrK%Jd4r^|M9DY{mpVNm&YyT<#WoDZ)9uF_VeXww>Fo> zf-D8I%{ksY$4~kGw*4;RviEI9ZC>r|@2+LWy-FP4v}?9VFu!(pRN=FH95}G<==pfy z_NK@&St(g0nO8pEex`?4UNARH#h)eFe6GyQ* z`$t_suP~sB2S$|+038S<9AaT3h8r7PT%4we1{S{Wy&2qx_8qHZ+ayRVr;ng_HkU%b zH>SX#+4aXDi*}Wc?U$LV#r=7^g$j?7%4u7T(kbTbE1CutkL|9w7YFyfyt*HbzVs8N z3=n>N`ExBQT*3JJ#&6e0W;i&pT&W7NAROHHx1laL0137vDZ&1yp)RBJ-~16E5(;4; zOr$dieFcf&!!fR?Fz|JFQNUO{I~kJ3GC9d_R$N<4U15_|$2X+25P4aBzat{pEcUVC zIBv(AfpNlOu8*-bCZSlDDPbUB@;oRR!b;vJ(&;*erK9s965Fj;pqIpKl!Ro}n1mlc z4|sG>;L&|lyAR3b@p;PXD#S`QJkbVcBog!0qb)Hv4aC2PJ^Fn zZ(O`c99JGd@9_wdk8l=1oQomA)nDpfg3dP?R<3f3<%J5WBe{5S&6I1@s9~LX8b54W zyWNLAsO)JBGP5PeEe(>GJ?bMtKDu0h1LDf&KraQ^#)hP&xq-{s2c9FN3FXiB`y%=d z^eI2ywvk{6plCazRT*`tl|p{Uc6Q_OJJcJ4gn1cpB%e(U)>g%tC7h9D;h0G=l}QtF z@+x!L?q#!P5vo0DF6%wC2;~s!Bst!IN_}$t4jNZN<+65dzle?*dD~jyU;fhaApsi+ z>3ZD}f7R`FB^=eGQ z3yzL$(T@Q&|Szk2?m;#I14{E~jX2@a6VN!CkEXj^3JM*WSx|hMBA}6zR36x6Pd?_0OSDv#Zdluk_M19|wKuyCIqnapN%DLKSm{lsb@cN19X>cWRhu{Lkmkk| zfl|`u&1rd4!xSDqd=(=Ne~C>)LsL>VTR%}C{UU;smAEqm6pEw9oTlLCU=zEZ<4D%G zj!=@SY%&7z1_mY%j5la1zU&G*HD-I zhpr{Zqb9dcyu6&On!Z~y=r^kK4m1?E>DHgUt|K9Xz+e6#eN(Cy>O8C?(n~gxgA;=Q zHjx05=s|IrHG$8o$3?EeDDzN0Wi?xRInieEynOZO<&!scjlF?cb$y{nYex$Hk00#Y zzMV-|T@I{Dl*eC;ZF3o7ItW9j{AJSV^h+N*=DuTuu>~HYYMwgei^VE8_aL+qgIUv| zU`8ku!GaY7hagFT*Vbz0R<>oLKe6QPtQhjcqVyP(X*)ZmwWI~J%cvS&*mOhX6rUT} zmbM2(u9Mg)j;5ulz94>~pZj^g(yxy4QT;prBMYb3v%kMqhiV($9(Oj(&hYm-{DUeHc8@7K!&euA3ml$JV&7%G+{7-7j@KS4W800+ zH*bd>HD-N$xwxc^ecT$CUkyx4x%kR{p~A$YdxF0s#}hP~{|4 zkZ{S;Qe|#1HpV40fL?libS-8q)A*8q|5~kmyXoF>6$sX!P5D|3kpUX-g=Y|GdwnX?`pPHpt@iGEPZ#Wv9WBrWW1zI z{YBKz^pFqEH7{P&y}0h56I$GnQ|Hqp03h~|N8zfkt*OMTr79&E!X|XB;+b*x>ec1< z$|TzlG23l+s$yUxdK8pmx32y+-Wy#%mi3)<%H`$w`2l-)(mY{tt!K#d?=P?Vbr~G5 z5GV56MFvOoOtrpKrBhlDrSc=8$eJxV&geQxfjV#XJZordFq@08Op&4F3oSHG+Xj`L zG+Ps!s9xDnhoC9&=QAQ_HJL>$q?1L? z{JX||)_d<8K4B4H(z4E%(2v_?PV2Z$m?)x2>hv^NRbA9zM(>zH12?G6YL;qP+hAEE zTRhVQU)HB76i=y_O)(eKpJ>$m?0mU@YLs76()i%1nAA=atHC_4URa1KG=muiKz41@ z6`)yXt#uW7b+zgmV1>%nqLdPiR0RiP5*!7(tVTDK{9c!QXy?~1=)erQ|t=r$~MzwMuvvZbd|*ij9Nb2^vg~ey(}{ZiwZ~Re*j}KYA~}Y$9yd! z$ih%%HsL^N5$xKAGinw<#&|I2IWO^Y;*sKyX4fVTL0Qco#q&A~qtefRe@%{~uP3~Uqa}no zBOt5jMQOBH>ZOob5};C^*#;NmVWpN^VgUvnSS@KXA8JznhuAd(o=CjI|F&bcD z5R5ktAho4`AQ-NAK z7LN%n#mc)V(z0P8Qz+JRK(9BAL_#pYYRu?*^Q1WY3-{w&Q)nx-%EPrszRQ1{e;D60 ztJSRqPL1qX8>$`;s#B?Dlj?ztH_Ysv>g`>4RGyw)?wwv-o?onZ7(S5Z%q1Yi3r13d zpHhb~2NRA#f1mAnOcO{!IFEf?U%QbYUn8y^ZEaDcIpm#qQTsB|Va+1vcw3NKLRGqp zH?{+&7dt*7Wi37oWRA$!f?HBDv9A(tge`5;f#G3*7T|$mdwCs*&+2L6S<3KKi4pH; z52=0fl4y#O^Ez-rQc9tkpC+|@V8&}MV-|5&8UZYy$QIo2o!so>Gu4P2P4DOBdlkdZ5#AK_ZHcB+^igL!q1k4COa+D{f<8j zIfwaN+ueVi=W@TPl5Jr@?s73ch5chD<)-X#`drOA?LA2@J}<7vA7^z&hLxs2$-Crz zb;a+qmrrL+r|7*5bbRyT9YL@4!p?nv2h=yYWLkNt9_lj7eG0rxO+&-bj|+WhK_(L@ zNipdCirsFKYx3C6y`^>2)`dLo?(QWe&G2Y{tUJ2eKXj}Gws(X_MwWa={y^&`U&+MR zlPX8uM>y?>Qi7R4EkCX<|6671EP-PSCH8-J|3HJ;7;af~&*>C5Q;!LBXXt(`zYEAL7> z*T{y)mr&O5E6`i?Hv5vj;4y=H2YTqm_S)~fx-%m~Qpa8KWZLOQhXwBA{+Yhlb_W3z z&pb+$hBa6#?p+0~eQ(=*)Mn+)=&*p=A+R9Oq;PZ)YE(|%_aPT>*_m1Y0+ltFG1n>> z_VfxEx?|Gl;BQ&}p`xOmr~62zH8AIFtx}O8-Yj-{Zs=8m!7xY)nBmv z01AvY@0ADpZ8NV6nU{D8xsuIa2RvO^^VDB3ZLT@VuiOiyHhmVNo@lCX*Idz=%*_1luqlf3$^Jp6c`B>c&xk1R96OwY?ApO5TKRNZ`9|p;)BPmf>86H* zm$$bcE|*0NGuJGczuyTomqaVCXSZ?&P}38u5qTthxVp`SHW~R#pX{nn>x4xCt$v;Y zc@D)6)jZ|BydYi6=@aL4+J%NYefsCO7B6!$pD@RAkqdF`0G%Z2sbV^Vn_BP9={mMAJ5OHLjF=f*eiZJJuNhj>T*`I0 ze7s;^SRvpepR>~P@l0ny&&aN7=SigK`CUvkIJ9^uR92pGeVM;}jjg)O0=@W&k7WRi zG4o#>8^KbFK~x;*-48|a-*4T814&!M?wzaeLS~?J{DQ=-s^RR(Rxpoz(1m6Cuo4M_ zB@9=Q{qasxCN_1)u=(M>h~K-0KSX40hl~I~E$_&R?q)8-Ey<BiWv^%fFHom4-5f`FGXda-jIQ<@l(&1{dUL-TE^!5D*3iZG&9%q7aXS>fAs&p zZBJF#w`)t_+S1ckmom@#L1U=^WhzqbkG1*;7c^~r7ybj%Ib#|A+IW*!NN)1Y9d+T^ zj4fMn7*=Cad_uxa!>S-Scz@ANE!m>a6F>6v(h4UJ&$`gC-|%xwOUoSI zFs0g}a_q>*?Ce!!Zx{}Z7aHvsJQwO`wtOh-kBb23D(bIjwUZkNWxS((-NN5@eowMr zXq1`~c8zVG`S@P!zB_hd`xgzIUrTl)YNU>2u*F6-Bd$&I{sjOib7-n*tu50Vw&OYI zcF!zk!C2rH@)RVuwhVO2@Yy8b88fq%W5}M3o=av;XYX!~bm3v&Y$(GJo}d3^@3$b> z=VNqs+yYuS2jSBa}VJjuYxa}8JAdhLfERLJl__A)O+*9qsrnV#J!myDN% z%zOQ*u5JK`qJ2UnTI2f8v&rR4w(eQmg4>t(Lh!{dGz#HGI&1u>t>o7mSHH}cy!sks zKlsfX4z`IN-C4|TD9$|Y$rsVBWh=|P6bigjj~V2UGXv>X$^4GG6)jPfbY@q0_T9fWih)do(GRyOx@PPfXWTqiOhcWi){d5C%+v=< zexu8F7?4@5uUhVkpL@YIAt=R*FGr8&8g1`tY_WlY!(9NI@bFM>!aqGdpT%2?a&{L; zegsm<7>gzsqUN->B$?GKZ!oW0vO6$Sf_MB=GTL2=iL?FN+kU?@C9U_RiB96ltn$gU z*oo71TNk(OzU936&VYO})#<{F_iut_3>1HZL-IG5%7(^!9Ls^RXFhSx=8QZ;)^QGj z^;V*5Ee>P#E#?n=rwh53S(!$NYlmi~d+pL%j8dNwu)lX)Kmw}_&{ zlqWT1S`|le;wg#m|FO)R-w2oQ3)}O%e&a|p(5Of021a;r@pvViL^T|IxxFpAT=t1R zalX$ZPs_PQ(ng3j@`d9(op#_Z!y2QcMhY)#_xEnwT`gzIa2^x=WRp+6E7A^lHFquN z_V(RqG0mce0IhiPf(*XbS!+J#EI{UcNesx{HGsx2jp+_11WiqKdHGwHx0uAE&BMdz z{_U$b69J+LXEvFn5ms5S6rS-3q^9(@uBYC2LqqbNUQs$zGxJ-^mj&@_SG(e|PkcRk z%nKeQ{k{uVj>km55O+OqpwXeUL{CcVOmFM;CB1uR{#nH7(QT;jb{_VdBd*@F{WdLa z%l9@V$_pr;Zk0Jcr^`PvKDKv8fTzjhb$>9nB5cr>ndGkUY<}kE>Be*NTVEpJ;o&iJ zd&=WwC2lI^{k|o$G^YRfdt%>wqvk>*ZE3^DUjY%!nRP8%=Clu9VST$=nX}_vNv73J zrkx|kdyyskt@0huvBN(-P)?RJ^V7)g z`26*rRag>UQq}J0T@?#NiOx3)#YMSqw>>y$+w*H3`?Wk|M;7|gej(jq!J%m8BI9xq z6S?W~8V_6k;~8S`dZEtDk(NlOfSS7Cn~UwR)ap{(mq$yXwDR$^3ysAci!|jQ{kMOFHkja5K&I$bQd-R(|p%0Fcrc`NLv% zEaEux+9}*krH-3tacNjX8gf1=f3~|E@~`w{vwU}ZTbEWP@sUpcZlbJZqqaQVMZdfi zJ9T9zrGMl|BJY|ScSzwlGO|3379DAKXJsdSKZge^SDbCbE0-ZZ5~o(@*fdY}=YIydB^h3BI*VfOkniF^ z!J>$!Nh+%@9u-)_oc`mL^4I;l#J%&U=Uo)GBNZk`dnG|1ShY{d%MKs#h4V8Es! zAiefYdT<6tY?$S7a7=V8y4}^akqN)@{0Ijc>87uqXTym5XaGE!cH!b%;JS+|o6EnphB^$$K}WjY9jBuY_@*uQ;QQ+?lQ<=EpJ z%d`A|>$985po{DP|1?`;i6TaH7gc^PT7pSP=o@$(>^;!^9`+(i211R101~gaY2pMX zi3w1QAyLNl#Ys}W1NCx45%y|W2=Ocw5@q}X13-9hmI2);4PZz#G6g4~((u?GKFr5CRUeh*)mjx;jfMFz~<}p2yFV3E(n- zV5m7f98@%gxr3f#J!0Zrw62KXY1?bWcbAoeOV7(OvExhGTe_ejKc$YZ&4SBKqb;g(&8|piOTUjP0 z{t`dUI*pcel&7tn#g`3NhgF;qqzc?grZhf|f}uk0qMq}s1UeBJ4r7+8GK2SOFgBDd z)~5pmNRWg?neYUkry2A-cJpPf5Hah)IgwFjB0cUZ^4@QB6yMn3ZU{W!4CPaA!Qun7km&GQ z0BXua2!s)`5Nd>S=~M&8fCJJ)OD3i(9h{5=o-y`VqeX#G1>hDWX(;?|HxJN&f>qHN zz1ziT2*X0UHu{m$C^t-!_FIwhP+2xTVKP<;7Wt5zb4Xs7Xzc5PVhlZnTMAqK${M$VZxfH49nZ)R%)i)9C5_z~n|l)`AdwcpP}~oFn%~hy5ds-)J%{95IzszTyfQ_BXtMoUKGztBjopkuq#UeZt-yxeR5C?>X%hXp`0xi@+` zv0qL#FVpNy>AObzM9}Wr1(4sD4y(j~s21AN(=SSkJWD}mujag6ZE~x64VGN1POCBm z=YQFM*79OK+R9lGoWPzah$S$`l5jfPXgNq?D>C0vxDZQQMaVWI@O#1LJPk`-&ieq> zbbNsJ(B!&t`sI1bvZU$MWio+i^p4!vJh z-u>bo|J+UXVFN#c5rrNn@g9Uo<(vlq4G=m&m1j&C$MALRHc;&P)V`H6=&CWr=|spy z(z_n?qol_#T3t1m55Pd#hG)U6)$LTPNqW%A!W{u{AU(l7Srq_99*VIQWF~ZV{OopJ z>}6g0_Ta~sNUnpiE04hQ<=`R8UD>^j+iUHcF%C+kDI6UNI;U*?h=%-T6W4UK+Tnw_|O_F9)Z zlu(CCx}F4w|IX1KlZVO5#f1Rlv-pREfB{`KVR`iF>*owCVR#A*+Yoh5aR!jXIrVTl z@eWSsHf5NkGkz-Q1EwTGXMh)|Az3p%iL?BT3@(+#LTwOoR{G&kcC_gzWK?@Dd%08O zY-Ui<#F{$9UZp%&0>G?0QTQl4e3db(Y)O12Fd(mK6fHV+xn0aB0!TDb5AxQug zP0dX4_Tz&a)*lYT`CR>>^C=u*(CyDj!yKt+5(323*{>*=61 zab?WanZ4RxHsr@L=c#jeC0W1#JaKid*=vh5d1#A&z(Jj9zOfdHm12Xjfmxmja4O~U z8Zl`R4`H5s<3w~0;C!`x(2LCC!NGU0buTX9A3YHQu|Fm zB_ev2gL=VJu`wfYWi&|>V`1+4m>eScE%73rj(q|>7P#8XwA_<~iXXNZyavezbn9FV zmWg&lAAs+v(7aR$r}OG!R0V<3)N$}xk&4(MiDoapY6`RR;e!AWfI#5HW)|Sls9<}^ zct88Z%Lk~#8Q~-(03iTCP}NB5FpMZPDmVZSLyM~wf=5-dOojA49M=#Z>;AU&YQXW0 ztc1C2mUBHoV%=u-E?V?A0gXFFzkexbZwzq0Bxj9;_2A?>)x**|*U;GHThV zV^`rZYo?VOf9X`pJWLx5Nu!g*LL^2B1Or6*@Ip@1kWy%Dmu6Tv7CIP#1q}wQ0g1{! ztm3!cG1N(LaY^wgDGbGL?dGU8h)op~fIvdvP&o2%)C?b#2Zo}0rc{QjtUD(gtxBWc zkVvswpcbwqVQt*4zZYgt~U$m+5VR6rV0@w-*PsUqY-hliU@b9LtpUfvh&4D%K)jsh={n*hcO^CqU}OZefEiMVZlSn|GzKml z8x=MogbeBGf+A(mQ0_ARbz~L@L?sHC0suw?5{{u!Awx}WQM3nYd%@aYi_IrvF4Kb- zOOn-@6-ESsz#z~tB3pa_AQ}>?ekiL)2m{MVz0gF~=m3B!Ix7IxtLRGep0j>|ER8bB z6iv1GiNb&bc(5rLYKRam4EQ7=4s;aQs!40&0Laey67))2aTp2^tDxr%Dsj1{e~_Sx zQ5tLt$Q^2+pgo0+IXaR7QO|c%HnuLG1r52s9{zc{^{hF^(=Xt3Y?JqOvshER-<7h^ z}BLQyM!Kq_5iKghc zs%Hf3-|e!lXz1sgw<><)^H^xSQE?t_Q~uIpNY$Dvk}G_|U#%{!fZ?$ZF0%OUh51Hy zFHTHpdr+gr%K;~K@mr3s`o}RUB^{EqNhWzAn@kuv-%M=J#y6)fe>I|Ne8JUTrG-pS zH#@Oq@`K^)trae2cNbqN&f)So51i*K*7&H?9u>m^fwqwarI%f}61JB1=Rswt4LtQ4 zS}?P*NDQ?r7=lDMgr8vWA{!W0QEFPUV-Lj^68c82E(uluFsMpa!v<_SiDK8?lvTZjzpT%YArzbRIa1xAEF-u$hZg*)m#)^Y-|6 z0FcOu1rmaZcgRrDW09hyhNYl01xmrMIg|28aAZ1k9@vu5lLJNJ5HrKc`2xTd#tEn* z@xoOxLC=C!B#Z2^K(cT0UG|ta^3+23V9=gbY3=eCj~g^B*jO1|xIj{9iH&l+{5Vr^ zBW1qcJR1Pb5g=hpFPy}WF3FRi0{D<1DpMe}=q&|2Sp!$^;-WN|`E&2?}HgXiQv499jiHt9~qyvg%py%CA$lobws8AfTh3${tTB ztD}Jg2u+NOj+w4wTT4&uI-pC2&^d#u#lz(8QM*oee^UaIXt2)nUgkFMc4F62iT`rQ zhK~fh3KBraK_u-^FGhU{ReQ%GM52jr6c|%h?fs)CcB~_dY2&Mtez>anaMQbr%@?MW zVZMsM2G_D+eoDq+vch_@5`ZS2fu#CwEPQzBcZ^HiRFe(R65dlt;smQB}#pS>e zp)g2jSharKxdPsMWX4oMW9t(2dejps*Y!rvmbG{*e|SHHN$y()O=+jnGYS7-zi&24 z@`s%zvIHGh-zwU<3gE@)Bsj?x5j5qhDXXbPatxEN!+53yXV)G+@w40HBv(qzg%o1V zp8}SEoR+KUBqms#n}(~Y``lIi5j)nSXqmbuo%{U#y}g%{T$dvO@%o=DE9+L`H!r)D zE&?sqmDKrq4-fAhD*67Fd=G>PFZLr$Da`k9IemZmr5x2J@X!jkbv{CQeOhGv_<4{y zSqTe^s-fs15@njm-G9QG!H44}Fa?3;;9zm4bG`42Vq@litRPraE-!Psn z<9TFe&au5&f!G<0>*wk+%(Ld4z{^w91gUcY*613G65=g+2#wm>bAB)a6%J$JU39Kw zs{%3NX!LN-bD3MC^G+lygQbBy40Bpx@6HfBqS(Z7d>qhS$%GK0UY5+!ffam{E?eiH z6uM6`kER#p-xWmEbD{O3*Y|ob)}o*&#FO3riHo>;`{uzPAE);qZCyY7Tj!^?_B!+j z_i%J`8=*dyKi?OZ=N+USU3ceFyu67y*JI8{glaKC39;})@Pc7-($*5s*b55ysR0ZC z32^2?m}3Dwo*6l_4P5cAWwfHuQS?#h*2#;!)GLu#xIaE zi;a%v)dLwno5?w8sCcBKV_*=@N?1li=g1_ZD`mrIgOZ}n^CyrDLqW($-$&sv;dQ|A zSfMB^6pT4`+_(eu)VT-kzCawoBdBVPX;=gl)4I!ArkJeME2l4cX@c>7g=&J-wx7=SLCIOe zs)e+m>r70$sUX(CHP*?dP(?$j=dtYANP-LiWR=-x#p!BDITlcihT=y7{^L4W9cDYs z=&Uj|Lr?K{%Lz)UijwO2F;K=Js1$yf1h4@XUy+ff#8EL8isVw*rL-x>G0(s0@6z^98v z8G(!!SaqfoXJVs5G7S#jU;Q2pNa|hWZ&OO;JBbuH*lTyX?aSrYB-FDx_Ar_zweIlkhvjNv&SIyKx-&dyhR1bFRG9G3;b~?Oruk z;QJlkxSi*_T?<3n?>CTSUj}i?lO3LziS%ox9bAsI*P6Hq@!8e8t zhiw>`xV#IRBNWVOeF9~)HajUG#Kh&AO;m_3_S`sAos8fR;@*6r@Xh$*8#+>l1}lmW za}wcNd`x;j4{A(HO`4CBj?rz%yn!J;3go3o6I74ND1~}v{Zh^M6mk3WuZ2)Z6LdUe zEPg3C<`j>HpHbt*J+fCU(a%a5WdQ&!R>je+s9;9#syIrU!$?_4C-zOaY97}l5I12v zMQdqBW^Z=NXhN7q^a-YhL=ZlC%zxtI->BLF3wSRBARlz}o=1tm;`ratPQl=;DuvV5 zeAQVJYErux%w>>RiZ}*hnY#vyBxQjTTYIE)eK6U3@wvCh8=S61#Xb-fpz%_AFjXx2 z(W%JtkUPCv{5XSL2DYF)fM~-H@)wYFW;J(ZI^ z!hoauQ+FwY0}~&$?&2P`gs`+*xz3nwK_2nVfT*(p4SEFy*F(f>M%duDS*B;)bdSN& z^AD&{m?#(?vcZ^4=WB5Ugs=r39=)UN=MaRntZU6Di^eF-ym}uXLAWj1dw4o6=93Ir z1$ER~GlC{F@W$2GQ_7Y5db=q6+JBm$YdK3TL@xD-J~xP`?6XMH;D<;b-y55NJVfMQ z%8zAIfIHZt&rJ{Itf{O5FIGEYs(Kh~10g6cR$6Q1Cd1BGMyfLjAUPJkQmo;b#Wc-%f+_ietJE<^;jgHK=IalpVCGOX)EUu>$N$uDHy|3Dq z->mC58RRYNF2CQ>>Uya{b86nkAuBII-HCI)ZNxq7{HFMbHq)1G-&KIeJL|Q%lT7xy zVRB^}1t1-=rjfXc4E!dVIKm$32Vgy7mQX#epB0MzIv$loQx@^CTopmPIXP!5=wECh z(YfPHruYFGNozaj<2;j(T>!wQVFhsoWf~B1RaPQ6E=#xsT|^o>KXe{Ij#oQ}W66;1 z5yE5;u~1$B3a}!IpwOQB>gd=Q-)eEyXe@LnfFS_{OMoGWhe&jEG7MV?sG{-y*{fc= zW%{u`r3-B<%K3K${e{86_`aB@^1tE_GIz9*}+_^n`kQ?z;R?Oa={tp|UV^CKQn*GpdK%GD(S56&@WXt%{TY zXffa*6m2OrfP$M8)ijdie+47xkT`Pr*fu8Ev`{LEyS@?zD8Y{bP+d5gpiu|u zJ^S|D!Hxn`5E*8`A)pF!FwkwuQY6+ij@H#uO=SLwO29)YI!fb(ieII1VgsYN6w8{M ztENXMD^Fv$nPO>nA2ARC+gnG%H~d?~BeH>Vw`d$)n1>vsD_^%xH;&JZ#;!at?k8g8 zpZLyi4t})Mr8Xiv>;&S`v$(qIeZz2)oztdQA7~e=l0fj{22(Y7wa{&VE)xF9>QZTA z7sduuS*L`{x`JlSdy*$)y7d5n$cjNS5_U44G7qrHqcmb4VUi+ImpK4TtIb>&U$4CYufR*ENAVb;JY~nSwS)Y2D*ZYAQ%9`M4GcK zl4r0$CJYZ1421)lGU&!sBV7Oxi~^vN&_WDE94rqHKtO=5C=fC#90vkbwr}r-23hOf+GyAt@jMQF(5r1jL!y) zS!keYd0}f{urW3#cL%f^FlOntwgnKnH?3cbge15%)?^9h zGDKg3jJm9mO$rGF2*Y` zV{PrH1xwq4=*hL`mV%en6hdDbxs1-YE`RrJve>?l$k#gEFG+MtABvq!r6xM6(g~jBfxT-meUE{hkDk6iu%e{NSguP;xZ| zLmZj~pKgw}9iJJrxFOA8O`ExFih^GK*yUEXDcTOM6SUlU2IQF=YU=5>Nq8hq`xI_SMDwl^b@8{abnN-I?p? zEz#oEFFH| zPZIo6SJ`x&mlml-;HR^jyw6?r!T!ND`LA35uU$|W7D|9}6U7#MO2GEP+f<|0c&-7Z zbssgI2UNTjnY?h`n8gBN2jAeXen;P&BlxDHP)Qj3h!9N?{QP@ztcRhk)cG%@#70Gs z$v3OyPN`-*eBR|?|K^ao!S4b#RiIrUo|Yw3+!zF~g0UI%w*oQ6ktQq^%y$`#N zmC^vvtGN~;f2B&!!f|2mU{JzpkjRC@jBYd6uHK-jGu23{su~d0q@@uI(F=h=xP~G{ z7wlhm^{UCxfWtM#0e;ocr0SfADuP$XfXG;?RwZi=iCvzK22|?})R+}pkPXuR=?$Fq zE9Wf9s9i%W!0g7%YFS(XWdf

SDl(Rc8tDs>v$QQIF{XW4wzKVM}T#0w(7mERYyK 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

0q+WJ+bXmIcp%t02+(C06*mkxZ|xBo|6p&^ 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˺V*XJvOnXD54;0VA{hS?Sd3bT`;_90|GK(xiQ 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 z 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ð{4 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 z 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≦jvYh+xR5T&!ENK9VLcS>m!%5s&*5a~*Cn(HNj$ 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Πc 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�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ðQLIngPk6547ghWkbtc%P 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

q8yqAwx!>&eC~iV~CAcoU%rGR>+dV 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%0AK?{Le>EQi1+Snn02M+S83iJw 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
p=Eq!pyMBI| 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

&Pq5Lfr{{CP- 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%0D;80)?=u%ElRi% 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 ? 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�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 HUVi#Bm49WAlrc-x{)Vq2nr5d)x?vv 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�FhXbXZT2Z(-{+AUohnYWJlW)@PKs!Q;4 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�Q1}QtmEzhb=Zka*$f#cN6Ak<(1*Mn=-1KN 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 z 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

w5VX*dFO2vaje28eC*0ZUhFjgnPP<)DYX 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

VFpW#ZmtCSn^8S6w3rhKYO?aF6rOj} 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

HiSn*TAL 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

}o6Ec^K5dJ0TJr$DsbNLqTg%!^K#|Gi5)(vWH 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

&Jmb?Lcy9`^5 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 space characters (utf-8 0x20). In cases where the layout would + # require a fractional tab character, the behavior of the fractional + # indentation is governed by + use_tabchars = False + + # If is True, then the value of this variable indicates how + # fractional indentions are handled during whitespace replacement. If set to + # 'use-space', fractional indentation is left as spaces (utf-8 0x20). If set + # to `round-up` fractional indentation is replaced with a single tab character + # (utf-8 0x09) effectively shifting the column to the next tabstop + fractional_tab_policy = 'use-space' + + # If an argument group contains more than this many sub-groups (parg or kwarg + # groups) then force it to a vertical layout. + max_subgroups_hwrap = 3 + + # If a positional argument group contains more than this many arguments, then + # force it to a vertical layout. + max_pargs_hwrap = 6 + + # If a cmdline positional group consumes more than this many lines without + # nesting, then invalidate the layout (and nest) + max_rows_cmdline = 2 + + # If true, separate flow control names from their parentheses with a space + separate_ctrl_name_with_space = False + + # If true, separate function names from parentheses with a space + separate_fn_name_with_space = False + + # If a statement is wrapped to more than one line, than dangle the closing + # parenthesis on its own line. + dangle_parens = False + + # If the trailing parenthesis must be 'dangled' on its on line, then align it + # to this reference: `prefix`: the start of the statement, `prefix-indent`: + # the start of the statement, plus one indentation level, `child`: align to + # the column of the arguments + dangle_align = 'prefix' + + # If the statement spelling length (including space and parenthesis) is + # smaller than this amount, then force reject nested layouts. + min_prefix_chars = 4 + + # If the statement spelling length (including space and parenthesis) is larger + # than the tab width by more than this amount, then force reject un-nested + # layouts. + max_prefix_chars = 10 + + # If a candidate layout is wrapped horizontally but it exceeds this many + # lines, then reject the layout. + max_lines_hwrap = 2 + + # What style line endings to use in the output. + line_ending = 'unix' + + # Format command names consistently as 'lower' or 'upper' case + command_case = 'canonical' + + # Format keywords consistently as 'lower' or 'upper' case + keyword_case = 'unchanged' + + # A list of command names which should always be wrapped + always_wrap = [] + + # If true, the argument lists which are known to be sortable will be sorted + # lexicographicall + enable_sort = True + + # If true, the parsers may infer whether or not an argument list is sortable + # (without annotation). + autosort = False + + # By default, if cmake-format cannot successfully fit everything into the + # desired linewidth it will apply the last, most agressive attempt that it + # made. If this flag is True, however, cmake-format will print error, exit + # with non-zero status code, and write-out nothing + require_valid_layout = False + + # A dictionary mapping layout nodes to a list of wrap decisions. See the + # documentation for more information. + layout_passes = {} + +# ------------------------------------------------ +# Options affecting comment reflow and formatting. +# ------------------------------------------------ +with section("markup"): + + # What character to use for bulleted lists + bullet_char = '*' + + # What character to use as punctuation after numerals in an enumerated list + enum_char = '.' + + # If comment markup is enabled, don't reflow the first comment block in each + # listfile. Use this to preserve formatting of your copyright/license + # statements. + first_comment_is_literal = True + + # If comment markup is enabled, don't reflow any comment block which matches + # this (regex) pattern. Default is `None` (disabled). + literal_comment_pattern = None + + # Regular expression to match preformat fences in comments default= + # ``r'^\s*([`~]{3}[`~]*)(.*)$'`` + fence_pattern = '^\\s*([`~]{3}[`~]*)(.*)$' + + # Regular expression to match rulers in comments default= + # ``r'^\s*[^\w\s]{3}.*[^\w\s]{3}$'`` + ruler_pattern = '^\\s*[^\\w\\s]{3}.*[^\\w\\s]{3}$' + + # If a comment line matches starts with this pattern then it is explicitly a + # trailing comment for the preceeding argument. Default is '#<' + explicit_trailing_pattern = '#<' + + # If a comment line starts with at least this many consecutive hash + # characters, then don't lstrip() them off. This allows for lazy hash rulers + # where the first hash char is not separated by space + hashruler_min_length = 10 + + # If true, then insert a space between the first hash char and remaining hash + # chars in a hash ruler, and normalize its length to fill the column + canonicalize_hashrulers = True + + # enable comment markup parsing and reflow + enable_markup = True + +# ---------------------------- +# Options affecting the linter +# ---------------------------- +with section("lint"): + + # a list of lint codes to disable + disabled_codes = [] + + # regular expression pattern describing valid function names + function_pattern = '[0-9a-z_]+' + + # regular expression pattern describing valid macro names + macro_pattern = '[0-9A-Z_]+' + + # regular expression pattern describing valid names for variables with global + # (cache) scope + global_var_pattern = '[A-Z][0-9A-Z_]+' + + # regular expression pattern describing valid names for variables with global + # scope (but internal semantic) + internal_var_pattern = '_[A-Z][0-9A-Z_]+' + + # regular expression pattern describing valid names for variables with local + # scope + local_var_pattern = '[a-z][a-z0-9_]+' + + # regular expression pattern describing valid names for privatedirectory + # variables + private_var_pattern = '_[0-9a-z_]+' + + # regular expression pattern describing valid names for public directory + # variables + public_var_pattern = '[A-Z][0-9A-Z_]+' + + # regular expression pattern describing valid names for function/macro + # arguments and loop variables. + argument_var_pattern = '[a-z][a-z0-9_]+' + + # regular expression pattern describing valid names for keywords used in + # functions or macros + keyword_pattern = '[A-Z][0-9A-Z_]+' + + # In the heuristic for C0201, how many conditionals to match within a loop in + # before considering the loop a parser. + max_conditionals_custom_parser = 2 + + # Require at least this many newlines between statements + min_statement_spacing = 1 + + # Require no more than this many newlines between statements + max_statement_spacing = 2 + max_returns = 6 + max_branches = 12 + max_arguments = 5 + max_localvars = 15 + max_statements = 50 + +# ------------------------------- +# Options affecting file encoding +# ------------------------------- +with section("encode"): + + # If true, emit the unicode byte-order mark (BOM) at the start of the file + emit_byteorder_mark = False + + # Specify the encoding of the input file. Defaults to utf-8 + input_encoding = 'utf-8' + + # Specify the encoding of the output file. Defaults to utf-8. Note that cmake + # only claims to support utf-8 so be careful when using anything else + output_encoding = 'utf-8' + +# ------------------------------------- +# Miscellaneous configurations options. +# ------------------------------------- +with section("misc"): + + # A dictionary containing any per-command configuration overrides. Currently + # only `command_case` is supported. + per_command = {} diff --git a/third-party/webp/libwebp/.pylintrc b/third-party/webp/libwebp/.pylintrc new file mode 100644 index 0000000000..4658b844b8 --- /dev/null +++ b/third-party/webp/libwebp/.pylintrc @@ -0,0 +1,441 @@ +# This Pylint rcfile contains a best-effort configuration to uphold the +# best-practices and style described in the Google Python style guide: +# https://google.github.io/styleguide/pyguide.html +# +# Its canonical open-source location is: +# https://google.github.io/styleguide/pylintrc + +[MASTER] + +# Files or directories to be skipped. They should be base names, not paths. +ignore=third_party + +# Files or directories matching the regex patterns are skipped. The regex +# matches against base names, not paths. +ignore-patterns= + +# Pickle collected data for later comparisons. +persistent=no + +# List of plugins (as comma separated values of python modules names) to load, +# usually to register additional checkers. +load-plugins= + +# Use multiple processes to speed up Pylint. +jobs=4 + +# Allow loading of arbitrary C extensions. Extensions are imported into the +# active Python interpreter and may run arbitrary code. +unsafe-load-any-extension=no + + +[MESSAGES CONTROL] + +# Only show warnings with the listed confidence levels. Leave empty to show +# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED +confidence= + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time (only on the command line, not in the configuration file where +# it should appear only once). See also the "--disable" option for examples. +#enable= + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once).You can also use "--disable=all" to +# disable everything first and then reenable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use"--disable=all --enable=classes +# --disable=W" +disable=abstract-method, + apply-builtin, + arguments-differ, + attribute-defined-outside-init, + backtick, + bad-option-value, + basestring-builtin, + buffer-builtin, + c-extension-no-member, + consider-using-enumerate, + cmp-builtin, + cmp-method, + coerce-builtin, + coerce-method, + delslice-method, + div-method, + duplicate-code, + eq-without-hash, + execfile-builtin, + file-builtin, + filter-builtin-not-iterating, + fixme, + getslice-method, + global-statement, + hex-method, + idiv-method, + implicit-str-concat-in-sequence, + import-error, + import-self, + import-star-module-level, + inconsistent-return-statements, + input-builtin, + intern-builtin, + invalid-str-codec, + locally-disabled, + long-builtin, + long-suffix, + map-builtin-not-iterating, + misplaced-comparison-constant, + missing-function-docstring, + metaclass-assignment, + next-method-called, + next-method-defined, + no-absolute-import, + no-else-break, + no-else-continue, + no-else-raise, + no-else-return, + no-init, # added + no-member, + no-name-in-module, + no-self-use, + nonzero-method, + oct-method, + old-division, + old-ne-operator, + old-octal-literal, + old-raise-syntax, + parameter-unpacking, + print-statement, + raising-string, + range-builtin-not-iterating, + raw_input-builtin, + rdiv-method, + reduce-builtin, + relative-import, + reload-builtin, + round-builtin, + setslice-method, + signature-differs, + standarderror-builtin, + suppressed-message, + sys-max-int, + too-few-public-methods, + too-many-ancestors, + too-many-arguments, + too-many-boolean-expressions, + too-many-branches, + too-many-instance-attributes, + too-many-locals, + too-many-nested-blocks, + too-many-public-methods, + too-many-return-statements, + too-many-statements, + trailing-newlines, + unichr-builtin, + unicode-builtin, + unnecessary-pass, + unpacking-in-except, + useless-else-on-loop, + useless-object-inheritance, + useless-suppression, + using-cmp-argument, + wrong-import-order, + xrange-builtin, + zip-builtin-not-iterating, + + +[REPORTS] + +# Set the output format. Available formats are text, parseable, colorized, msvs +# (visual studio) and html. You can also give a reporter class, eg +# mypackage.mymodule.MyReporterClass. +output-format=text + +# Put messages in a separate file for each module / package specified on the +# command line instead of printing them on stdout. Reports (if any) will be +# written in a file name "pylint_global.[txt|html]". This option is deprecated +# and it will be removed in Pylint 2.0. +files-output=no + +# Tells whether to display a full report or only the messages +reports=no + +# Python expression which should return a note less than 10 (10 is the highest +# note). You have access to the variables errors warning, statement which +# respectively contain the number of errors / warnings messages and the total +# number of statements analyzed. This is used by the global evaluation report +# (RP0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + +# Template used to display messages. This is a python new-style format string +# used to format the message information. See doc for all details +#msg-template= + + +[BASIC] + +# Good variable names which should always be accepted, separated by a comma +good-names=main,_,PRESUBMIT + +# Bad variable names which should always be refused, separated by a comma +bad-names= + +# Colon-delimited sets of names that determine each other's naming style when +# the name regexes allow several styles. +name-group= + +# Include a hint for the correct naming format with invalid-name +include-naming-hint=no + +# List of decorators that produce properties, such as abc.abstractproperty. Add +# to this list to register other decorators that produce valid properties. +property-classes=abc.abstractproperty,cached_property.cached_property,cached_property.threaded_cached_property,cached_property.cached_property_with_ttl,cached_property.threaded_cached_property_with_ttl + +# Regular expression matching correct function names +function-rgx=^(?:(?PsetUp|tearDown|setUpModule|tearDownModule)|(?P_?[A-Z][a-zA-Z0-9]*)|(?P_?[a-z][a-z0-9_]*))$ + +# Regular expression matching correct variable names +variable-rgx=^[a-z][a-z0-9_]*$ + +# Regular expression matching correct constant names +const-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$ + +# Regular expression matching correct attribute names +attr-rgx=^_{0,2}[a-z][a-z0-9_]*$ + +# Regular expression matching correct argument names +argument-rgx=^[a-z][a-z0-9_]*$ + +# Regular expression matching correct class attribute names +class-attribute-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$ + +# Regular expression matching correct inline iteration names +inlinevar-rgx=^[a-z][a-z0-9_]*$ + +# Regular expression matching correct class names +class-rgx=^_?[A-Z][a-zA-Z0-9]*$ + +# Regular expression matching correct module names +module-rgx=^(_?[a-z][a-z0-9_]*|__init__)$ + +# Regular expression matching correct method names +method-rgx=(?x)^(?:(?P_[a-z0-9_]+__|runTest|setUp|tearDown|setUpTestCase|tearDownTestCase|setupSelf|tearDownClass|setUpClass|(test|assert)_*[A-Z0-9][a-zA-Z0-9_]*|next)|(?P_{0,2}[A-Z][a-zA-Z0-9_]*)|(?P_{0,2}[a-z][a-z0-9_]*))$ + +# Regular expression which should only match function or class names that do +# not require a docstring. +no-docstring-rgx=(__.*__|main|test.*|.*test|.*Test)$ + +# Minimum line length for functions/classes that require docstrings, shorter +# ones are exempt. +docstring-min-length=10 + + +[TYPECHECK] + +# List of decorators that produce context managers, such as +# contextlib.contextmanager. Add to this list to register other decorators that +# produce valid context managers. +contextmanager-decorators=contextlib.contextmanager,contextlib2.contextmanager + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# List of module names for which member attributes should not be checked +# (useful for modules/projects where namespaces are manipulated during runtime +# and thus existing member attributes cannot be deduced by static analysis. It +# supports qualified module names, as well as Unix pattern matching. +ignored-modules= + +# List of class names for which member attributes should not be checked (useful +# for classes with dynamically set attributes). This supports the use of +# qualified names. +ignored-classes=optparse.Values,thread._local,_thread._local + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E1101 when accessed. Python regular +# expressions are accepted. +generated-members= + + +[FORMAT] + +# Maximum number of characters on a single line. +max-line-length=80 + +# TODO(https://github.com/PyCQA/pylint/issues/3352): Direct pylint to exempt +# lines made too long by directives to pytype. + +# Regexp for a line that is allowed to be longer than the limit. +ignore-long-lines=(?x)( + ^\s*(\#\ )??$| + ^\s*(from\s+\S+\s+)?import\s+.+$) + +# Allow the body of an if to be on the same line as the test if there is no +# else. +single-line-if-stmt=yes + +# List of optional constructs for which whitespace checking is disabled. `dict- +# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}. +# `trailing-comma` allows a space between comma and closing bracket: (a, ). +# `empty-line` allows space-only lines. +no-space-check= + +# Maximum number of lines in a module +max-module-lines=99999 + +# String used as indentation unit. The internal Google style guide mandates 2 +# spaces. Google's externaly-published style guide says 4, consistent with +# PEP 8. Here, we use 2 spaces, for conformity with many open-sourced Google +# projects (like TensorFlow). +indent-string=' ' + +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=4 + +# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. +expected-line-ending-format= + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=TODO + + +[STRING] + +# This flag controls whether inconsistent-quotes generates a warning when the +# character used as a quote delimiter is used inconsistently within a module. +check-quote-consistency=yes + + +[VARIABLES] + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# A regular expression matching the name of dummy variables (i.e. expectedly +# not used). +dummy-variables-rgx=^\*{0,2}(_$|unused_|dummy_) + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid to define new builtins when possible. +additional-builtins= + +# List of strings which can identify a callback function by name. A callback +# name must start or end with one of those strings. +callbacks=cb_,_cb + +# List of qualified module names which can have objects that can redefine +# builtins. +redefining-builtins-modules=six,six.moves,past.builtins,future.builtins,functools + + +[LOGGING] + +# Logging modules to check that the string format arguments are in logging +# function parameter format +logging-modules=logging,absl.logging,tensorflow.io.logging + + +[SIMILARITIES] + +# Minimum lines number of a similarity. +min-similarity-lines=4 + +# Ignore comments when computing similarities. +ignore-comments=yes + +# Ignore docstrings when computing similarities. +ignore-docstrings=yes + +# Ignore imports when computing similarities. +ignore-imports=no + + +[SPELLING] + +# Spelling dictionary name. Available dictionaries: none. To make it working +# install python-enchant package. +spelling-dict= + +# List of comma separated words that should not be checked. +spelling-ignore-words= + +# A path to a file that contains private dictionary; one word per line. +spelling-private-dict-file= + +# Tells whether to store unknown words to indicated private dictionary in +# --spelling-private-dict-file option instead of raising a message. +spelling-store-unknown-words=no + + +[IMPORTS] + +# Deprecated modules which should not be used, separated by a comma +deprecated-modules=regsub, + TERMIOS, + Bastion, + rexec, + sets + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report RP0402 must not be disabled) +import-graph= + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled) +ext-import-graph= + +# Create a graph of internal dependencies in the given file (report RP0402 must +# not be disabled) +int-import-graph= + +# Force import order to recognize a module as part of the standard +# compatibility libraries. +known-standard-library= + +# Force import order to recognize a module as part of a third party library. +known-third-party=enchant, absl + +# Analyse import fallback blocks. This can be used to support both Python 2 and +# 3 compatible code, which means that the block might have code that exists +# only in one or another interpreter, leading to false positives when analysed. +analyse-fallback-blocks=no + + +[CLASSES] + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__, + __new__, + setUp + +# List of member names, which should be excluded from the protected access +# warning. +exclude-protected=_asdict, + _fields, + _replace, + _source, + _make + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls, + class_ + +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg=mcs + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when being caught. Defaults to +# "Exception" +overgeneral-exceptions=StandardError, + Exception, + BaseException diff --git a/third-party/webp/libwebp/.style.yapf b/third-party/webp/libwebp/.style.yapf new file mode 100644 index 0000000000..0be981a486 --- /dev/null +++ b/third-party/webp/libwebp/.style.yapf @@ -0,0 +1,2 @@ +[style] +based_on_style = yapf \ No newline at end of file diff --git a/third-party/webp/libwebp/AUTHORS b/third-party/webp/libwebp/AUTHORS new file mode 100644 index 0000000000..8359b20da9 --- /dev/null +++ b/third-party/webp/libwebp/AUTHORS @@ -0,0 +1,60 @@ +Contributors: +- Aidan O'Loan (aidanol at gmail dot com) +- Alan Browning (browning at google dot com) +- Alexandru Ardelean (ardeleanalex at gmail dot com) +- Brian Ledger (brianpl at google dot com) +- Charles Munger (clm at google dot com) +- Cheng Yi (cyi at google dot com) +- Christian Duvivier (cduvivier at google dot com) +- Christopher Degawa (ccom at randomderp dot com) +- Clement Courbet (courbet at google dot com) +- Djordje Pesut (djordje dot pesut at imgtec dot com) +- Frank Barchard (fbarchard at google dot com) +- Hui Su (huisu at google dot com) +- H. Vetinari (h dot vetinari at gmx dot com) +- Ilya Kurdyukov (jpegqs at gmail dot com) +- Ingvar Stepanyan (rreverser at google dot com) +- James Zern (jzern at google dot com) +- Jan Engelhardt (jengelh at medozas dot de) +- Jehan (jehan at girinstud dot io) +- Jeremy Maitin-Shepard (jbms at google dot com) +- Johann Koenig (johann dot koenig at duck dot com) +- Jovan Zelincevic (jovan dot zelincevic at imgtec dot com) +- Jyrki Alakuijala (jyrki at google dot com) +- Konstantin Ivlev (tomskside at gmail dot com) +- Lode Vandevenne (lode at google dot com) +- Lou Quillio (louquillio at google dot com) +- Mans Rullgard (mans at mansr dot com) +- Marcin Kowalczyk (qrczak at google dot com) +- Martin Olsson (mnemo at minimum dot se) +- Maryla Ustarroz-Calonge (maryla at google dot com) +- MikoÅ‚aj Zalewski (mikolajz at google dot com) +- Mislav Bradac (mislavm at google dot com) +- Nico Weber (thakis at chromium dot org) +- Noel Chromium (noel at chromium dot org) +- Nozomi Isozaki (nontan at pixiv dot co dot jp) +- Oliver Wolff (oliver dot wolff at qt dot io) +- Owen Rodley (orodley at google dot com) +- Parag Salasakar (img dot mips1 at gmail dot com) +- Pascal Massimino (pascal dot massimino at gmail dot com) +- PaweÅ‚ Hajdan, Jr (phajdan dot jr at chromium dot org) +- Pierre Joye (pierre dot php at gmail dot com) +- Roberto Alanis (alanisbaez at google dot com) +- Sam Clegg (sbc at chromium dot org) +- Scott Hancher (seh at google dot com) +- Scott LaVarnway (slavarnway at google dot com) +- Scott Talbot (s at chikachow dot org) +- Slobodan Prijic (slobodan dot prijic at imgtec dot com) +- Somnath Banerjee (somnath dot banerjee at gmail dot com) +- Sriraman Tallam (tmsriram at google dot com) +- Tamar Levy (tamar dot levy at intel dot com) +- Thiago Perrotta (tperrotta at google dot com) +- Timothy Gu (timothygu99 at gmail dot com) +- Urvang Joshi (urvang at google dot com) +- Vikas Arora (vikasa at google dot com) +- Vincent Rabaud (vrabaud at google dot com) +- Vlad Tsyrklevich (vtsyrklevich at chromium dot org) +- Wan-Teh Chang (wtc at google dot com) +- Yang Zhang (yang dot zhang at arm dot com) +- Yannis Guyon (yguyon at google dot com) +- Zhi An Ng (zhin at chromium dot org) diff --git a/third-party/webp/libwebp/Android.mk b/third-party/webp/libwebp/Android.mk new file mode 100644 index 0000000000..f1e9ad8030 --- /dev/null +++ b/third-party/webp/libwebp/Android.mk @@ -0,0 +1,295 @@ +# Ignore this file during non-NDK builds. +ifdef NDK_ROOT +LOCAL_PATH := $(call my-dir) + +WEBP_CFLAGS := -Wall -DANDROID -DHAVE_MALLOC_H -DHAVE_PTHREAD -DWEBP_USE_THREAD +WEBP_CFLAGS += -fvisibility=hidden + +ifeq ($(APP_OPTIM),release) + WEBP_CFLAGS += -finline-functions -ffast-math \ + -ffunction-sections -fdata-sections + ifeq ($(findstring clang,$(NDK_TOOLCHAIN_VERSION)),) + WEBP_CFLAGS += -frename-registers -s + endif +endif + +# mips32 fails to build with clang from r14b +# https://bugs.chromium.org/p/webp/issues/detail?id=343 +ifeq ($(findstring clang,$(NDK_TOOLCHAIN_VERSION)),clang) + ifeq ($(TARGET_ARCH),mips) + clang_version := $(shell $(TARGET_CC) --version) + ifneq ($(findstring clang version 3,$(clang_version)),) + WEBP_CFLAGS += -no-integrated-as + endif + endif +endif + +ifneq ($(findstring armeabi-v7a, $(TARGET_ARCH_ABI)),) + # Setting LOCAL_ARM_NEON will enable -mfpu=neon which may cause illegal + # instructions to be generated for armv7a code. Instead target the neon code + # specifically. + NEON := c.neon + USE_CPUFEATURES := yes + WEBP_CFLAGS += -DHAVE_CPU_FEATURES_H +else + NEON := c +endif + +sharpyuv_srcs := \ + sharpyuv/sharpyuv.c \ + sharpyuv/sharpyuv_cpu.c \ + sharpyuv/sharpyuv_csp.c \ + sharpyuv/sharpyuv_dsp.c \ + sharpyuv/sharpyuv_gamma.c \ + sharpyuv/sharpyuv_neon.$(NEON) \ + sharpyuv/sharpyuv_sse2.c \ + +dec_srcs := \ + src/dec/alpha_dec.c \ + src/dec/buffer_dec.c \ + src/dec/frame_dec.c \ + src/dec/idec_dec.c \ + src/dec/io_dec.c \ + src/dec/quant_dec.c \ + src/dec/tree_dec.c \ + src/dec/vp8_dec.c \ + src/dec/vp8l_dec.c \ + src/dec/webp_dec.c \ + +demux_srcs := \ + src/demux/anim_decode.c \ + src/demux/demux.c \ + +dsp_dec_srcs := \ + src/dsp/alpha_processing.c \ + src/dsp/alpha_processing_mips_dsp_r2.c \ + src/dsp/alpha_processing_neon.$(NEON) \ + src/dsp/alpha_processing_sse2.c \ + src/dsp/alpha_processing_sse41.c \ + src/dsp/cpu.c \ + src/dsp/dec.c \ + src/dsp/dec_clip_tables.c \ + src/dsp/dec_mips32.c \ + src/dsp/dec_mips_dsp_r2.c \ + src/dsp/dec_msa.c \ + src/dsp/dec_neon.$(NEON) \ + src/dsp/dec_sse2.c \ + src/dsp/dec_sse41.c \ + src/dsp/filters.c \ + src/dsp/filters_mips_dsp_r2.c \ + src/dsp/filters_msa.c \ + src/dsp/filters_neon.$(NEON) \ + src/dsp/filters_sse2.c \ + src/dsp/lossless.c \ + src/dsp/lossless_mips_dsp_r2.c \ + src/dsp/lossless_msa.c \ + src/dsp/lossless_neon.$(NEON) \ + src/dsp/lossless_sse2.c \ + src/dsp/lossless_sse41.c \ + src/dsp/rescaler.c \ + src/dsp/rescaler_mips32.c \ + src/dsp/rescaler_mips_dsp_r2.c \ + src/dsp/rescaler_msa.c \ + src/dsp/rescaler_neon.$(NEON) \ + src/dsp/rescaler_sse2.c \ + src/dsp/upsampling.c \ + src/dsp/upsampling_mips_dsp_r2.c \ + src/dsp/upsampling_msa.c \ + src/dsp/upsampling_neon.$(NEON) \ + src/dsp/upsampling_sse2.c \ + src/dsp/upsampling_sse41.c \ + src/dsp/yuv.c \ + src/dsp/yuv_mips32.c \ + src/dsp/yuv_mips_dsp_r2.c \ + src/dsp/yuv_neon.$(NEON) \ + src/dsp/yuv_sse2.c \ + src/dsp/yuv_sse41.c \ + +dsp_enc_srcs := \ + src/dsp/cost.c \ + src/dsp/cost_mips32.c \ + src/dsp/cost_mips_dsp_r2.c \ + src/dsp/cost_neon.$(NEON) \ + src/dsp/cost_sse2.c \ + src/dsp/enc.c \ + src/dsp/enc_mips32.c \ + src/dsp/enc_mips_dsp_r2.c \ + src/dsp/enc_msa.c \ + src/dsp/enc_neon.$(NEON) \ + src/dsp/enc_sse2.c \ + src/dsp/enc_sse41.c \ + src/dsp/lossless_enc.c \ + src/dsp/lossless_enc_mips32.c \ + src/dsp/lossless_enc_mips_dsp_r2.c \ + src/dsp/lossless_enc_msa.c \ + src/dsp/lossless_enc_neon.$(NEON) \ + src/dsp/lossless_enc_sse2.c \ + src/dsp/lossless_enc_sse41.c \ + src/dsp/ssim.c \ + src/dsp/ssim_sse2.c \ + +enc_srcs := \ + src/enc/alpha_enc.c \ + src/enc/analysis_enc.c \ + src/enc/backward_references_cost_enc.c \ + src/enc/backward_references_enc.c \ + src/enc/config_enc.c \ + src/enc/cost_enc.c \ + src/enc/filter_enc.c \ + src/enc/frame_enc.c \ + src/enc/histogram_enc.c \ + src/enc/iterator_enc.c \ + src/enc/near_lossless_enc.c \ + src/enc/picture_enc.c \ + src/enc/picture_csp_enc.c \ + src/enc/picture_psnr_enc.c \ + src/enc/picture_rescale_enc.c \ + src/enc/picture_tools_enc.c \ + src/enc/predictor_enc.c \ + src/enc/quant_enc.c \ + src/enc/syntax_enc.c \ + src/enc/token_enc.c \ + src/enc/tree_enc.c \ + src/enc/vp8l_enc.c \ + src/enc/webp_enc.c \ + +mux_srcs := \ + src/mux/anim_encode.c \ + src/mux/muxedit.c \ + src/mux/muxinternal.c \ + src/mux/muxread.c \ + +utils_dec_srcs := \ + src/utils/bit_reader_utils.c \ + src/utils/color_cache_utils.c \ + src/utils/filters_utils.c \ + src/utils/huffman_utils.c \ + src/utils/palette.c \ + src/utils/quant_levels_dec_utils.c \ + src/utils/random_utils.c \ + src/utils/rescaler_utils.c \ + src/utils/thread_utils.c \ + src/utils/utils.c \ + +utils_enc_srcs := \ + src/utils/bit_writer_utils.c \ + src/utils/huffman_encode_utils.c \ + src/utils/quant_levels_utils.c \ + +################################################################################ +# libwebpdecoder + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + $(dec_srcs) \ + $(dsp_dec_srcs) \ + $(utils_dec_srcs) \ + +LOCAL_CFLAGS := $(WEBP_CFLAGS) +LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/src + +# prefer arm over thumb mode for performance gains +LOCAL_ARM_MODE := arm + +ifeq ($(USE_CPUFEATURES),yes) + LOCAL_STATIC_LIBRARIES := cpufeatures +endif + +LOCAL_MODULE := webpdecoder_static + +include $(BUILD_STATIC_LIBRARY) + +ifeq ($(ENABLE_SHARED),1) +include $(CLEAR_VARS) + +LOCAL_WHOLE_STATIC_LIBRARIES := webpdecoder_static + +LOCAL_MODULE := webpdecoder + +include $(BUILD_SHARED_LIBRARY) +endif # ENABLE_SHARED=1 + +################################################################################ +# libwebp + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + $(sharpyuv_srcs) \ + $(dsp_enc_srcs) \ + $(enc_srcs) \ + $(utils_enc_srcs) \ + +LOCAL_CFLAGS := $(WEBP_CFLAGS) +LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/src $(LOCAL_PATH) + +# prefer arm over thumb mode for performance gains +LOCAL_ARM_MODE := arm + +LOCAL_WHOLE_STATIC_LIBRARIES := webpdecoder_static + +LOCAL_MODULE := webp + +ifeq ($(ENABLE_SHARED),1) + include $(BUILD_SHARED_LIBRARY) +else + include $(BUILD_STATIC_LIBRARY) +endif + +################################################################################ +# libwebpdemux + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(demux_srcs) + +LOCAL_CFLAGS := $(WEBP_CFLAGS) +LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/src + +# prefer arm over thumb mode for performance gains +LOCAL_ARM_MODE := arm + +LOCAL_MODULE := webpdemux + +ifeq ($(ENABLE_SHARED),1) + LOCAL_SHARED_LIBRARIES := webp + include $(BUILD_SHARED_LIBRARY) +else + LOCAL_STATIC_LIBRARIES := webp + include $(BUILD_STATIC_LIBRARY) +endif + +################################################################################ +# libwebpmux + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(mux_srcs) + +LOCAL_CFLAGS := $(WEBP_CFLAGS) +LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/src + +# prefer arm over thumb mode for performance gains +LOCAL_ARM_MODE := arm + +LOCAL_MODULE := webpmux + +ifeq ($(ENABLE_SHARED),1) + LOCAL_SHARED_LIBRARIES := webp + include $(BUILD_SHARED_LIBRARY) +else + LOCAL_STATIC_LIBRARIES := webp + include $(BUILD_STATIC_LIBRARY) +endif + +################################################################################ + +WEBP_SRC_PATH := $(LOCAL_PATH) +include $(WEBP_SRC_PATH)/imageio/Android.mk +include $(WEBP_SRC_PATH)/examples/Android.mk + +ifeq ($(USE_CPUFEATURES),yes) + $(call import-module,android/cpufeatures) +endif +endif # NDK_ROOT diff --git a/third-party/webp/libwebp/CMakeLists.txt b/third-party/webp/libwebp/CMakeLists.txt new file mode 100644 index 0000000000..ad5e14c347 --- /dev/null +++ b/third-party/webp/libwebp/CMakeLists.txt @@ -0,0 +1,802 @@ +# Copyright (c) 2020 Google LLC. +# +# Use of this source code is governed by a BSD-style license +# that can be found in the LICENSE file in the root of the source +# tree. An additional intellectual property rights grant can be found +# in the file PATENTS. All contributing project authors may +# be found in the AUTHORS file in the root of the source tree. + +if(APPLE) + cmake_minimum_required(VERSION 3.17) +else() + cmake_minimum_required(VERSION 3.7) +endif() + +if(POLICY CMP0072) + cmake_policy(SET CMP0072 NEW) +endif() + +project(WebP C) + +# Options for coder / decoder executables. +if(BUILD_SHARED_LIBS) + set(WEBP_LINK_STATIC_DEFAULT OFF) +else() + set(WEBP_LINK_STATIC_DEFAULT ON) +endif() +option(WEBP_LINK_STATIC + "Link using static libraries. If OFF, use dynamic libraries." + ${WEBP_LINK_STATIC_DEFAULT}) +if(NOT EMSCRIPTEN) + # Disable SIMD on Emscripten by default, as it's a new unstable Wasm feature. + # Users can still explicitly opt-in to make a SIMD-enabled build. + set(WEBP_ENABLE_SIMD_DEFAULT ON) +endif() +option(WEBP_ENABLE_SIMD "Enable any SIMD optimization." + ${WEBP_ENABLE_SIMD_DEFAULT}) +option(WEBP_BUILD_ANIM_UTILS "Build animation utilities." ON) +option(WEBP_BUILD_CWEBP "Build the cwebp command line tool." ON) +option(WEBP_BUILD_DWEBP "Build the dwebp command line tool." ON) +option(WEBP_BUILD_GIF2WEBP "Build the gif2webp conversion tool." ON) +option(WEBP_BUILD_IMG2WEBP "Build the img2webp animation tool." ON) +option(WEBP_BUILD_VWEBP "Build the vwebp viewer tool." ON) +option(WEBP_BUILD_WEBPINFO "Build the webpinfo command line tool." ON) +option(WEBP_BUILD_LIBWEBPMUX "Build the libwebpmux library." ON) +option(WEBP_BUILD_WEBPMUX "Build the webpmux command line tool." ON) +option(WEBP_BUILD_EXTRAS "Build extras." ON) +option(WEBP_BUILD_WEBP_JS "Emscripten build of webp.js." OFF) +option(WEBP_USE_THREAD "Enable threading support" ON) +option(WEBP_NEAR_LOSSLESS "Enable near-lossless encoding" ON) +option(WEBP_ENABLE_SWAP_16BIT_CSP "Enable byte swap for 16 bit colorspaces." + OFF) +set(WEBP_BITTRACE "0" CACHE STRING "Bit trace mode (0=none, 1=bit, 2=bytes)") +set_property(CACHE WEBP_BITTRACE PROPERTY STRINGS 0 1 2) + +if(WEBP_LINK_STATIC) + if(WIN32) + set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) + else() + set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) + endif() + set(CMAKE_POSITION_INDEPENDENT_CODE ON) + # vwebp does not compile on Ubuntu with static libraries so disabling it for + # now. + set(WEBP_BUILD_VWEBP OFF) +endif() + +# Option needed for handling Unicode file names on Windows. +if(WIN32) + option(WEBP_UNICODE "Build Unicode executables." ON) +endif() + +if(WEBP_BUILD_WEBP_JS) + set(WEBP_BUILD_ANIM_UTILS OFF) + set(WEBP_BUILD_CWEBP OFF) + set(WEBP_BUILD_DWEBP OFF) + set(WEBP_BUILD_GIF2WEBP OFF) + set(WEBP_BUILD_IMG2WEBP OFF) + set(WEBP_BUILD_VWEBP OFF) + set(WEBP_BUILD_WEBPINFO OFF) + set(WEBP_BUILD_WEBPMUX OFF) + set(WEBP_BUILD_EXTRAS OFF) + set(WEBP_USE_THREAD OFF) + + if(WEBP_ENABLE_SIMD) + message(NOTICE + "wasm2js does not support SIMD, disabling webp.js generation.") + endif() +endif() + +set(SHARPYUV_DEP_LIBRARIES) +set(SHARPYUV_DEP_INCLUDE_DIRS) +set(WEBP_DEP_LIBRARIES) +set(WEBP_DEP_INCLUDE_DIRS) + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Release" + CACHE STRING "Build type: Release, Debug, MinSizeRel or RelWithDebInfo" + FORCE) +endif() + +# Include dependencies. +if(WEBP_BUILD_ANIM_UTILS + OR WEBP_BUILD_CWEBP + OR WEBP_BUILD_DWEBP + OR WEBP_BUILD_EXTRAS + OR WEBP_BUILD_GIF2WEBP + OR WEBP_BUILD_IMG2WEBP) + set(WEBP_FIND_IMG_LIBS TRUE) +else() + set(WEBP_FIND_IMG_LIBS FALSE) +endif() +include(cmake/deps.cmake) +include(GNUInstallDirs) + +if(BUILD_SHARED_LIBS AND NOT DEFINED CMAKE_INSTALL_RPATH) + # Set the rpath to match autoconf/libtool behavior. Note this must be set + # before target creation. + set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") +endif() + +# ############################################################################## +# Options. +if(WEBP_ENABLE_SWAP_16BIT_CSP) + add_definitions(-DWEBP_SWAP_16BIT_CSP=1) +endif() + +if(NOT WEBP_BITTRACE STREQUAL "0") + add_definitions(-DBITTRACE=${WEBP_BITTRACE}) +endif() + +if(WEBP_UNICODE) + # Windows recommends setting both UNICODE and _UNICODE. + add_definitions(-DUNICODE -D_UNICODE) +endif() + +if(MSVC AND BUILD_SHARED_LIBS) + add_definitions(-DWEBP_DLL) +endif() + +# pkg-config variables used by *.pc.in. +set(prefix ${CMAKE_INSTALL_PREFIX}) +set(exec_prefix "\${prefix}") +if(IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}") + set(libdir "${CMAKE_INSTALL_LIBDIR}") +else() + set(libdir "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}") +endif() +if(IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}") + set(includedir "${CMAKE_INSTALL_INCLUDEDIR}") +else() + set(includedir "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}") +endif() +set(PTHREAD_LIBS ${CMAKE_THREAD_LIBS_INIT}) +set(INSTALLED_LIBRARIES) + +if(MSVC) + # match the naming convention used by nmake + set(webp_libname_prefix "lib") + set(CMAKE_SHARED_LIBRARY_PREFIX "${webp_libname_prefix}") + set(CMAKE_IMPORT_LIBRARY_PREFIX "${webp_libname_prefix}") + set(CMAKE_STATIC_LIBRARY_PREFIX "${webp_libname_prefix}") +endif() + +set(CMAKE_C_VISIBILITY_PRESET hidden) + +# ############################################################################## +# Android only. +if(ANDROID) + include_directories(${ANDROID_NDK}/sources/android/cpufeatures) + add_library(cpufeatures-webp STATIC + ${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c) + list(APPEND INSTALLED_LIBRARIES cpufeatures-webp) + target_link_libraries(cpufeatures-webp dl) + set(SHARPYUV_DEP_LIBRARIES ${SHARPYUV_DEP_LIBRARIES} cpufeatures-webp) + set(WEBP_DEP_LIBRARIES ${WEBP_DEP_LIBRARIES} cpufeatures-webp) + set(cpufeatures_include_dir ${ANDROID_NDK}/sources/android/cpufeatures) + set(SHARPYUV_DEP_INCLUDE_DIRS ${SHARPYUV_DEP_INCLUDE_DIRS} + ${cpufeatures_include_dir}) + set(WEBP_DEP_INCLUDE_DIRS ${WEBP_DEP_INCLUDE_DIRS} ${cpufeatures_include_dir}) + add_definitions(-DHAVE_CPU_FEATURES_H=1) + set(HAVE_CPU_FEATURES_H 1) +else() + set(HAVE_CPU_FEATURES_H 0) +endif() + +function(configure_pkg_config FILE) + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/${FILE}.in" + "${CMAKE_CURRENT_BINARY_DIR}/${FILE}" @ONLY) + + if(HAVE_MATH_LIBRARY) + # MSVC doesn't have libm + file(READ ${CMAKE_CURRENT_BINARY_DIR}/${FILE} data) + string(REPLACE "-lm" "" data ${data}) + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/${FILE} ${data}) + endif() + + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${FILE}" + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) +endfunction() + +# ############################################################################## +# WebP source files. Read the Makefile.am to get the source files. + +# We expect the Makefiles to define the sources as defined in the first regex. +# E.g.: libimagedec_la_SOURCES = image_dec.c image_dec.h +function(parse_Makefile_am FOLDER VAR SRC_REGEX) + file(READ ${FOLDER}/Makefile.am MAKEFILE_AM) + string(REGEX MATCHALL "${SRC_REGEX}_SOURCES[ ]*\\+?=[ ]+[0-9a-z\\._ ]*" + FILES_PER_LINE ${MAKEFILE_AM}) + set(SRCS ${${VAR}}) + foreach(FILES ${FILES_PER_LINE}) + string(FIND ${FILES} "=" OFFSET) + math(EXPR OFFSET "${OFFSET} + 2") + string(SUBSTRING ${FILES} ${OFFSET} -1 FILES) + if(FILES) + string(REGEX MATCHALL "[0-9a-z\\._]+" FILES ${FILES}) + foreach(FILE ${FILES}) + list(APPEND SRCS ${FOLDER}/${FILE}) + endforeach() + endif() + endforeach() + set(${VAR} ${SRCS} PARENT_SCOPE) +endfunction() + +set(WEBP_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src) +parse_makefile_am(${WEBP_SRC_DIR}/dec "WEBP_DEC_SRCS" "") +parse_makefile_am(${WEBP_SRC_DIR}/demux "WEBP_DEMUX_SRCS" "") +parse_makefile_am(${WEBP_SRC_DIR}/dsp "WEBP_DSP_COMMON_SRCS" "COMMON") +parse_makefile_am(${WEBP_SRC_DIR}/dsp "WEBP_DSP_ENC_SRCS" "ENC") +parse_makefile_am(${WEBP_SRC_DIR}/dsp "WEBP_DSP_ENC_SRCS" "dsp_[^ ]*") +parse_makefile_am(${WEBP_SRC_DIR}/dsp "WEBP_DSP_DEC_SRCS" "decode_[^ ]*") +parse_makefile_am(${WEBP_SRC_DIR}/enc "WEBP_ENC_SRCS" "") +parse_makefile_am(${WEBP_SRC_DIR}/utils "WEBP_UTILS_COMMON_SRCS" "COMMON") +parse_makefile_am(${WEBP_SRC_DIR}/utils "WEBP_UTILS_ENC_SRCS" "ENC") +parse_makefile_am(${WEBP_SRC_DIR}/utils "WEBP_UTILS_DEC_SRCS" "decode_[^ ]*") + +# Remove the files specific to SIMD we don't use. +foreach(FILE ${WEBP_SIMD_FILES_NOT_TO_INCLUDE}) + list(REMOVE_ITEM WEBP_DSP_ENC_SRCS ${FILE}) + list(REMOVE_ITEM WEBP_DSP_DEC_SRCS ${FILE}) +endforeach() + +# Generate the config.h file. +configure_file(${CMAKE_CURRENT_LIST_DIR}/cmake/config.h.in + ${CMAKE_CURRENT_BINARY_DIR}/src/webp/config.h @ONLY) +add_definitions(-DHAVE_CONFIG_H) + +# Set the version numbers. +macro(set_version FILE TARGET_NAME NAME_IN_MAKEFILE) + file(READ ${CMAKE_CURRENT_SOURCE_DIR}/${FILE} SOURCE_FILE) + string(REGEX MATCH + "${NAME_IN_MAKEFILE}_la_LDFLAGS[^\n]* -version-info [0-9:]+" TMP + ${SOURCE_FILE}) + string(REGEX MATCH "[0-9:]+" TMP ${TMP}) + string(REGEX REPLACE ":" " " LT_VERSION ${TMP}) + + # See the libtool docs for more information: + # https://www.gnu.org/software/libtool/manual/libtool.html#Updating-version-info + # + # c=, a=, r= + # + # libtool generates a .so file as .so.[c-a].a.r, while -version-info c:r:a is + # passed to libtool. + # + # We set FULL = [c-a].a.r and MAJOR = [c-a]. + separate_arguments(LT_VERSION) + list(GET LT_VERSION 0 LT_CURRENT) + list(GET LT_VERSION 1 LT_REVISION) + list(GET LT_VERSION 2 LT_AGE) + math(EXPR LT_CURRENT_MINUS_AGE "${LT_CURRENT} - ${LT_AGE}") + + set_target_properties( + ${TARGET_NAME} + PROPERTIES VERSION ${LT_CURRENT_MINUS_AGE}.${LT_AGE}.${LT_REVISION} + SOVERSION ${LT_CURRENT_MINUS_AGE}) + if(APPLE) + # For compatibility, set MACHO_COMPATIBILITY_VERSION and + # MACHO_CURRENT_VERSION to match libtool. These properties were introduced + # in 3.17: + # https://cmake.org/cmake/help/latest/prop_tgt/MACHO_COMPATIBILITY_VERSION.html + math(EXPR LIBWEBP_MACHO_COMPATIBILITY_VERSION "${LT_CURRENT} + 1") + set_target_properties( + ${TARGET_NAME} + PROPERTIES MACHO_COMPATIBILITY_VERSION + ${LIBWEBP_MACHO_COMPATIBILITY_VERSION} + MACHO_CURRENT_VERSION + ${LIBWEBP_MACHO_COMPATIBILITY_VERSION}.${LT_REVISION}) + endif() +endmacro() + +# ############################################################################## +# Build the webpdecoder library. + +# Creates a source file with an unused stub function in $CMAKE_BINARY_DIR and +# adds it to the specified target. Currently used only with Xcode. +# +# See also: +# https://cmake.org/cmake/help/v3.18/command/add_library.html#object-libraries +# "Some native build systems (such as Xcode) may not like targets that have only +# object files, so consider adding at least one real source file to any target +# that references $." +function(libwebp_add_stub_file TARGET) + set(stub_source_dir "${CMAKE_BINARY_DIR}") + set(stub_source_file "${stub_source_dir}/libwebp_${TARGET}_stub.c") + set(stub_source_code + "// Generated file. DO NOT EDIT!\n" + "// C source file created for target ${TARGET}.\n" + "void libwebp_${TARGET}_stub_function(void)\;\n" + "void libwebp_${TARGET}_stub_function(void) {}\n") + file(WRITE "${stub_source_file}" ${stub_source_code}) + + target_sources(${TARGET} PRIVATE ${stub_source_file}) +endfunction() + +parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/sharpyuv "WEBP_SHARPYUV_SRCS" "") +add_library(sharpyuv ${WEBP_SHARPYUV_SRCS}) +target_link_libraries(sharpyuv ${SHARPYUV_DEP_LIBRARIES}) +set_version(sharpyuv/Makefile.am sharpyuv sharpyuv) +target_include_directories( + sharpyuv PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/src) +set_target_properties( + sharpyuv + PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/sharpyuv/sharpyuv.h;\ +${CMAKE_CURRENT_SOURCE_DIR}/sharpyuv/sharpyuv_csp.h") +configure_pkg_config("sharpyuv/libsharpyuv.pc") +install( + TARGETS sharpyuv + EXPORT ${PROJECT_NAME}Targets + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/webp/sharpyuv + INCLUDES + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + ${CMAKE_INSTALL_INCLUDEDIR}/webp + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + +if(MSVC) + # avoid security warnings for e.g., fopen() used in the examples. + add_definitions(-D_CRT_SECURE_NO_WARNINGS) +else() + add_compile_options(-Wall) +endif() +include_directories(${WEBP_DEP_INCLUDE_DIRS}) +add_library(webpdecode OBJECT ${WEBP_DEC_SRCS}) +target_include_directories(webpdecode PRIVATE ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}) +add_library(webpdspdecode OBJECT ${WEBP_DSP_COMMON_SRCS} ${WEBP_DSP_DEC_SRCS}) +target_include_directories(webpdspdecode PRIVATE ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}) +add_library(webputilsdecode OBJECT ${WEBP_UTILS_COMMON_SRCS} + ${WEBP_UTILS_DEC_SRCS}) +target_include_directories(webputilsdecode PRIVATE ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}) +add_library( + webpdecoder $ $ + $) +if(XCODE) + libwebp_add_stub_file(webpdecoder) +endif() +target_link_libraries(webpdecoder ${WEBP_DEP_LIBRARIES}) +target_include_directories( + webpdecoder PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} + INTERFACE $ + $) +set_target_properties( + webpdecoder + PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/webp/decode.h;\ +${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h") + +configure_pkg_config("src/libwebpdecoder.pc") + +# Build the webp library. +add_library(webpencode OBJECT ${WEBP_ENC_SRCS}) +target_include_directories( + webpencode PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/src) +add_library(webpdsp OBJECT ${WEBP_DSP_COMMON_SRCS} ${WEBP_DSP_DEC_SRCS} + ${WEBP_DSP_ENC_SRCS}) +target_include_directories(webpdsp PRIVATE ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}) +add_library(webputils OBJECT ${WEBP_UTILS_COMMON_SRCS} ${WEBP_UTILS_DEC_SRCS} + ${WEBP_UTILS_ENC_SRCS}) +target_include_directories(webputils PRIVATE ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}) +add_library(webp $ $ + $ $) +target_link_libraries(webp sharpyuv) +if(XCODE) + libwebp_add_stub_file(webp) +endif() +target_link_libraries(webp ${WEBP_DEP_LIBRARIES}) +target_include_directories( + webp PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} + PUBLIC $ + $) +set_target_properties( + webp + PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/webp/decode.h;\ +${CMAKE_CURRENT_SOURCE_DIR}/src/webp/encode.h;\ +${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h") + +# Make sure the OBJECT libraries are built with position independent code (it is +# not ON by default). +set_target_properties(webpdecode webpdspdecode webputilsdecode webpencode + webpdsp webputils PROPERTIES POSITION_INDEPENDENT_CODE ON) +configure_pkg_config("src/libwebp.pc") + +# Build the webp demux library. +add_library(webpdemux ${WEBP_DEMUX_SRCS}) +target_link_libraries(webpdemux webp) +target_include_directories( + webpdemux PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} + PUBLIC $) +set_target_properties( + webpdemux + PROPERTIES + PUBLIC_HEADER + "${CMAKE_CURRENT_SOURCE_DIR}/src/webp/decode.h;\ +${CMAKE_CURRENT_SOURCE_DIR}/src/webp/demux.h;\ +${CMAKE_CURRENT_SOURCE_DIR}/src/webp/mux_types.h;\ +${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h") + +configure_pkg_config("src/demux/libwebpdemux.pc") + +set_version(src/Makefile.am webp webp) +set_version(src/Makefile.am webpdecoder webpdecoder) +set_version(src/demux/Makefile.am webpdemux webpdemux) +file(READ ${CMAKE_CURRENT_SOURCE_DIR}/configure.ac CONFIGURE_FILE) +string(REGEX MATCH "AC_INIT\\([^\n]*\\[[0-9\\.]+\\]" TMP ${CONFIGURE_FILE}) +string(REGEX MATCH "[0-9\\.]+" PROJECT_VERSION ${TMP}) + +# Define the libraries to install. +list(APPEND INSTALLED_LIBRARIES webpdecoder webp webpdemux) + +# Deal with SIMD. Change the compile flags for SIMD files we use. +list(LENGTH WEBP_SIMD_FILES_TO_INCLUDE WEBP_SIMD_FILES_TO_INCLUDE_LENGTH) +math(EXPR WEBP_SIMD_FILES_TO_INCLUDE_RANGE + "${WEBP_SIMD_FILES_TO_INCLUDE_LENGTH}-1") + +foreach(I_FILE RANGE ${WEBP_SIMD_FILES_TO_INCLUDE_RANGE}) + list(GET WEBP_SIMD_FILES_TO_INCLUDE ${I_FILE} FILE) + list(GET WEBP_SIMD_FLAGS_TO_INCLUDE ${I_FILE} SIMD_COMPILE_FLAG) + set_source_files_properties(${FILE} PROPERTIES COMPILE_FLAGS + ${SIMD_COMPILE_FLAG}) +endforeach() + +if(NOT WEBP_BUILD_LIBWEBPMUX) + set(WEBP_BUILD_GIF2WEBP OFF) + set(WEBP_BUILD_IMG2WEBP OFF) + set(WEBP_BUILD_WEBPMUX OFF) +endif() + +if(WEBP_BUILD_GIF2WEBP AND NOT GIF_FOUND) + set(WEBP_BUILD_GIF2WEBP OFF) +endif() + +if(WEBP_BUILD_ANIM_UTILS AND NOT GIF_FOUND) + set(WEBP_BUILD_ANIM_UTILS OFF) +endif() + +# Build the executables if asked for. +if(WEBP_BUILD_ANIM_UTILS + OR WEBP_BUILD_CWEBP + OR WEBP_BUILD_DWEBP + OR WEBP_BUILD_GIF2WEBP + OR WEBP_BUILD_IMG2WEBP + OR WEBP_BUILD_VWEBP + OR WEBP_BUILD_WEBPMUX + OR WEBP_BUILD_WEBPINFO) + # Example utility library. + parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "EXAMPLEUTIL_SRCS" + "example_util_[^ ]*") + list(APPEND EXAMPLEUTIL_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/examples/stopwatch.h) + add_library(exampleutil STATIC ${EXAMPLEUTIL_SRCS}) + target_include_directories( + exampleutil PUBLIC $) + + parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/imageio "IMAGEIOUTILS_SRCS" + "imageio_util_[^ ]*") + add_library(imageioutil STATIC ${IMAGEIOUTILS_SRCS}) + target_link_libraries(imageioutil webp) + target_link_libraries(exampleutil imageioutil) + + # Image-decoding utility library. + parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/imageio "IMAGEDEC_SRCS" + "imagedec_[^ ]*") + add_library(imagedec STATIC ${IMAGEDEC_SRCS}) + target_link_libraries(imagedec imageioutil webpdemux webp + ${WEBP_DEP_IMG_LIBRARIES}) + + # Image-encoding utility library. + parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/imageio "IMAGEENC_SRCS" + "imageenc_[^ ]*") + add_library(imageenc STATIC ${IMAGEENC_SRCS}) + target_link_libraries(imageenc imageioutil webp) + + set_property( + TARGET exampleutil imageioutil imagedec imageenc + PROPERTY INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/src + ${CMAKE_CURRENT_BINARY_DIR}/src) +endif() + +if(WEBP_BUILD_DWEBP) + # dwebp + parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "DWEBP_SRCS" "dwebp") + add_executable(dwebp ${DWEBP_SRCS}) + target_link_libraries(dwebp exampleutil imagedec imageenc) + target_include_directories(dwebp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src) + install(TARGETS dwebp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() + +if(WEBP_BUILD_CWEBP) + # cwebp + parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "CWEBP_SRCS" "cwebp") + add_executable(cwebp ${CWEBP_SRCS}) + target_link_libraries(cwebp exampleutil imagedec webp) + target_include_directories(cwebp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src + ${CMAKE_CURRENT_SOURCE_DIR}) + install(TARGETS cwebp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() + +if(WEBP_BUILD_LIBWEBPMUX) + parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/src/mux "WEBP_MUX_SRCS" "") + add_library(libwebpmux ${WEBP_MUX_SRCS}) + target_link_libraries(libwebpmux webp) + target_include_directories(libwebpmux PRIVATE ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}) + set_version(src/mux/Makefile.am libwebpmux webpmux) + set_target_properties( + libwebpmux + PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/webp/mux.h;\ +${CMAKE_CURRENT_SOURCE_DIR}/src/webp/mux_types.h;\ +${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h;") + set_target_properties(libwebpmux PROPERTIES OUTPUT_NAME webpmux) + list(APPEND INSTALLED_LIBRARIES libwebpmux) + configure_pkg_config("src/mux/libwebpmux.pc") +endif() + +if(WEBP_BUILD_GIF2WEBP) + # gif2webp + include_directories(${WEBP_DEP_GIF_INCLUDE_DIRS}) + parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "GIF2WEBP_SRCS" + "gif2webp") + add_executable(gif2webp ${GIF2WEBP_SRCS}) + target_link_libraries(gif2webp exampleutil imageioutil webp libwebpmux + ${WEBP_DEP_GIF_LIBRARIES}) + target_include_directories(gif2webp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src) + install(TARGETS gif2webp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() + +if(WEBP_BUILD_IMG2WEBP) + # img2webp + include_directories(${WEBP_DEP_IMG_INCLUDE_DIRS}) + parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "IMG2WEBP_SRCS" + "img2webp") + add_executable(img2webp ${IMG2WEBP_SRCS}) + target_link_libraries(img2webp exampleutil imagedec imageioutil webp + libwebpmux) + target_include_directories(img2webp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src + ${CMAKE_CURRENT_SOURCE_DIR}) + install(TARGETS img2webp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() + +if(WEBP_BUILD_VWEBP) + # vwebp + find_package(GLUT) + if(GLUT_FOUND) + include_directories(${WEBP_DEP_IMG_INCLUDE_DIRS}) + parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "VWEBP_SRCS" "vwebp") + add_executable(vwebp ${VWEBP_SRCS}) + target_link_libraries( + vwebp + ${OPENGL_LIBRARIES} + exampleutil + GLUT::GLUT + imageioutil + webp + webpdemux) + target_include_directories( + vwebp PRIVATE ${GLUT_INCLUDE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/src + ${OPENGL_INCLUDE_DIR}) + install(TARGETS vwebp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") + check_c_compiler_flag("-Wno-deprecated-declarations" HAS_NO_DEPRECATED) + if(HAS_NO_DEPRECATED) + target_compile_options(vwebp PRIVATE "-Wno-deprecated-declarations") + endif() + endif() + endif() +endif() + +if(WEBP_BUILD_WEBPINFO) + # webpinfo + include_directories(${WEBP_DEP_IMG_INCLUDE_DIRS}) + parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "WEBPINFO_SRCS" + "webpinfo") + add_executable(webpinfo ${WEBPINFO_SRCS}) + target_link_libraries(webpinfo exampleutil imageioutil) + target_include_directories(webpinfo PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src + ${CMAKE_CURRENT_SOURCE_DIR}/src) + install(TARGETS webpinfo RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() + +if(WEBP_BUILD_WEBPMUX) + # webpmux + parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "WEBPMUX_SRCS" + "webpmux") + add_executable(webpmux ${WEBPMUX_SRCS}) + target_link_libraries(webpmux exampleutil imageioutil libwebpmux webp) + target_include_directories(webpmux PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src) + install(TARGETS webpmux RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() + +if(WEBP_BUILD_EXTRAS) + set(EXTRAS_MAKEFILE "${CMAKE_CURRENT_SOURCE_DIR}/extras") + parse_makefile_am(${EXTRAS_MAKEFILE} "WEBP_EXTRAS_SRCS" "libwebpextras_la") + parse_makefile_am(${EXTRAS_MAKEFILE} "GET_DISTO_SRCS" "get_disto") + parse_makefile_am(${EXTRAS_MAKEFILE} "WEBP_QUALITY_SRCS" "webp_quality") + parse_makefile_am(${EXTRAS_MAKEFILE} "VWEBP_SDL_SRCS" "vwebp_sdl") + + # libextras + add_library(extras STATIC ${WEBP_EXTRAS_SRCS}) + target_include_directories( + extras PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/src) + + # get_disto + add_executable(get_disto ${GET_DISTO_SRCS}) + target_link_libraries(get_disto imagedec) + target_include_directories(get_disto PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/src) + + # webp_quality + add_executable(webp_quality ${WEBP_QUALITY_SRCS}) + target_link_libraries(webp_quality exampleutil imagedec extras) + target_include_directories(webp_quality PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR}) + + # vwebp_sdl + find_package(SDL) + if(WEBP_BUILD_VWEBP AND SDL_FOUND) + add_executable(vwebp_sdl ${VWEBP_SDL_SRCS}) + target_link_libraries(vwebp_sdl ${SDL_LIBRARY} imageioutil webp) + target_include_directories( + vwebp_sdl PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/src ${SDL_INCLUDE_DIR}) + set(WEBP_HAVE_SDL 1) + target_compile_definitions(vwebp_sdl PUBLIC WEBP_HAVE_SDL) + endif() +endif() + +if(WEBP_BUILD_WEBP_JS) + # The default stack size changed from 5MB to 64KB in 3.1.27. See + # https://crbug.com/webp/614. + if(EMSCRIPTEN_VERSION VERSION_GREATER_EQUAL "3.1.27") + # TOTAL_STACK size was renamed to STACK_SIZE in 3.1.27. The old name was + # kept for compatibility, but prefer the new one in case it is removed in + # the future. + set(emscripten_stack_size "-sSTACK_SIZE=5MB") + else() + set(emscripten_stack_size "-sTOTAL_STACK=5MB") + endif() + # wasm2js does not support SIMD. + if(NOT WEBP_ENABLE_SIMD) + # JavaScript version + add_executable(webp_js ${CMAKE_CURRENT_SOURCE_DIR}/extras/webp_to_sdl.c) + target_link_libraries(webp_js webpdecoder SDL) + target_include_directories(webp_js PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) + set(WEBP_HAVE_SDL 1) + set_target_properties( + webp_js + PROPERTIES LINK_FLAGS "-sWASM=0 ${emscripten_stack_size} \ + -sEXPORTED_FUNCTIONS=_WebPToSDL -sINVOKE_RUN=0 \ + -sEXPORTED_RUNTIME_METHODS=cwrap") + set_target_properties(webp_js PROPERTIES OUTPUT_NAME webp) + target_compile_definitions(webp_js PUBLIC EMSCRIPTEN WEBP_HAVE_SDL) + endif() + + # WASM version + add_executable(webp_wasm ${CMAKE_CURRENT_SOURCE_DIR}/extras/webp_to_sdl.c) + target_link_libraries(webp_wasm webpdecoder SDL) + target_include_directories(webp_wasm PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) + set_target_properties( + webp_wasm + PROPERTIES LINK_FLAGS "-sWASM=1 ${emscripten_stack_size} \ + -sEXPORTED_FUNCTIONS=_WebPToSDL -sINVOKE_RUN=0 \ + -sEXPORTED_RUNTIME_METHODS=cwrap") + target_compile_definitions(webp_wasm PUBLIC EMSCRIPTEN WEBP_HAVE_SDL) + + target_compile_definitions(webpdspdecode PUBLIC EMSCRIPTEN) +endif() + +if(WEBP_BUILD_ANIM_UTILS) + # anim_diff + include_directories(${WEBP_DEP_IMG_INCLUDE_DIRS} ${WEBP_DEP_GIF_INCLUDE_DIRS}) + parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "ANIM_DIFF_SRCS" + "anim_diff") + add_executable(anim_diff ${ANIM_DIFF_SRCS}) + target_link_libraries( + anim_diff + exampleutil + imagedec + imageenc + imageioutil + webp + webpdemux + ${WEBP_DEP_GIF_LIBRARIES}) + target_include_directories(anim_diff PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src) + + # anim_dump + include_directories(${WEBP_DEP_IMG_INCLUDE_DIRS} ${WEBP_DEP_GIF_INCLUDE_DIRS}) + parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "ANIM_DUMP_SRCS" + "anim_dump") + add_executable(anim_dump ${ANIM_DUMP_SRCS}) + target_link_libraries( + anim_dump + exampleutil + imagedec + imageenc + imageioutil + webp + webpdemux + ${WEBP_DEP_GIF_LIBRARIES}) + target_include_directories(anim_dump PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src) +endif() + +# Install the different headers and libraries. +install( + TARGETS ${INSTALLED_LIBRARIES} + EXPORT ${PROJECT_NAME}Targets + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/webp + INCLUDES + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +set(ConfigPackageLocation ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/cmake/) +install(EXPORT ${PROJECT_NAME}Targets NAMESPACE ${PROJECT_NAME}:: + DESTINATION ${ConfigPackageLocation}) + +# Create the CMake version file. +include(CMakePackageConfigHelpers) +write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/WebPConfigVersion.cmake" + VERSION ${PACKAGE_VERSION} COMPATIBILITY AnyNewerVersion) + +# Create the Config file. +include(CMakePackageConfigHelpers) +# Fix libwebpmux reference. The target name libwebpmux is used for compatibility +# purposes, but the library mentioned in WebPConfig.cmake should be the +# unprefixed version. Note string(...) can be replaced with list(TRANSFORM ...) +# if cmake_minimum_required is >= 3.12. +string(REGEX REPLACE "libwebpmux" "webpmux" INSTALLED_LIBRARIES + "${INSTALLED_LIBRARIES}") + +if(MSVC) + # For compatibility with nmake, MSVC builds use a custom prefix (lib) that + # needs to be included in the library name. + string(REGEX REPLACE "[A-Za-z0-9_]+" "${CMAKE_STATIC_LIBRARY_PREFIX}\\0" + INSTALLED_LIBRARIES "${INSTALLED_LIBRARIES}") +endif() + +configure_package_config_file( + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/WebPConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/WebPConfig.cmake + INSTALL_DESTINATION ${ConfigPackageLocation} + PATH_VARS CMAKE_INSTALL_INCLUDEDIR) + +# Install the generated CMake files. +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/WebPConfigVersion.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/WebPConfig.cmake" + DESTINATION ${ConfigPackageLocation}) + +# Install the man pages. +set(MAN_PAGES + cwebp.1 + dwebp.1 + gif2webp.1 + img2webp.1 + vwebp.1 + webpmux.1 + webpinfo.1) +set(EXEC_BUILDS + "CWEBP" + "DWEBP" + "GIF2WEBP" + "IMG2WEBP" + "VWEBP" + "WEBPMUX" + "WEBPINFO") +list(LENGTH MAN_PAGES MAN_PAGES_LENGTH) +math(EXPR MAN_PAGES_RANGE "${MAN_PAGES_LENGTH} - 1") + +foreach(I_MAN RANGE ${MAN_PAGES_RANGE}) + list(GET EXEC_BUILDS ${I_MAN} EXEC_BUILD) + if(WEBP_BUILD_${EXEC_BUILD}) + list(GET MAN_PAGES ${I_MAN} MAN_PAGE) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/man/${MAN_PAGE} + DESTINATION ${CMAKE_INSTALL_MANDIR}/man1 COMPONENT doc) + endif() +endforeach() diff --git a/third-party/webp/libwebp/CONTRIBUTING.md b/third-party/webp/libwebp/CONTRIBUTING.md new file mode 100644 index 0000000000..9540f34f75 --- /dev/null +++ b/third-party/webp/libwebp/CONTRIBUTING.md @@ -0,0 +1,78 @@ +# How to Contribute + +We'd love to accept your patches and contributions to this project. There are +just a few small guidelines you need to follow. + +## Contributor License Agreement + +Contributions to this project must be accompanied by a Contributor License +Agreement. You (or your employer) retain the copyright to your contribution; +this simply gives us permission to use and redistribute your contributions as +part of the project. Head over to to see +your current agreements on file or to sign a new one. + +You generally only need to submit a CLA once, so if you've already submitted one +(even if it was for a different project), you probably don't need to do it +again. + +## Code reviews + +All submissions, including submissions by project members, require review. We +use a [Gerrit](https://www.gerritcodereview.com) instance hosted at +https://chromium-review.googlesource.com for this purpose. + +## Sending patches + +The basic git workflow for modifying libwebp code and sending for review is: + +1. Get the latest version of the repository locally: + + ```sh + git clone https://chromium.googlesource.com/webm/libwebp && cd libwebp + ``` + +2. Copy the commit-msg script into ./git/hooks (this will add an ID to all of + your commits): + + ```sh + curl -Lo .git/hooks/commit-msg https://chromium-review.googlesource.com/tools/hooks/commit-msg && chmod u+x .git/hooks/commit-msg + ``` + +3. Modify the local copy of libwebp. Make sure the code + [builds successfully](https://chromium.googlesource.com/webm/libwebp/+/HEAD/doc/building.md#cmake). + +4. Choose a short and representative commit message: + + ```sh + git commit -a -m "Set commit message here" + ``` + +5. Send the patch for review: + + ```sh + git push https://chromium-review.googlesource.com/webm/libwebp HEAD:refs/for/main + ``` + + Go to https://chromium-review.googlesource.com to view your patch and + request a review from the maintainers. + +See the +[WebM Project page](https://www.webmproject.org/code/contribute/submitting-patches/) +for additional details. + +## Code Style + +The C code style is based on the +[Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) and +`clang-format --style=Google`, though this project doesn't use the tool to +enforce the formatting. + +CMake files are formatted with +[cmake-format](https://cmake-format.readthedocs.io/en/latest/). `cmake-format +-i` can be used to format individual files, it will use the settings from +`.cmake-format.py`. + +## Community Guidelines + +This project follows +[Google's Open Source Community Guidelines](https://opensource.google.com/conduct/). diff --git a/third-party/webp/libwebp/COPYING b/third-party/webp/libwebp/COPYING new file mode 100644 index 0000000000..7a6f99547d --- /dev/null +++ b/third-party/webp/libwebp/COPYING @@ -0,0 +1,30 @@ +Copyright (c) 2010, Google Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Google nor the names of its contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/third-party/webp/libwebp/ChangeLog b/third-party/webp/libwebp/ChangeLog new file mode 100644 index 0000000000..33ec48633c --- /dev/null +++ b/third-party/webp/libwebp/ChangeLog @@ -0,0 +1,4626 @@ +1ace578c update NEWS +63234c42 bump version to 1.3.2 +2af26267 Fix OOB write in BuildHuffmanTable. +fd7bb21c update ChangeLog (tag: v1.3.1-rc2, tag: v1.3.1) +e1adea50 update NEWS +43393320 enc/*: normalize WebPEncodingSetError() calls +287fdefe enc/*: add missing WebPEncodingSetError() calls +c3bd7cff EncodeAlphaInternal: add missing error check +d49cfbb3 vp8l_enc,WriteImage: add missing error check +2e5a9ec3 muxread,MuxImageParse: add missing error checks +ebb6f949 cmake,emscripten: explicitly set stack size +59a2b1f9 WebPDecodeYUV: check u/v/stride/uv_stride ptrs +8e965ccb Call png_get_channels() to see if image has alpha +7f0a3419 update ChangeLog (tag: v1.3.1-rc1) +bab7efbe update NEWS +7138bf8f bump version to 1.3.1 +435b4ded update AUTHORS +47351229 update .mailmap +ff6c7f4e CONTRIBUTING.md: add C style / cmake-format notes +dd530437 add .cmake-format.py +adbe2cb1 cmake,cosmetics: apply cmake-format +15b36508 doc/webp-container-spec: rm future codec comment +c369c4bf doc/webp-lossless-bitstream-spec: improve link text +1de35f47 doc/webp-container-spec: don't use 'currently' +bb06a16e doc/webp-container-spec: prefer present tense +9f38b71e doc/webp-lossless-bitstream-spec: prefer present tense +7acb6b82 doc/webp-container-spec: avoid i.e. & e.g. +4967e7cd doc/webp-lossless-bitstream-spec: avoid i.e. & e.g. +e3366659 Merge "Do not find_package image libraries if not needed." into main +428588ef clarify single leaf node trees and use of canonical prefix coding +709ec152 Do not find_package image libraries if not needed. +8dd80ef8 fuzz_utils.h: lower kFuzzPxLimit w/ASan +8f187b9f Clean message calls in CMake +cba30078 WebPConfig.cmake.in: use calculated include path +6cf9a76a Merge "webp-lossless-bitstream-spec: remove use of 'dynamics'" into main +740943b2 Merge "Specialize and optimize ITransform_SSE2 using do_two" into main +2d547e24 Compare kFuzzPxLimit to max_num_operations +ac42dde1 Specialize and optimize ITransform_SSE2 using do_two +17e0ef1d webp-lossless-bitstream-spec: remove use of 'dynamics' +ed274371 neon.h,cosmetics: clear a couple lint warnings +3fb82947 cpu.h,cosmetics: segment defines +0c496a4f cpu.h: add WEBP_AARCH64 +8151f388 move VP8GetCPUInfo declaration to cpu.c +916548c2 Make kFuzzPxLimit sanitizer dependent +4070b271 advanced_api_fuzzer: reduce scaling limit +761f49c3 Merge "webp-lossless-bitstream-spec: add missing bits to ABNF" into main +84d04c48 webp-lossless-bitstream-spec: add missing bits to ABNF +0696e1a7 advanced_api_fuzzer: reduce scaling limit +93d88aa2 Merge "deps.cmake: remove unneeded header checks" into main +118e0035 deps.cmake: remove unneeded header checks +4c3d7018 webp-lossless-bitstream-spec: condense normal-prefix-code +a6a09b32 webp-lossless-bitstream-spec: fix 2 code typos +50ac4f7c Merge "cpu.h: enable NEON w/_M_ARM64EC" into main +4b7d7b4f Add contribution instructions +0afbd97b cpu.h: enable NEON w/_M_ARM64EC +349f4353 Merge changes Ibd89e56b,Ic57e7f84,I89096614 into main +8f7513b7 upsampling_neon.c: fix WEBP_SWAP_16BIT_CSP check +cbf624b5 advanced_api_fuzzer: reduce scaling limit +89edfdd1 Skip slow scaling in libwebp advanced_api_fuzzer +859f19f7 Reduce libwebp advanced_api_fuzzer threshold +a4f04835 Merge changes Ic389aaa2,I329ccd79 into main +1275fac8 Makefile.vc: fix img2webp link w/dynamic cfg +2fe27bb9 img2webp: normalize help output +24bed3d9 cwebp: reflow -near_lossless help text +0825faa4 img2webp: add -sharp_yuv/-near_lossless +d64e6d7d Merge "PaletteSortModifiedZeng: fix leak on error" into main +0e12a22d Merge "EncodeAlphaInternal: clear result->bw on error" into main +0edbb6ea PaletteSortModifiedZeng: fix leak on error +41ffe04e Merge "Update yapf style from "chromium" to "yapf"" into main +2d9d9265 Update yapf style from "chromium" to "yapf" +a486d800 EncodeAlphaInternal: clear result->bw on error +1347a32d Skip big scaled advanced_api_fuzzer +52b6f067 Fix scaling limit in advanced_api_fuzzer.c +73618428 Limit scaling in libwebp advanced_api_fuzzer.c +b54d21a0 Merge "CMakeLists.txt: allow CMAKE_INSTALL_RPATH to be set empty" into main +31c28db5 libwebp{,demux,mux}.pc.in: Requires -> Requires.private +d9a505ff CMakeLists.txt: allow CMAKE_INSTALL_RPATH to be set empty +bdf33d03 Merge tag 'v1.3.0' +b5577769 update ChangeLog (tag: v1.3.0-rc1, tag: v1.3.0) +0ba77244 update NEWS +e763eb1e bump version to 1.3.0 +2a8686fc update AUTHORS +106a57c1 Merge "*/Android.mk: add a check for NDK_ROOT" into main +c5e841c4 Merge "extras: WebpToSDL -> WebPToSDL" into main +dbc30715 Merge "xcframeworkbuild.sh: bump MACOSX_CATALYST_MIN_VERSION" into main +6fc1a9f9 */Android.mk: add a check for NDK_ROOT +d3e151fc doc/api.md,webp_js/README.md: Webp -> WebP +ed92a626 extras: WebpToSDL -> WebPToSDL +6eb0189b xcframeworkbuild.sh: bump MACOSX_CATALYST_MIN_VERSION +1d58575b CMake: align .pc variables with autoconf +e5fe2cfc webp-lossless-bitstream-spec,cosmetics: reflow paragraphs +0ceeeab9 webp-lossless-bitstream-spec: add amendment note +607611cd Merge "webp-container-spec: normalize section title case" into main +f853685e lossless: SUBTRACT_GREEN -> SUBTRACT_GREEN_TRANSFORM +786497e4 webp-lossless-bitstream-spec: fix inv color txfm description +c6ac672d webp-lossless-bitstream-spec: fix num_code_lengths check +b5700efb webp-lossless-bitstream-spec,cosmetics: grammar/capitalization +d8ed8c11 webp-container-spec: normalize section title case +52ec0b8f Merge changes Ie975dbb5,Ifc8c93af,I6ca7c5d6,I2e8d66f5,I152477b8 into main +5097ef62 webp-container-spec,cosmetics: grammar/capitalization +e3ba2b1f webp-lossless-bitstream-spec,cosmetics: reflow abstract +1e8e3ded webp-lossless-bitstream-spec: reword abstract re alpha +017cb6fa webp-container-spec,cosmetics: normalize range syntax +f6a4684b webp-lossless-bitstream-spec,cosmetics: normalize range syntax +54ebd5a3 webp-lossless-bitstream-spec: limit dist map lut to 69 cols +44741f9c webp-lossless-bitstream-spec: fix dist mapping example +fad0ece7 pnmdec.c: use snprintf instead of sprintf +3f73e8f7 sharpyuv: add SharpYuvGetVersion() +ce2f2d66 SharpYuvConvert: fix a race on SharpYuvGetCPUInfo +a458e308 sharpyuv_dsp.h: restore sharpyuv_cpu.h include +9ba800a7 Merge changes Id72fbf3b,Ic59d23a2 into main +979c0ebb sharpyuv: add SharpYuvGetCPUInfo +8bab09a4 Merge "*.pc.in: rename lib_prefix to webp_libname_prefix" into main +769387c5 cpu.c,cosmetics: fix a typo +a02978c2 sharpyuv/Makefile.am+cmake: add missing -lm +28aedcb9 *.pc.in: rename lib_prefix to webp_libname_prefix +c42e6d5a configure.ac: export an empty lib_prefix variable +dfc843aa Merge "*.pc.in: add lib prefix to lib names w/MSVC" into main +2498209b *.pc.in: add lib prefix to lib names w/MSVC +ac252b61 Merge "analysis_enc.c: fix a dead store warning" into main +56944762 analysis_enc.c: fix a dead store warning +d34f9b99 Merge "webp-lossless-bitstream-spec: convert BNF to ABNF" into main +dc05b4db Merge changes I96bc063c,I45880467,If9e18e5a,I6ee938e4,I0a410b28, ... into main +83270c7f webp-container-spec: add prose for rendering process +73b19b64 webp-container-spec: note reserved fields MUST be ignored +57101d3f webp-lossless-bitstream-spec: improve 'small' color table stmt +dfd32e45 webp-container-spec: remove redundant sentence +8a6185dd doc/webp-*: fix some punctuation, grammar +72776530 webp-lossless-bitstream-spec: convert BNF to ABNF +d992bb08 cmake: rename cpufeatures target to cpufeatures-webp +3ed2b275 webp-container-spec: clarify background color note +951c292d webp-container-spec: come too late -> out of order +902dd787 webp-container-spec: prefer hex literals +a8f6b5ee webp-container-spec: change SHOULD to MUST w/ANIM chunk +1dc59435 webp-container-spec: add unknown fields MUST be ignored +280a810f webp-container-spec: make padding byte=0 a MUST +41f0bf68 webp-container-spec: update note on trailing data +6bdd36db webp-container-spec: clarify Chunk Size is in bytes +87e36c48 Merge "webp_js/README.md,cosmetics: reflow some lines" into main +5b01f321 Merge "Update Windows makefile to build libsharpyuv library." into main +19b1a71c webp_js/README.md,cosmetics: reflow some lines +780db756 Update Windows makefile to build libsharpyuv library. +e407d4b3 CMakeLists.txt: replace GLUT_glut_LIBRARY w/GLUT::GLUT +abf73d62 Merge "WebPConfig.cmake.in: add find_dependency(Threads)" into main +25807fb4 Merge "cmake: restore compatibility with cmake < 3.12" into main +5dbc4bfa WebPConfig.cmake.in: add find_dependency(Threads) +b2a175dd Merge "Update wasm instructions." into main +cb90f76b Update wasm instructions. +02d15258 cmake: restore compatibility with cmake < 3.12 +5ba046e2 CMake: add_definitions -> add_compile_options +e68765af dsp,neon: use vaddv in a few more places +e8f83de2 Set libsharpyuv include dir to 'webp' subdirectory. +15a91ab1 cmake,cosmetics: apply cmake-format +0dd49d1a CMakeLists.txt: set @ONLY in configure_file() calls +62b1bfe8 Merge changes I2877e7bb,I777cad70,I15af7d1a,I686e6740,If10538a9, ... into main +95c8fe5f Merge changes Iecea3603,I9dc228ab into main +e7c805cf picture_csp_enc.c: remove SafeInitSharpYuv +6af8845a sharpyuv: prefer webp/types.h +639619ce cmake: fix dll exports +782ed48c sharpyuv,SharpYuvInit: add mutex protection when available +cad0d5ad sharyuv_{neon,sse2}.c: merge WEBP_USE_* sections +ef70ee06 add a few missing includes for NULL +f0f9eda4 sharpyuv.h: remove +9b902cba Merge "picture_csp_enc.c,CheckNonOpaque: rm unneeded local" into main +9c1d457c cmake/cpu.cmake: remove unused variable +9ac25bcb CMakeLists.txt,win32: match naming convention used by nmake +76c353ba picture_csp_enc.c,CheckNonOpaque: rm unneeded local +5000de54 Merge "cwebp: fix WebPPictureHasTransparency call" into main +e1729309 Merge "WebPPictureHasTransparency: add missing pointer check" into main +00ff988a vp8l_enc,AddSingleSubGreen: clear int sanitizer warnings +e2fecc22 dsp/lossless_enc.c: clear int sanitizer warnings +129cf9e9 dsp/lossless.c: clear int sanitizer warnings +ad7d1753 dsp/lossless_enc.c: clear int sanitizer warnings +5037220e VP8LSubtractGreenFromBlueAndRed_C: clear int sanitizer warnings +2ee786c7 upsampling_sse2.c: clear int sanitizer warnings +4cc157d4 ParseOptionalChunks: clear int sanitizer warning +892cf033 BuildHuffmanTable: clear int sanitizer warning +3a9a4d45 VP8GetSigned: clear int sanitizer warnings +704a3d0a dsp/lossless.c: quiet int sanitizer warnings +1a6c109c WebPPictureHasTransparency: add missing pointer check +c626e7d5 cwebp: fix WebPPictureHasTransparency call +866e349c Merge tag 'v1.2.4' +c170df38 Merge "Create libsharpyuv.a in makefile.unix." into main +9d7ff74a Create libsharpyuv.a in makefile.unix. +0d1f1254 update ChangeLog (tag: v1.2.4) +fcbc2d78 Merge "doc/*.txt: restrict code to 69 columns" into main +4ad0e189 Merge "webp-container-spec.txt: normalize fourcc spelling" into main +980d2488 update NEWS +9fde8127 bump version to 1.2.4 +7a0a9935 doc/*.txt: restrict code to 69 columns +c040a615 webp-container-spec.txt: normalize fourcc spelling +aff1c546 dsp,x86: normalize types w/_mm_cvtsi128_si32 calls +ab540ae0 dsp,x86: normalize types w/_mm_cvtsi32_si128 calls +8980362e dsp,x86: normalize types w/_mm_set* calls (2) +e626925c lossless: fix crunch mode w/WEBP_REDUCE_SIZE +83539239 dsp,x86: normalize types w/_mm_set* calls +8a4576ce webp-container-spec.txt: replace & with & +db870881 Merge "webp-container-spec.txt: make reserved 0 values a MUST" into main +01d7d378 webp-lossless-bitstream-spec: number all sections +337cf69f webp-lossless-bitstream-spec: mv Nomenclature after Intro +79be856e Merge changes I7111d1f7,I872cd62c into main +5b87983a webp-container-spec.txt: make reserved 0 values a MUST +bd939123 Merge changes I7a25b1a6,I51b2c2a0,I87d0cbcf,I6ec60af6,I0a3fe9dc into main +04764b56 libwebp.pc: add libsharpyuv to requires +7deee810 libsharpyuv: add pkg-config file +1a64a7e6 webp-container-spec.txt: clarify some SHOULDs +bec2c88a webp-container-spec.txt: move ChunkHeader to terminology +c9359332 webp-container-spec.txt: clarify 'VP8 '/'XMP ' fourccs +70fe3063 webp-container-spec.txt: rightsize table entries +ddbf3f3f webp-container-spec.txt: update 'key words' text +c151e95b utils.h,WEBP_ALIGN: make bitmask unsigned +748e92bb add WebPInt32ToMem +3fe15b67 Merge "Build libsharpyuv as a full installable library." into main +4f402f34 add WebPMemToInt32 +a3b68c19 Build libsharpyuv as a full installable library. +b4994eaa CMake: set rpath for shared objects +94cd7117 Merge "CMake: fix dylib versioning" into main +e91451b6 Fix the lossless specs a bit more. +231bdfb7 CMake: fix dylib versioning +bfad7ab5 CMakeLists.txt: correct libwebpmux name in WebPConfig.cmake +c2e3fd30 Revert "cmake: fix webpmux lib name for cmake linking" +7366f7f3 Merge "lossless: fix crunch mode w/WEBP_REDUCE_SIZE" into main +84163d9d lossless: fix crunch mode w/WEBP_REDUCE_SIZE +d01c1eb3 webp-lossless-bitstream-spec,cosmetics: normalize capitalization +8813ca8e Merge tag 'v1.2.3' +3c4a0fbf update ChangeLog (tag: v1.2.3) +56a480e8 dsp/cpu.h: add missing extern "C" +62b45bdd update ChangeLog (tag: v1.2.3-rc1) +8764ec7a Merge changes Idb037953,Id582e395 into 1.2.3 +bcb872c3 vwebp: fix file name display in windows unicode build +67c44ac5 webpmux: fix -frame option in windows unicode build +8278825a makefile.unix: add sharpyuv objects to clean target +14a49e01 update NEWS +34b1dc33 bump version to 1.2.3 +0b397fda update AUTHORS +c16488ac update .mailmap +5a2d929c Merge "unicode.h: set console mode before using wprintf" into main +169f867f unicode.h: set console mode before using wprintf +a94b855c Merge "libsharpyuv: add version defines" into main +f83bdb52 libsharpyuv: add version defines +bef0d797 unicode_gif.h: fix -Wdeclaration-after-statement +404c1622 Rename Huffman coding to prefix coding in the bitstream spec +8895f8a3 Merge "run_static_analysis.sh: fix scan-build archive path" into main +92a673d2 Merge "Add -fvisibility=hidden flag in CMakeLists." into main +67c1d722 Merge "add WEBP_MSAN" into main +1124ff66 Add -fvisibility=hidden flag in CMakeLists. +e15b3560 add WEBP_MSAN +ec9e782a sharpyuv: remove minimum image size from sharpyuv library +7bd07f3b run_static_analysis.sh: fix scan-build archive path +5ecee06f Merge "sharpyuv: increase precision of gamma<->linear conversion" into main +f81dd7d6 Merge changes I3d17d529,I53026880,I1bd61639,I6bd4b25d,Icfec8fba into main +2d607ee6 sharpyuv: increase precision of gamma<->linear conversion +266cbbc5 sharpyuv: add 32bit version of SharpYuvFilterRow. +9fc12274 CMake: add src to webpinfo includes +7d18f40a CMake: add WEBP_BUILD_WEBPINFO to list of checks for exampleutil +11309aa5 CMake: add WEBP_BUILD_WEBPMUX to list of checks for exampleutil +4bc762f7 CMake: link imageioutil to exampleutil after defined +0d1b9bc4 WEBP_DEP_LIBRARIES: use Threads::Threads +20ef48f0 Merge "sharpyuv: add support for 10/12/16 bit rgb and 10/12 bit yuv." into main +93c54371 sharpyuv: add support for 10/12/16 bit rgb and 10/12 bit yuv. +53cf2b49 normalize WebPValidatePicture declaration w/definition +d3006f4b sharpyuv: slightly improve precision +ea967098 Merge changes Ia01bd397,Ibf3771af into main +11bc8410 Merge changes I2d317c4b,I9e77f6db into main +30453ea4 Add an internal WebPValidatePicture. +6c43219a Some renamings for consistency. +4f59fa73 update .mailmap +e74f8a62 webp-lossless-bitstream-spec,cosmetics: normalize range syntax +5a709ec0 webp-lossless-bitstream-spec,cosmetics: fix code typo +a2093acc webp-lossless-bitstream-spec: add amendment note +86c66930 webp-lossless-bitstream-spec: fix BNF +232f22da webp-lossless-bitstream-spec: fix 'simple code' snippet +44dd765d webp-lossless-bitstream-spec: fix ColorTransform impl +7a7e33e9 webp-lossless-bitstream-spec: fix TR-pixel right border note +86f94ee0 Update lossless spec with Huffman codes. +a3927cc8 sharpyuv.c,cosmetics: fix indent +6c45cef7 Make sure the stride has a minimum value in the importer. +0c8b0e67 sharpyuv: cleanup/cosmetic changes +dc3841e0 {histogram,predictor}_enc: quiet int -> float warnings +a19a25bb Replace doubles by floats in lossless misc cost estimations. +42888f6c Add an option to enable static builds. +7efcf3cc Merge "Fix typo in color constants: Marix -> Matrix" into main +8f4b5c62 Fix typo in color constants: Marix -> Matrix +90084d84 Merge "demux,IsValidExtendedFormat: remove unused variable" into main +ed643f61 Merge changes I452d2485,Ic6d75475 into main +8fa053d1 Rename SharpYUV to SharpYuv for consistency. +99a87562 SharpYuvComputeConversionMatrix: quiet int->float warnings +deb426be Makefile.vc: add sharpyuv_csp.obj to SHARPYUV_OBJS +779597d4 demux,IsValidExtendedFormat: remove unused variable +40e8aa57 Merge "libsharpyuv: add colorspace utilities" into main +01a05de1 libsharpyuv: add colorspace utilities +2de4b05a Merge changes Id9890a60,I376d81e6,I1c958838 into main +b8bca81f Merge "configure.ac: use LT_INIT if available" into main +e8e77b9c Merge changes I479bc487,I39864691,I5d486c2c,I186d13be into main +7e7d5d50 Merge ".gitignore: add Android Studio & VS code dirs" into main +10c50848 normalize label indent +89f774e6 mux{edit,internal}: fix leaks on error +2d3293ad ExUtilInitCommandLineArguments: fix leak on error +ec34fd70 anim_util: fix leaks on error +e4717287 gif2webp: fix segfault on OOM +e3cfafaf GetBackwardReferences: fail on alloc error +a828a59b BackwardReferencesHashChainDistanceOnly: fix segfault on OOM +fe153fae VP8LEncodeStream: fix segfault on OOM +919acc0e .gitignore: add Android Studio & VS code dirs +efa0731b configure.ac: use LT_INIT if available +0957fd69 tiffdec: add grayscale support +e685feef Merge "Make libsharpyuv self-contained by removing dependency on cpu.c" into main +841960b6 Make libsharpyuv self-contained by removing dependency on cpu.c +617cf036 image_dec: add WebPGetEnabledInputFileFormats() +7a68afaa Let SharpArgbToYuv caller pass in an RGB>YUV conversion matrix. +34bb332c man/cwebp.1: add note about crop/resize order +f0e9351c webp-lossless-bitstream-spec,cosmetics: fix some typos +5ccbd6ed vp8l_dec.c,cosmetics: fix a few typos +c3d0c2d7 fix ios build scripts after sharpyuv dep added +d0d2292e Merge "Make libwebp depend on libsharpyuv." into main +03d12190 alpha_processing_neon.c: fix 0x01... typo +d55d447c Make libwebp depend on libsharpyuv. +e4cbcdd2 Fix lossless encoding for MIPS. +924e7ca6 alpha_processing_neon.c: fix Dispatch/ExtractAlpha_NEON +0fa0ea54 Makefile.vc: use /MANIFEST:EMBED +29cc95ce Basic version of libsharpyuv in libwebp, in C. +a30f2190 examples/webpmux.c: fix a couple of typos +66b3ce23 Fix bad overflow check in ReadTIFF() +54e61a38 Markdownify libwebp docs and reorganize them. +b4533deb CMakeLists.txt,cosmetics: break long line +b9d2f9cd quant_enc.c: use WEBP_RESTRICT qualifier +ec178f2c Add progress hook granularity in lossless +26139c73 Rename MAX_COST to MAX_BIT_COST in histogram_enc.c +13b82816 cmake: fix webpmux lib name for cmake linking +88b6a396 webp-container-spec.txt,cosmetics: normalize formatting +6f496540 Merge tag 'v1.2.2' +4074acf8 dsp.h: bump msvc arm64 version requirement to 16.6 +b0a86089 update ChangeLog (tag: v1.2.2) +6db8248c libwebp: Fix VP8EncTokenLoop() progress +827a307f BMP enc: fix the transparency case +db25f1b4 libwebp: Fix VP8EncTokenLoop() progress +286e7fce libwebp: do not destroy jpeg codec twice on error +6e8a4126 libwebp: do not destroy jpeg codec twice on error +faf21968 Merge "BMP enc: fix the transparency case" into main +480cd51d BMP enc: fix the transparency case +9195ea05 update ChangeLog (tag: v1.2.2-rc2) +4acae017 update NEWS +883f0633 man/img2webp.1: update date +567e1f44 Reword img2webp synopsis command line +1b0c15db man/img2webp.1: update date +17bade38 Merge "Reword img2webp synopsis command line" into main +a80954a1 Reword img2webp synopsis command line +f084244d anim_decode: fix alpha blending with big-endian +b217b4ff webpinfo: fix fourcc comparison w/big-endian +ec497b75 Merge "anim_decode: fix alpha blending with big-endian" into main +e4886716 anim_decode: fix alpha blending with big-endian +e3cb052c webpinfo: fix fourcc comparison w/big-endian +a510fedb patch-check: detect duplicated files +f035d2e4 update ChangeLog (tag: v1.2.2-rc1) +7031946a update NEWS +973390b6 bump version to 1.2.2 +abd6664f update AUTHORS +5b7e7930 Merge "add missing USE_{MSA,NEON} checks in headers" into main +02ca04c3 add missing USE_{MSA,NEON} checks in headers +e94716e2 xcframeworkbuild.sh: place headers in a subdir +c846efd8 patch-check: commit subject length check +b6f756e8 update http links +8f5cb4c1 update rfc links +8ea81561 change VP8LPredictorFunc signature to avoid reading 'left' +6b1d18c3 webpmux: fix the -bgcolor description +3368d876 Merge "webpmux: add "-set bgcolor A,R,G,B"" into main +f213abf6 webpinfo: print the number of warnings +50c97c30 webpmux: add "-set bgcolor A,R,G,B" +2c206aaf Remove CMakeLists.txt check in compile.sh +96e3dfef Merge "infra/common.sh: add shard_should_run()" into main +0e0f74b7 infra/common.sh: add shard_should_run() +35b7436a Jenkins scripts port: update shell function comments +21d24b4c webp-container-spec.txt: remove 'experimental' markers +cdcf8902 Merge "Port Jenkins script: compile" into main +dc683cde Jenkins scripts port: static analysis +0858494e Port Jenkins script: compile +c2cf6a93 Jenkins scripts port: android compilation +df0e808f presubmit: Add pylint-2.7 and .pylintrc +676c57db patch-check: shfmt +7bb7f747 patch-check: Add shellcheck +abcd1797 Reformat docstrings and imports +edaf0895 Port Jenkins scripts: compile js +b9622063 Set CheckPatchFormatted flags to fail on diffs +e23cd548 dsp.h: enable NEON w/VS2019+ ARM64 targets +3875c7de CMakeLists.txt: set minimum version to 3.7 +1a8f0d45 Have a hard-coded value for memset in TrellisQuantizeBlock. +93480160 Speed up TrellisQuantizeBlock +45eaacc9 Convert deprecated uint32 to uint32_t. +42592af8 webp,cmake: Remove unnecessary include dirs +e298e05f Add patch-check steps in PRESUBMIT.py +29148919 Merge tag 'v1.2.1' +9ce5843d update ChangeLog (tag: v1.2.1) +d9191588 fuzzer/*: normalize src/ includes +c5bc3624 fuzzer/*: normalize src/ includes +53b6f762 fix indent +d2caaba4 fix indent +731246ba update ChangeLog (tag: v1.2.1-rc2) +d250f01d dsp/*: use WEBP_HAVE_* to determine Init availability +1fe31625 dsp/*: use WEBP_HAVE_* to determine Init availability +3a4d3ecd update NEWS +b2bc8093 bump version to 1.2.1 +e542fc7a update AUTHORS +e0241154 Merge "libwebp/CMake: Add to webp incl" into main +edea6444 libwebp/CMake: Add to webp incl +ece18e55 dsp.h: respect --disable-sse2/sse4.1/neon +a89a3230 wicdec: support alpha from WebP WIC decoder +26f4aa01 Merge "alpha_processing: fix visual studio warnings" into main +8f594663 alpha_processing: fix visual studio warnings +46d844e6 Merge "cpu.cmake: fix compiler flag detection w/3.17.0+" into main +298d26ea Merge changes I593adf92,If20675e7,Ifac68eac into main +a1e5dae0 alpha_processing*: use WEBP_RESTRICT qualifier +327ef24f cpu.cmake: fix compiler flag detection w/3.17.0+ +f70819de configure: enable libwebpmux by default +dc7e2b42 configure: add informational notices when disabling binaries +9df23ddd configure: move lib flag checks before binaries +a2e18f10 Merge "WebPConfig.config.in: correct WEBP_INCLUDE_DIRS" into main +e1a8d4f3 Merge "bit_reader_inl_utils: uniformly apply WEBP_RESTRICT" into main +4de35f43 rescaler.c: fix alignment +0f13eec7 bit_reader_inl_utils: uniformly apply WEBP_RESTRICT +277d3074 Fix size_t overflow in WebPRescalerInit +97adbba5 WebPConfig.config.in: correct WEBP_INCLUDE_DIRS +b60d4603 advanced_api_fuzzer: add extreme config value coverage +72fe52f6 anim_encode.c,cosmetics: normalize indent +116d235c anim_encode: Fix encoded_frames_[] overflow +6f445b3e CMake: set CMP0072 to NEW +b1cf887f define WEBP_RESTRICT for MSVC +3e265136 Add WEBP_RESTRICT & use it in VP8BitReader +f6d29247 vp8l_dec::ProcessRows: fix int overflow in multiply +de3b4ba8 CMake: add WEBP_BUILD_LIBWEBPMUX +7f09d3d1 CMakeLists.txt: rm libwebpmux dep from anim_{diff,dump} +4edea4a6 Init{RGB,YUV}Rescaler: fix a few more int overflows +c9e26bdb rescaler_utils: set max valid scaled w/h to INT_MAX/2 +28d488e6 utils.h: add SizeOverflow() +695bdaa2 Export/EmitRescaledRowsRGBA: fix pointer offset int overflow +685d073e Init{RGB,YUV}Rescaler: fix int overflows in multiplication +d38bd0dd WebPFlipBuffer: fix integer overflow +109ff0f1 utils: allow MALLOC_LIMIT to indicate a max +a2fce867 WebPRescalerImportRowExpand_C: promote some vals before multiply +776983d4 AllocateBuffer: fix int multiplication overflow check +315abbd6 Merge "Revert "Do not use a palette for one color images."" +eae815d0 Merge changes Ica3bbf75,I82f82954 +afbca5a1 Require Emscripten 2.0.18 +3320416b CMakeLists,emscripten: use EXPORTED_RUNTIME_METHODS +29145ed6 Update README instructions for using Emscripten +1f579139 cosmetics: remove use of 'sanity' / 'master' +29b6129c WebPAnimEncoderNewInternal: remove some unnecessary inits +b60869a1 Revert "Do not use a palette for one color images." +6fb4cddc demux: move padded size calc post unpadded validation +05b72d42 vp8l_enc.c: normalize index types +b6513fba Do not use a palette for one color images. +98bbe35b Fix multi-threading with palettes. +b1674240 Add modified Zeng's method to palette sorting. +88c90c45 add CONTRIBUTING.md +6a9916d7 WebPRescalerInit: add missing int64_t promotion +b6cf52d5 WebPIoInitFromOptions: treat use_scaling as a bool +3b12b7f4 WebPIoInitFromOptions: treat use_cropping as a bool +595fa13f add WebPCheckCropDimensions() +8fdaecb0 Disable cross-color when palette is used. +8933bac2 WebPIoInitFromOptions: respect incoming bypass_filtering val +7d416ff0 webpdec,cosmetics: match error text to function call +ec6cfeb5 Fix typo on WebPPictureAlloc() in README +7e58a1a2 *.cmake: add license header +5651a6b2 cmake: fix .so versioning +25ae67b3 xcframeworkbuild.sh: add arm64 simulator target +5d4ee4c3 cosmetics: remove use of the term 'dummy' +01b38ee1 faster CollectColorXXXTransforms_SSE41 +652aa344 Merge "Use BitCtz for FastSLog2Slow_C" +0320e1e3 add the missing default BitsCtz() code +8886f620 Use BitCtz for FastSLog2Slow_C +fae41617 faster CombinedShannonEntropy_SSE2 +5bd2704e Introduce the BitCtz() function. +fee64287 Merge "wicdec,icc: treat unsupported op as non-fatal" +33ddb894 lossless_sse{2,41}: remove some unneeded includes +b27ea852 wicdec,icc: treat unsupported op as non-fatal +b78494a9 Merge "Fix undefined signed shift." +e79974cd Fix undefined signed shift. +a8853394 SSE4.1 versions of BGRA to RGB/BGR color-space conversions +a09a6472 SSE4.1 version of TransformColorInverse +401da22b Merge "pngdec: check version before using png_get_chunk_malloc_max" +26907822 pngdec: check version before using png_get_chunk_malloc_max +06c1e72e Code cleanup +8f0d41aa Merge changes Id135bbf4,I99e59797 +373eb170 gif2webp: don't store loop-count if there's only 1 frame +759b9d5a cmake: add WEBP_USE_THREAD option +926ce921 cmake: don't install binaries from extras/ +9c367bc6 WebPAnimDecoderNewInternal: validate bitstream before alloc +47f64f6e filters_sse2: import Chromium change +cc3577e9 fuzzer/*: use src/ based include paths +004d77ff Merge tag 'v1.2.0' +fedac6cc update ChangeLog (tag: v1.2.0-rc3, tag: v1.2.0) +170a8712 Fix check_c_source_compiles with pthread. +ceddb5fc Fix check_c_source_compiles with pthread. +85995719 disable CombinedShannonEntropy_SSE2 on x86 +289757fe TiffDec: enforce stricter mem/dimension limit on tiles +8af7436f Merge "{ios,xcframework}build.sh: make min version(s) more visible" into 1.2.0 +e56c3c5b pngdec: raise memory limit if needed +8696147d pngdec: raise memory limit if needed +13b8e9fe {ios,xcframework}build.sh: make min version(s) more visible +a9225410 animdecoder_fuzzer: fix memory leak +d6c2285d update gradle to 6.1.1 +8df77fb1 animdecoder_fuzzer: fix memory leak +52ce6333 update NEWS +28c49820 bump version to 1.2.0 +7363dff2 webp/encode.h: restore WEBP_ENCODER_ABI_VERSION to v1.1.0 +826aafa5 update AUTHORS +63258823 animdecoder_fuzzer: validate canvas size +9eb26381 CMake: remove duplicate "include(GNUInstallDirs)" +2e7bed79 WebPPicture: clarify the ownership of user-owned data. +cccf5e33 webpmux: add an '-set loop ' option +c9a3f6a1 Merge changes Ie29f9867,I289c54c4 +319f56f1 iosbuild.sh: sync some aspects of xcframeworkbuild.sh +e8e8db98 add xcframeworkbuild.sh +ae545534 dsp.h: allow config.h to override MSVC SIMD autodetection +fef789f3 Merge "cmake: fix per-file assembly flags" +fc14fc03 Have C encoding predictors use decoding predictors. +7656f0b3 README,cosmetics: fix a couple typos +d2e245ea cmake: disable webp.js if WEBP_ENABLE_SIMD=1 +96099a79 cmake: fix per-file assembly flags +5abb5582 Merge "cmake: fix compilation w/Xcode generator" +8484a120 cmake: fix compilation w/Xcode generator +d7bf01c9 Merge changes Ifcae0f38,Iee2d7401 +36c81ff6 WASM-SIMD: port 2 patches from rreverser@'s tree +988b02ab Merge "Couple of fixes to allow SIMD on Emscripten" +26faf770 wicdec: fail with animated images +ab2d08a8 [cd]webp: document lack of animated webp support +52273943 Couple of fixes to allow SIMD on Emscripten +8870ba7f Fix skia bug #10952 +4b3c6953 Detect if StoreFrame read more than anmf_payload_size bytes +17fd4ba8 webp/decode.h,cosmetics: normalize 'flip' comment +411d3677 remove some unreachable break statements +3700ffd7 WebPPictureHasTransparency: remove unreachable return +83604bf3 {animencoder,enc_dec}_fuzzer: convert some abort()s to returns +eb44119c Merge changes I8ae09473,I678c8b1e +9f6055fc fuzz_utils.h: rename max() to Max() +695788e7 fuzz_utils.h: make functions WEBP_INLINE +906c1fcd make ImgIoUtilReadFile use WebPMalloc instead of malloc +8cb7e536 rename demux_api_fuzzer.c -> mux_demux_api_fuzzer.c +443db47d add animdecoder_fuzzer.cc +36a6eea3 Merge "import fuzzers from oss-fuzz/chromium" +ec5f12c1 Makefile.vc: remove deprecated /Gm option +64425a08 picture_tools_enc: fix windows build warning +bd94090a import fuzzers from oss-fuzz/chromium +cf847cba use WEBP_DSP_INIT_FUNC for Init{GammaTables*,GetCoeffs} +55a080e5 Add WebPReplaceTransparentPixels() in dsp +84739717 GetBackgroundColorGIF: promote to uint32_t before << 24 +def64e92 cwebp: Fix -print_psnr for near_lossless +cf2f88b3 Add palette and spatial for q >= 75 and -m 5 +f0110bae Add no-color cache configuration to the cruncher +749a8b99 Better estimate of the cache cost. +4f9f00cc Use spatial predictors on top of palette no matter what. +7658c686 Add spatial prediction on top of palette in cruncher. +133ff0e3 webp_js: force WASM=0 option explicitly +e3c259a2 Fix integer overflow in EmitFancyRGB. +b3ff0bde man/{gif2,img2}webp,webpmux: normalize some wording +f9b30586 fix ABI breakage introduced by 6a0ff358 +1d58dcfc README.webp_js: update note about emscripten version +44070266 README.webp_js: s/fastcomp/upstream/ +2565fa8f README.webp_js: update cmake command +47309ef5 webp: WEBP_OFFSET_PTR() +687ab00e DC{4,8,16}_NEON: replace vmovl w/vaddl +1b92fe75 DC16_NEON,aarch64: use vaddlv +53f3d8cf dec_neon,DC8_NEON: use vaddlv instead of movl+vaddv +27d08240 Fix integer overflow in WebPAnimDecoderGetNext() +69776e38 Merge "remove call to MBAnalyzeBestIntra4Mode for method >= 5" +a99078c1 remove call to MBAnalyzeBestIntra4Mode for method >= 5 +22e404cc CMakeLists.txt: fix set(CACHE) argument order +71690b52 fix MSVC warning +6a0ff358 Enc: add a qmin / qmax range for quality factor +0fa56f30 Merge tag 'v1.1.0' +6cf504d0 PNM decoding: handle max_value != 255 +d7844e97 update ChangeLog (tag: v1.1.0-rc2, tag: v1.1.0) +7f006436 Makefile.vc: fix webp_quality.exe link +cf047e83 Makefile.vc: fix webp_quality.exe link +c074c653 update NEWS +30f09551 bump version to 1.1.0 +a76694a1 update AUTHORS +6e3ef7b3 extras: fix WEBP_SWAP_16BIT_CSP check +47178dbd extras: add WebPUnmultiplyARGB() convenience function +22cbae33 idec_dec: fix 0 offset of NULL pointer +290dd0b4 muxread: fix 0 offset of NULL pointer +0df474ac Merge "lossless_(enc_|)sse2: avoid offsetting a NULL pointer" +c6b75a19 lossless_(enc_|)sse2: avoid offsetting a NULL pointer +295e5e38 fix UBSAN warning +e2575e05 DC8_NEON,aarch64: use vaddv +b0e09e34 dec_neon: Fix build failure under some toolchains +cf0e903c dsp/lossless: Fix non gcc ARM builds +bb7bc40b Remove ubsan errors. +78881b76 CMake: fix GLUT library link +9f750f7a cmake: fix BUILD_SHARED_LIBS build on mac +17850e74 libwebp: Remove char-subscripts warning in pnmdec.c +2fa2552d Merge "Expose WebPMalloc() in addition to WebPFree()" +a4df4aae Expose WebPMalloc() in addition to WebPFree() +853ea3d8 imageio/tiff: Return error before allocating bad tile size +af650c0b Fix a Wxor-used-as-pow false positive +601ef17c libwebp.py: update to swig 3.0.12 +0e48d889 bugfix: last alpha rows were incorrectly decoded +24d2ccb4 webp: Fix imageio ReadPNM() TUPLTYPE +fab8f9cf cosmetics: normalize '*' association +94138e0e update .gitignore +0fe1a89d update ChangeLog (tag: v1.0.3-rc1, tag: v1.0.3) +2ad0916d update NEWS +1287362b bump version to 1.0.3 +7b968cc2 update AUTHORS +9d6988f4 Fix the oscillating prediction problem at low quality +312f74d0 makefile.unix: allow *_LIBS to be overridden w/EXTRA_LIBS +92dbf237 filters_sse2,cosmetics: shorten some long lines +a277d197 filters_sse2.c: quiet integer sanitizer warnings +804540f1 Fix cpufeatures in CMake. +bf00c15b Add CMake option for bittrace. +a788b498 filters_sse2.c: quiet integer sanitizer warnings +e6a92c5e filters.c: quiet integer sanitizer warnings +ec1cc40a lossless.c: remove U32 -> S8 conversion warnings +1106478f remove conversion U32 -> S8 warnings +812a6b49 lossless_enc: fix some conversion warning +4627c1c9 lossless_enc,TransformColorBlue: quiet uint32_t conv warning +c84673a6 lossless_enc_sse{2,41}: quiet signed conv warnings +776a7757 dec_sse2: quiet signed conv warnings +bd39c063 Merge "thread_utils: release mutex before signaling" +0550576f Merge "(alpha_processing,enc}_sse2: quiet signed conv warnings" +6682f2c4 thread_utils: release mutex before signaling +e78dea75 (alpha_processing,enc}_sse2: quiet signed conv warnings +9acf18ba iosbuild.sh: add WebP{Demux,Mux}.framework +b9be7e65 vwebp: remove the -fit option (and make it default) +1394a2bb Merge "README.webp_js: update Emscripten.cmake note" +dd3e7f8a README.webp_js: update Emscripten.cmake note +32cf8801 predictor_enc,GetBestGreenRedToBlue: quiet implicit conv warnings +e1c8acb5 Merge "vwebp: add a -fit option" +cbd23dd5 vwebp: add a -fit option +2e672351 bit_writer_utils,Flush: quiet implicit conversion warnings +1326988d swig: update libwebp_python_wrap.c +0e7f8548 update generated swig files +17ed1438 Merge "PutLE{16,24}: quiet implicit conversion warnings" +24686538 PutLE{16,24}: quiet implicit conversion warnings +153bb3a0 fix some clang-7 warnings: +ab2dc893 Rescaler: fix rounding error +aa65f89a HistogramCombineStochastic: fix free of uninit value +af0bac64 Merge "encode.h: mention 'exact' default in WebPEncodeLossless*" +6d2e11ec encode.h: mention 'exact' default in WebPEncodeLossless* +8c3f04fe AndroidCPUInfo: reorder terms in conditional +fcfd9c71 BitTrace: if BITTRACE is > 0, record and print syntax bits used +067031ea Speedups for unused Huffman groups. +01ac46ba libwebp: Display "libjpeg error:" in imageio/jpegdec +d9a662e1 WebPRescalerGetScaledDimensions: round scaled dimension up +62eb3f08 libwebp: Fix missing '{' in README +e05f785a Merge "unicode,INIT_WARGV: add missing cast" +63c9a69f tag the VP8LHashPix() function for potential uint roll-over +2b7214ab unicode,INIT_WARGV: add missing cast +bf424b46 tag the GetPixPairHash64() function for potential uint roll-over +7d05d6ca Have the color cache computation be u32-bit only. +6bcf8769 Remove BINARYEN_METHOD in wasm settings. +2b98df90 update ChangeLog (tag: v1.0.2-rc1, tag: v1.0.2) +61e372b7 update NEWS +7ae658a0 bump version to 1.0.2 +51c4907d update AUTHORS +666bd6c6 man/cwebp.1: refine near-lossless text +561cdce5 Clarify the doc about GetFeatures. +aec2cf02 near_lossless: fix fuzzing-detected integer overflow +928a75de webp: Fix VP8LBitWriterClone() bug +5173d4ee neon IsFlat +5b081219 IsFlat: inline when possible +381b7b54 IsFlat: use int for thresh +6ed15ea1 fix unprobable leak in webp_sdl.c +22bbb24e Merge "IsFlat: return int" +8b3fb238 Merge tag 'v1.0.1' +f435de95 IsFlat: return int +41521aed utils.h: only define WEBP_NEED_LOG_TABLE_8BIT when needed +9f4d4a3f neon: GetResidualCost +0fd7514b neon: SetResidualCoeffs +f95a996c Simpler histogram clustering. +e85d3313 update ChangeLog (tag: v1.0.1-rc2, tag: v1.0.1) +fa8210e4 Fix pair update in stochastic entropy merging. +fd198f73 add codereview.settings +825389ac README.mux: add a reference to the AnimDecoder API +3be698c3 CMake: fix webp_js compilation +485ff86f Fix pair update in stochastic entropy merging. +4cd0582d CMake: fix webp_js compilation +4cbb4caf update NEWS +f5a5918d bump version to 1.0.1 +d61385db Speed-up: Make sure we only initialize histograms when needed. +6752904b Speed-up: Make sure we only initialize histograms when needed. +0c570316 update AUTHORS +301a2dda img2webp: add help note about arguments from a file +f0abab92 Speedups for empty histograms. +f2dfd925 Split HistogramAdd to only have the high level logic in C. +06b7bc7d Fix compilation on windows and clang-cl+ninja. +b6284d82 img2webp: add help note about arguments from a file +decf6f6b Speedups for empty histograms. +dea3e899 Split HistogramAdd to only have the high level logic in C. +632798ae Merge "Fix compilation on windows and clang-cl+ninja." +dc1a9518 Merge "libwebp: Unicode command tools on Windows" +9cf9841b libwebp: Unicode command tools on Windows +98179495 remove some minor TODOs +a376e7b9 Fix compilation on windows and clang-cl+ninja. +cbf82cc0 Remove AVX2 files. +5030e902 Merge "TIFF decoder: remove unused KINV definition" +ac543311 Remove a few more useless #defines +123d3306 TIFF decoder: remove unused KINV definition +ef1094b0 Merge "- install pkg-config files during the CMake build" +b911fbc9 libwebp: Remove duplicate GIFDisplayError in anim_util +eee00b66 - install pkg-config files during the CMake build +ac3ec8c9 Merge "Clean-up the common sources in dsp." +3e13da7b Clean-up the common sources in dsp. +5c395f1d libwebp: cmake-format all +e7a69729 libwebp: Add extras targets in CMakeLists.txt +e52485d6 libwebp: Rename macros in webpmux.c +92dc0f09 clean-up MakeInputImageCopy() +39952de2 VP8IteratorImport: add missing 'const' +382af7a2 clean-up WebPBlendAlpha +14d020f6 libwebp: Use ExUtilGet*() in anim_diff +0d92ff25 libwebp: remove useless variable in gif2webp +556cb1b4 Merge "CMake: Set WEBP_BUILD_GIF2WEBP to off" +da26ee49 CMake: Set WEBP_BUILD_GIF2WEBP to off +b2a867c0 cwebp: Don't premultiply during -resize if -exact +637141bc pngdec: fix build w/libpng < 1.4.x +bc5092b1 pngdec: set memory functions +50d8345a Fix CMake math library. +6aa3e8aa Fix math library on Visual Studio. +d71df4e2 Fix math library finding in CMake. +de08d727 cosmetics: normalize include guard comment +009562b4 vwebp: Fix bug when Dispose then NoBlend frames +423f2579 Fix up CMake to create targets. +907208f9 Wait for all threads to be done in DecodeRemaining. +4649b3c4 vwebp: Add background color display option +78ad57a3 Fix bad glClearColor parameters +da96d8d9 Allow for a non-initialized alpha decompressor in DoRemap. +2563db47 fix rescaling rounding inaccuracy +211f37ee fix endian problems in pattern copy +5f0f5c07 Make sure partition #0 is read before VP8 data in IDecode. +de98732b fix GetColorf() bug +4338cd36 misc fixes in libwebpmux +e00af13e fix signatures after a9ceda7ff1 +a9ceda7f Speed-up chunk list operations. +2281bbf6 Merge "Better handling of bogus Huffman codes." +39cb9aad Better handling of bogus Huffman codes. +89cc9d37 Merge "fix read-overflow while parsing VP8X chunk" +95fd6507 fix read-overflow while parsing VP8X chunk +9e729fe1 Fix VP8IoTeardownHook being called twice on worker sync failure +29fb8562 Merge "muxread,anmf: fail on multiple image chunks" +eb82ce76 muxread,anmf: fail on multiple image chunks +1344a2e9 fix alpha-filtering crash when image width is larger than radius +be738c6d muxread,ChunkVerifyAndAssign: validate chunk_size +2c70ad76 muxread,CreateInternal: fix riff size checks +569001f1 Fix for thread race heap-use-after-free +c56a02d9 Android.mk: use LOCAL_EXPORT_C_INCLUDES w/public libs +15795596 CMakeLists.txt,cosmetics: normalize if() formatting +1a44c233 Merge "cmake: add support for webpmux" +e9569ad7 Merge "configure,*am,cosmetics: s/WANT_/BUILD_/" +35c7de6f cmake: add support for webpmux +0f25e61c WebpToSDL(): fix the return value in case of error +5d8985de configure,*am,cosmetics: s/WANT_/BUILD_/ +895fd28f Merge "man/Makefile.am: add img2webp.1" +5cf3e2af man/Makefile.am: add img2webp.1 +2a9de5b9 Add build rules for anim_diff & anim_dump utils. +71ed73cf fix invalid check for buffer size +af0e4fbb gif2webp: fix transcode of loop count=65535 +dce5d764 Limit memory allocation when reading invalid Huffman codes. +f9df0081 Merge "cmake: quiet glut deprecation warnings on OS X" +dc39b16f webpmux.1: correct grammar +c7aa1264 cwebp.c: fix a missing \n +53aa51e9 Merge tag 'v1.0.0' +698b8844 update ChangeLog (tag: v1.0.0) +8d510751 webp-container-spec: correct frame duration=0 note +e6b2164e vwebp: Copy Chrome's behavior w/frame duration == 0 +094b3b28 cmake: quiet glut deprecation warnings on OS X +71c39a06 webp-container-spec: correct frame duration=0 note +fd3d5756 vwebp: Copy Chrome's behavior w/frame duration == 0 +b0c966fb Build vwebp from CMake. +d20b7707 update ChangeLog (tag: v1.0.0-rc3) +0d5fad46 add WEBP_DSP_INIT / WEBP_DSP_INIT_FUNC +d77bf512 add WEBP_DSP_INIT / WEBP_DSP_INIT_FUNC +c1cb86af fix 16b overflow in SSE2 +e577feb7 makefile.unix: add DEBUG flag for compiling w/ debug-symbol +99be34b3 cwebp,get_disto: fix bpp output +e122e511 cwebp,get_disto: fix bpp output +f5565ca8 cmake: Make sure we use near-lossless by default. +d898dc14 fix bug in WebPImport565: alpha value was not set +1c8f358d Fix CMake with WASM. +a0215fb7 webp_js: fix webp_js demo html +882784b0 update ChangeLog (tag: v1.0.0-rc2) +2f930e08 Revert "Use proper targets for CMake." +8165e8fb Use proper targets for CMake. +3f157dd5 Remove some very hard TODOs. +abb47760 Merge "Use proper targets for CMake." +cd758a17 {de,}mux/Makefile.am: add missing headers +e155dda0 Use proper targets for CMake. +b892b8ba makefile.unix,dist: use ascii for text output +64a57d05 add -version option to anim_dump,anim_diff and img2webp +994be82d Merge "Remove some very hard TODOs." +4033e1d7 Remove some very hard TODOs. +fc1b8e3a webp_js: fix webp_js demo html +15aa48d9 update ChangeLog (tag: v1.0.0-rc1) +e607dabc update AUTHORS +38410c08 [CFI] Remove function pointer casts +978eec25 [CFI] Remove function pointer casts +c57b2736 bump version to 1.0.0 +cba28853 update NEWS +c909d531 Merge "remove some deprecation warning on MacOSX" +217443c7 remove some deprecation warning on MacOSX +b672bdfa configure: quiet glut deprecation warnings on OS X +daa9fcaf configure: use sdl-config if available +dd174cae Merge "imagedec: support metadata reading for WebP image decoding" +641cedcc imagedec: support metadata reading for WebP image decoding +065b2ce1 anim_diff: add a couple missing newlines in Help() +c4cc1147 Merge "gif2webp: force low duration frames to 100ms" +09333097 gif2webp: force low duration frames to 100ms +e03f0ec3 sharp_yuv: use 14b fixed-point precision for gamma +b2db361c image_enc,WebPWritePNG: move locals after setjmp +74e82ec6 Merge "WebPPictureDistortion: fix big-endian results order" +645d04ca Merge "cwebp,get_disto: report bpp" +120f58c3 Merge "lossless*sse2: improve non-const 16-bit vector creation" +a7fe9412 WebPPictureDistortion: fix big-endian results order +e26fe066 cwebp,get_disto: report bpp +9df64e28 Merge changes Id5b4a1a4,Ia20ce844 +8043504f lossless*sse2: improve non-const 16-bit vector creation +1e3dfc48 Import: extract condition from loop +3b07d327 Import,RGBA: fix for BigEndian import +551948e4 Remove unused argument in VP8LBitsEntropy. +3005237a ReadWebP: fix for big-endian +499c395a Merge "anim_diff: expose the -max_diff option" +f69dcd69 Merge "remove WEBP_EXPERIMENTAL_FEATURES" +07d884d5 anim_diff: expose the -max_diff option +f4dd9256 remove WEBP_EXPERIMENTAL_FEATURES +94a8377b extract the command-line parsing helpers to example_util +fc09e6e2 PNM decoder: prevent unsupported depth=2 PAM case. +6de58603 MIPS64: Fix defined-but-not-used errors with WEBP_REDUCE_CSP +cbde5728 gif2webp: add support for reading from stdin +cf1c5054 Add an SSE4 version of some lossless color transforms. +45a8b5eb Fix lint error with man page. +cff38e8f Merge "PNG decoder: handle gAMA chunk" +59cb1a48 Merge "enable dc error-diffusion always" +78318b30 PNG decoder: handle gAMA chunk +664c21dd Merge "remove some TODOs" +815652de enable dc error-diffusion always +aec45cec remove some TODOs +5715dfce fix block-count[] increment in case of large image +c2d04f3e enable DC error-diffusion always for multi-pass +96bf07c5 use DC error diffusion for U/V at low-quality +1c59020b fix missing sse41 targets in makefile.unix +7a8e814b cosmetics: s/color_space/colorspace/ +05f6fe24 upsampling: rm asserts w/REDUCE_CSP+OMIT_C_CODE +b4cf5597 Merge "Upsampling SSE2/SSE4 speedup." +ccbeb32c Makefile.vc: add missing sse41 files +55403a9a Upsampling SSE2/SSE4 speedup. +807b53c4 Implement the upsampling/yuv functions in SSE41 +84101a81 Fix wasm WebP compilation +8bebd2a3 fix warning on MSVC +a7f93fe3 webpmux: allow reading argument from a file +b69f18a7 gif2webp.1: fix -loop_compatibility layout +72d530c0 Merge "fix lossless decoding w/WEBP_REDUCE_SIZE" +296c7dc4 fix lossless decoding w/WEBP_REDUCE_SIZE +0d5d029c Merge "ImgIoUtilReadFile: fix file leak upon error" +ae568ce7 ImgIoUtilReadFile: fix file leak upon error +796b5a8a Merge tag 'v0.6.1' +6b7a95fd update ChangeLog (tag: v0.6.1) +f66955de WEBP_REDUCE_CSP: restrict colorspace support +1af0df76 Merge "WEBP_REDUCE_CSP: restrict colorspace support" +6de20df0 WEBP_REDUCE_CSP: restrict colorspace support +a289d8e7 update ChangeLog (tag: v0.6.1-rc2) +c10a493c vwebp: disable double buffering on windows & mac +0d4466c2 webp_to_sdl.c: fix file mode +1b27bf8b WEBP_REDUCE_SIZE: disable all rescaler code +126be109 webpinfo: add -version option +0df22b9e WEBP_REDUCE_SIZE: disable all rescaler code +9add62b5 bump version to 0.6.1 +d3e26144 update NEWS +2edda639 README: add webpinfo section +9ca568ef Merge "right-size some tables" +31f1995c Merge "SSE2 implementation of HasAlphaXXX" +a80c46bd SSE2 implementation of HasAlphaXXX +083507f2 right-size some tables +2e5785b2 anim_utils.c: remove warning when !defined(WEBP_HAVE_GIF) +b299c47e add WEBP_REDUCE_SIZE +f593d71a enc: disable pic->stats/extra_info w/WEBP_DISABLE_STATS +541179a9 Merge "predictor_enc: fix build w/--disable-near-lossless" +5755a7ec predictor_enc: fix build w/--disable-near-lossless +eab5bab7 add WEBP_DISABLE_STATS +8052c585 remove some petty TODOs from vwebp. +c245343d move LOAD8x4 and STORE8x2 closer to their use location +b9e734fd dec,cosmetics: normalize function naming style +c188d546 dec: harmonize function suffixes +28c5ac81 dec_sse41: harmonize function suffixes +e65b72a3 Merge "introduce WebPHasAlpha8b and WebPHasAlpha32b" +b94cee98 dec_sse2: remove HE8uv_SSE2 +44a0ee3f introduce WebPHasAlpha8b and WebPHasAlpha32b +aebf59ac Merge "WebPPictureAllocARGB: align argb allocation" +c184665e WebPPictureAllocARGB: align argb allocation +3daf7509 WebPParseHeaders: remove obsolete animation TODO +80285d97 cmake: avoid security warnings under msvc +650eac55 cmake: don't set -Wall with MSVC +c462cd00 Remove useless code. +01a98217 Merge "remove WebPWorkerImpl declaration from the header" +3c49fc47 Merge "thread_utils: fix potentially bad call to Execute" +fde2782e thread_utils: fix potentially bad call to Execute +2a270c1d remove WebPWorkerImpl declaration from the header +f1f437cc remove mention of 'lossy-only parameters' from the doc +3879074d Merge "WebPMemToUint32: remove ptr cast to int" +04b029d2 WebPMemToUint32: remove ptr cast to int +b7971d0e dsp: avoid defining _C functions w/NEON builds +6ba98764 webpdec: correct alloc size check w/use_argb +5cfb3b0f normalize include guards +f433205e Merge changes Ia17c7dfc,I75423abb,Ia2f716b4,I161caa14,I4210081a, ... +8d033b14 {dec,enc}_neon: harmonize function suffixes x2 +0295e981 upsampling_neon: harmonize function suffixes +d572c4e5 yuv_neon: harmonize function suffixes +ab9c2500 rescaler_neon: harmonize function suffixes +93e0ce27 lossless_neon: harmonize function suffixes +22fbc50e lossless_enc_neon: harmonize function suffixes +447875b4 filters_neon,cosmetics: fix indent +e51bdd43 remove unused VP8TokenToStats() function +785da7ea enc_neon: harmonize function suffixes +bc1a251f dec_neon: harmonize function suffixes +61e535f1 dsp/lossless: workaround gcc-4.8 bug on arm +68b2eab7 cwebp: fix alpha reporting w/lossless & metadata +30042faa WebPDemuxGetI: add doc details around WebPFormatFeature +0a17f471 Merge "WIP: list includes as descendants of the project dir" +a4399721 WIP: list includes as descendants of the project dir +08275708 Merge "Make sure we reach the full range for alpha blending." +d361a6a7 yuv_sse2: harmonize function suffixes +6921aa6f upsampling_sse2: harmonize function suffixes +08c67d3e ssim_sse2: harmonize function suffixes +582a1b57 rescaler_sse2: harmonize function suffixes +2c1b18ba lossless_sse2: harmonize function suffixes +0ac46e81 lossless_enc_sse2: harmonize function suffixes +bc634d57 enc_sse2: harmonize function suffixes +bcb7347c dec_sse2: harmonize function suffixes +e14ad93c Make sure we reach the full range for alpha blending. +7038ca8d demux,StoreFrame: restore hdr size check to min req +fb3daad6 cpu: fix ssse3 check +be590e06 Merge "Fix CMake redefinition for HAVE_CPU_FEATURES_H" +35f736e1 Fix CMake redefinition for HAVE_CPU_FEATURES_H +a5216efc Fix integer overflow warning. +a9c8916b decode.h,WebPIDecGetRGB: clarify output ptr validity +3c74c645 gif2webp: handle 1-frame case properly + fix anim_diff +c7f295d3 Merge "gif2webp: introduce -loop_compatibility option" +b4e04677 gif2webp: introduce -loop_compatibility option +f78da3de add LOCAL_CLANG_PREREQ and avoid WORK_AROUND_GCC w/3.8+ +01c426f1 define WEBP_USE_INTRINSICS w/gcc-4.9+ +8635973d use sdl-config (if available) to determine the link flags +e9459382 use CPPFLAGS before CFLAGS +4a9d788e Merge "Android.mk,mips: fix clang build with r15" +4fbdc9fb Android.mk,mips: fix clang build with r15 +a80fcc4a ifdef code not used by Chrome/Android. +3993af12 Fix signed integer overflows. +f66f94ef anim_dump: small tool to dump frames from animated WebP +6eba857b Merge "rationalize the Makefile.am" +c5e34fba function definition cleanup +3822762a rationalize the Makefile.am +501ef6e4 configure style fix: animdiff -> anim_diff +f8bdc268 Merge "protect against NULL dump_folder[] value in ReadAnimatedImage()" +23bfc652 protect against NULL dump_folder[] value in ReadAnimatedImage() +8dc3d71b cosmetics,ReadAnimatedWebP: correct function comment +5bd40066 Merge changes I66a64a0a,I4d2e520f +7945575c cosmetics,webpinfo: remove an else after a return +8729fa11 cosmetics,cwebp: remove an else after a return +f324b7f9 cosmetics: normalize fn proto & decl param names +869eb369 CMake cleanups. +289e62a3 Remove declaration of unimplemented VP8ApplyNearLosslessPredict +20a94186 pnmdec,PAM: validate depth before calculating bytes_per_px +34130afe anim_encode: fix integer overflow +42c79aa6 Merge "Encoder: harmonize function suffixes" +b09307dc Encoder: harmonize function suffixes +bed0456d Merge "SSIM: harmonize the function suffix" +54f6a3cf lossless_sse2.c: fix some missed suffix changes +088f1dcc SSIM: harmonize the function suffix +86fc4dd9 webpdec: use ImgIoUtilCheckSizeArgumentsOverflow +08ea9ecd imageio: add ability restrict max image size +6f9daa4a jpegdec,ReadError: fix leaks on error +a0f72a4f VP8LTransformColorFunc: drop an non-respected 'const' from the signature. +8c934902 Merge "Lossess dec: harmonize the function suffixes" +622242aa Lossess dec: harmonize the function suffixes +1411f027 Lossless Enc: harmonize the function suffixes +24ad2e3c add const to two variables +46efe062 Merge "Allow the lossless cruncher to work for alpha." +8c3f9a47 Speed-up LZ77. +1aef4c71 Allow the lossless cruncher to work for alpha. +b8821dbd Improve the box LZ77 speed. +7beed280 add missing ()s to macro parameters +6473d20b Merge "fix Android standalone toolchain build" +dcefed95 Merge "build.gradle: fix arm64 build" +0c83a8bc Merge "yuv: harmonize suffix naming" +c6d1db4b fix Android standalone toolchain build +663a6d9d unify the ALTERNATE_CODE flag usage +73ea9f27 yuv: harmonize suffix naming +c71b68ac build.gradle: fix arm64 build +c4568b47 Rescaler: harmonize the suffix naming +6cb13b05 Merge "alpha_processing: harmonize the naming suffixes to be _C()" +83a3e69a Merge "simplify WEBP_EXTERN macro" +7295fde2 Merge "filters: harmonize the suffixes naming to _SSE2(), _C(), etc." +8e42ba4c simplify WEBP_EXTERN macro +331ab34b cost*.c: harmonize the suffix namings +b161f670 filters: harmonize the suffixes naming to _SSE2(), _C(), etc. +dec5e4d3 alpha_processing: harmonize the naming suffixes to be _C() +6878d427 fix memory leak in SDL_Init() +461ae555 Merge "configure: fix warnings in sdl check" +62486a22 configure: test for -Wundef +92982609 dsp.h: fix -Wundef w/__mips_dsp_rev +0265cede configure: fix warnings in sdl check +88c73d8a backward_references_enc.h: fix WINDOW_SIZE_BITS check +4ea49f6b rescaler_sse2.c: fix WEBP_RESCALER_FIX -> _RFIX typo +1b526638 Clean-up some CMake +87f57a4b Merge "cmake: fix gif lib detection when cross compiling" +b34a9db1 cosmetics,dec_sse2: remove some redundant comments +471c5755 cmake: fix gif lib detection when cross compiling +c793417a cmake: disable gif2webp if gif lib isn't found +dcbc1c88 cmake: split gif detection from IMG deps +66ad84f0 Merge "muxread: remove unreachable code" +50ec3ab7 muxread: remove unreachable code +7d67a164 Lossy encoding: smoothen transparent areas to improve compression +e50650c7 Merge "fix signature for DISABLE_TOKEN_BUFFER compilation" +671d2567 fix signature for DISABLE_TOKEN_BUFFER compilation +d6755580 cpu.cmake: use unique flag to test simd disable flags +28914528 Merge "Remove the argb* files." +8acb4942 Remove the argb* files. +3b62347b README: correct cmake invocation note +7ca0df13 Have the SSE2 version of PackARGB use common code. +7b250459 Merge "Re-use the transformed image when trying several LZ77 in lossless." +e132072f Re-use the transformed image when trying several LZ77 in lossless. +5d7a50ef Get code to compile in C++. +7b012987 configure: test for -Wparentheses-equality +f0569adb Fix man pages for multi-threading. +f1d5a397 multithread cruncher: only copy stats when picture->stats != NULL +f8c2ac15 Multi-thread the lossless cruncher. +a88c6522 Merge "Integrate a new LZ77 looking for matches in the neighborhood of a pixel only." +8f6df1d0 Unroll Predictors 10, 11 and 12. +355c3d1b Integrate a new LZ77 looking for matches in the neighborhood of a pixel only. +a1779a01 Refactor LZ77 handling in preparation for a new method. +67de68b5 Android.mk/build.gradle: fix mips build with clang from r14b +f209a548 Use the plane code and not the distance when computing statistics. +b903b80c Split cost-based backward references in its own file. +498cad34 Cosmetic changes in backward reference. +e4eb4587 lossless, VP8LTransformColor_C: make sure no overflow happens with colors. +af6deaff webpinfo: handle alpha flag mismatch +7caef29b Fix typo that creeped in. +39e19f92 Merge "near lossless: fix unsigned int overflow warnings." +9bbc0891 near lossless: fix unsigned int overflow warnings. +e1118d62 Merge "cosmetics,FindClosestDiscretized: use uint in mask creation" +186bc9b7 Merge "webpinfo: tolerate ALPH+VP8L" +b5887297 cosmetics,FindClosestDiscretized: use uint in mask creation +f1784aee near_lossless,FindClosestDiscretized: use unsigned ops +0d20abb3 webpinfo: tolerate ALPH+VP8L +972104b3 webpmux: tolerate false positive Alpha flag +dd7e83cc tiffdec,ReadTIFF: ensure data_size is < tsize_t max +d988eb7b tiffdec,MyRead: quiet -Wshorten-64-to-32 warning +dabda707 webpinfo: add support to parse Alpha bitstream +4c117643 webpinfo: correct background color output, BGRA->ARGB +defc98d7 Doc: clarify the role of quality in WebPConfig. +d78ff780 Merge "Fix code to compile with C++." +c8f14093 Fix code to compile with C++. +497dc6a7 pnmdec: sanitize invalid header output +d78e5867 Merge "configure: test for -Wconstant-conversion" +481e91eb Merge "pnmdec,PAM: set bytes_per_px based on depth when missing" +93b12753 configure: test for -Wconstant-conversion +645f0c53 pnmdec,PAM: set bytes_per_px based on depth when missing +e9154605 Merge "vwebp: activate GLUT double-buffering" +818d795b vwebp: activate GLUT double-buffering +d63e6f4b Add a man page for webpinfo +4d708435 Merge "NEON: implement ConvertRGB24ToY/BGR24/ARGB/RGBA32ToUV/ARGBToUV" +faf42213 NEON: implement ConvertRGB24ToY/BGR24/ARGB/RGBA32ToUV/ARGBToUV +b4d576fa Install man pages with CMake. +cbc1b921 webpinfo: add features to parse bitstream header +e644c556 Fix bad bit writer initialization. +b62cdad2 Merge "Implement a cruncher for lossless at method 6." +da3e4dfb use the exact constant for the gamma transfer function +a9c701e0 Merge "tiffdec: fix EXTRASAMPLES check" +adab8ce0 Implement a cruncher for lossless at method 6. +1b92b237 Merge "Fix VP8ApplyNearLossless to respect const and stride." +1923ff02 tiffdec: fix EXTRASAMPLES check +97cce5ba tiffdec: only request EXTRASAMPLES w/> 3 samples/px +0dcd85b6 Fix VP8ApplyNearLossless to respect const and stride. +f7682189 yuv: rationalize the C/SSE2 function naming +52245424 NEON implementation of some Sharp-YUV420 functions +690efd82 Avoid several backward reference copies. +4bb1f607 src/dec/vp8_dec.h, cosmetics: fix comments +285748be cmake: build/install webpinfo +78fd199c backward_references_enc.c: clear -Wshadow warnings +ae836410 WebPLog2FloorC: clear -Wshadow warning +d0b7404e Merge "WASM support" +134e314f WASM support +c08adb6f Merge "VP8LEnc: remove use of BitsLog2Ceiling()" +28c37ebd VP8LEnc: remove use of BitsLog2Ceiling() +2cb58ab2 webpinfo: output format as a human readable string +bb175a93 Merge "rename some symbols clashing with MSVC headers" +39eda658 Remove a duplicated pixel hash implementation. +36b8274d rename some symbols clashing with MSVC headers +274daf54 Add webpinfo tool. +ec5036e4 add explicit reference to /usr/local/{lib,inc} +18f0dfac Merge "fix TIFF encoder regarding rgbA/RGBA" +4e2b0b50 Merge "webpdec.h: fix a doc typo" +e2eeabff Merge "Install binaries, libraries and headers in CMake." +836607e6 webpdec.h: fix a doc typo +9273e441 fix TIFF encoder regarding rgbA/RGBA +17e3c11f Add limited PAM decoding support +5f624871 Install binaries, libraries and headers in CMake. +976adac1 Merge "lossless incremental decoding: fix missing eos_ test" +f8fad4fa lossless incremental decoding: fix missing eos_ test +27415d41 Merge "vwebp_sdl: fix the makefile.unix" +49566182 Merge "ImgIoUtilWriteFile(): use ImgIoUtilSetBinaryMode" +6f75a51b Analyze the transform entropy on the whole image. +a5e4e3af Use palette only if we can in entropy analysis. +75a9c3c4 Improve compression by better entropy analysis. +39cf6f4f vwebp_sdl: fix the makefile.unix +699b0416 ImgIoUtilWriteFile(): use ImgIoUtilSetBinaryMode +7d985bd1 Fix small entropy analysis bug. +6e7caf06 Optimize the color cache size. +833c9219 More efficient stochastic histogram merge. +5183326b Refactor the greedy histogram merge. +99f6f462 Merge "histogram_enc.c,MyRand: s/ul/u/ for unsigned constants" +80a22186 ssim.c: remove dead include +a128dfff histogram_enc.c,MyRand: s/ul/u/ for unsigned constants +693bf74e move the SSIM calculation code in ssim.c / ssim_sse2.c +10d791ca Merge "Fix the random generator in HistogramCombineStochastic." +fa63a966 Fix the random generator in HistogramCombineStochastic. +16be192f VP8LSetBitPos: remove the eos_ setting +027151ca don't erase the surface before blitting. +4105d565 disable WEBP_USE_XXX optimisations when EMSCRIPTEN is defined +9ee32a75 Merge "WebP-JS: emscripten-based Javascript decoder" +ca9f7b7d WebP-JS: emscripten-based Javascript decoder +868aa690 Perform greedy histogram merge in a unified way. +5b393f2d Merge "fix path typo for vwebp_sdl in Makefile.vc" +e0012bea CMake: only use libwebpdecoder for building dwebp +84c2a7b0 fix path typo for vwebp_sdl in Makefile.vc +1b0e4abf Merge "Add a flag to disable SIMD optimizations." +32263250 Add a flag to disable SIMD optimizations. +b494fdec optimize the ARGB->ARGB Import to use memcpy +f1536039 Merge "ReadWebP: decode directly into a pre-allocated buffer" +e69ed291 ReadWebP: decode directly into a pre-allocated buffer +57d8de8a Merge "vwebp_sdl: simple viewer based on SDL" +5cfd4ebc LZ77 interval speedups. Faster, smaller, simpler. +1e7ad88b PNM header decoder: add some basic numerical validation +17c7890c Merge "Add a decoder only library for WebP in CMake." +be733786 Merge "Add clang build fix for MSA" +03cda0e4 Add a decoder only library for WebP in CMake. +aa893914 Add clang build fix for MSA +31a92e97 Merge "imageio: add limited PNM support for reading" +dcf9d82a imageio: add limited PNM support for reading +6524fcd6 vwebp_sdl: simple viewer based on SDL +6cf24a24 get_disto: fix reference file read +43d472aa Merge tag 'v0.6.0' +50d1a848 update ChangeLog (tag: v0.6.0, origin/0.6.0) +20a7fea0 extras/Makefile.am: fix libwebpextras.la reference +415f3ffe update ChangeLog (tag: v0.6.0-rc3) +3c6d1224 update NEWS +ee4a4141 update AUTHORS +32ed856f Fix "all|no frames are keyframes" settings. +1c3190b6 Merge "Fix "all|no frames are keyframes" settings." +f4dc56fd disable GradientUnfilter_NEON +4f3e3bbd disable GradientUnfilter_NEON +2dc0bdca Fix "all|no frames are keyframes" settings. +0d8e0588 img2webp: treat -loop as a no-op w/single images +b0450139 ReadImage(): restore size reporting +0ad3b4ef update ChangeLog (tag: v0.6.0-rc2) +6451709e img2webp,get_disto: fix image decode w/WIC builds +92504d21 get_disto: make ReadPicture() return a bool +c3e4b3a9 update NEWS +3363eb6d man/img2webp.1: fix formatting warning +4d1312f2 update NEWS +36c42ea4 bump version to 0.6.0 +bb498a51 update AUTHORS +84cef16f Makefile.vc: fix CFG=debug-dynamic build +919f9e2f Merge "add .rc files for windows dll versioning" +f1ae8af4 Merge ".gitignore: add img2webp" +4689ce16 cwebp: add a -sharp_yuv option for 'sharp' RGB->YUV conversion +79bf46f1 rename the pretentious SmartYUV into SharpYUV +eb1dc89a silently expose use_delta_palette in the WebPConfig API +c85b0dde .gitignore: add img2webp +43d3f01a add .rc files for windows dll versioning +668e1dd4 src/{dec,enc,utils}: give filenames a unique suffix +0e6b7f33 Merge "iosbuild.sh: only add required headers to framework" +29ed6f9a iosbuild.sh: only add required headers to framework +71c53f1a NEON: speed-up strong filtering +73f567ea Merge "get_disto: remove redundant reader check" +9e14276f Merge "makefiles: prune get_disto & webp_quality deps" +99965bac Merge "Makefile.vc: add get_disto.exe, webp_quality.exe" +d4912238 get_disto: remove redundant reader check +ea482409 makefiles: prune get_disto & webp_quality deps +2ede5a19 Makefile.vc: add get_disto.exe, webp_quality.exe +a345068a ARM: speed up bitreader by avoiding tables +1dc82a6b Merge "introduce a generic GetCoeffs() function pointer" +8074b89e introduce a generic GetCoeffs() function pointer +749a45a5 Merge "NEON: implement alpha-filters (horizontal/vertical/gradient)" +74c053b5 Merge "NEON: fix overflow in SSE NxN calculation" +0a3aeff7 Merge "dsp: WebPExtractGreen function for alpha decompression" +1de931c6 NEON: implement alpha-filters (horizontal/vertical/gradient) +9b3aca40 NEON: fix overflow in SSE NxN calculation +1c07a3c6 dsp: WebPExtractGreen function for alpha decompression +9ed5e3e5 use pointers for WebPRescaler's in WebPDecParams +db013a8d Merge "ARM: don't use USE_GENERIC_TREE" +fcd4784d use a 8b table for C-version for clz() +fbb5c473 ARM: don't use USE_GENERIC_TREE +8fda5612 Merge "add a kSlowSSSE3 feature for CPUInfo" +86bbd245 add a kSlowSSSE3 feature for CPUInfo +7c2779e9 Get code to fully compile in C++. +250c3586 Merge "When compiling as C++, avoid narrowing warnings." +c0648ac2 When compiling as C++, avoid narrowing warnings. +0d55f60c 40% faster ApplyAlphaMultiply_SSE2 +49d0280d NEON: implement several alpha-processing functions +48b1e85f SSE2: 15% faster alpha-processing functions +e3b8abbc fix warning from static analysis. +28fe054e SSE2: 30% faster ApplyAlphaMultiply() +f44acd25 Merge "Properly compute the optimal color cache size." +527844fe Properly compute the optimal color cache size. +be0ef639 fix a comment typo +8874b162 Fix a non-deterministic color cache size computation. +d712e20d Do not allow a color cache size bigger than the number of colors. +ecff04f6 re-introduce some comments in Huffman Cost. +259e9828 replace 'ptr + y * stride' by 'ptr += stride' +00b08c88 Merge "NEON: 5% faster conversion to RGB565 and RGBA4444" +0e7f4447 Merge "NEON: faster fancy upsampling" +b016cb91 NEON: faster fancy upsampling +1cb63801 Call the C function to finish off lossless SSE loops only when necessary. +875fafc1 Implement BundleColorMap in SSE2. +3674d49e Merge "remove Clang warnings with unused arch arguments." +f04eb376 Merge tag 'v0.5.2' +341d711c NEON: 5% faster conversion to RGB565 and RGBA4444 +abb54827 remove Clang warnings with unused arch arguments. +ece9684f update ChangeLog (tag: v0.5.2-rc2, tag: v0.5.2, origin/0.5.2) +aa7744ca anim_util: quiet implicit conv warnings in 32-bit +d9120271 jpegdec: correct ContextFill signature +24eb3940 Remove some errors when compiling the code as C++. +a4a8e5f3 vwebp: clear canvas during resize w/o animation +67c25ad5 vwebp: clear canvas during resize w/o animation +a4bbe4b3 fix indentation +31ca2a80 tiffdec: restore libtiff 3.9.x compatibility +b2f77b57 update NEWS +5ab6d9de AnimEncoder: avoid freeing uninitialized memory pointer. +f29bf582 WebPAnimEncoder: If 'minimize_size' and 'allow_mixed' on, try lossy + lossless. +3ebe1c00 AnimEncoder: avoid freeing uninitialized memory pointer. +df780e0e fix a potential overflow with MALLOC_LIMIT +58fc5078 Merge "PredictorSub: implement fully-SSE2 version" +9cc42167 PredictorSub: implement fully-SSE2 version +0aa1f35c remove dependency of imageio/ to stopwatch.h +cb9ec84b Merge "remove the dependency to stop_watch.[ch] in imageio" +dc0c01fb Merge "anim_util: quiet implicit conv warnings in 32-bit" +827d3c50 Merge "fix a potential overflow with MALLOC_LIMIT" +1e2e25b0 anim_util: quiet implicit conv warnings in 32-bit +218460cd bump version to 0.5.2 +de7d654d update AUTHORS & .mailmap +273367c1 Merge "dsp/lossless.c,cosmetics: fix indent" +76bbcf2e fix a potential overflow with MALLOC_LIMIT +8ac1abfe Merge "jpegdec: correct ContextFill signature" +cb215aed remove the dependency to stop_watch.[ch] in imageio +2423017a dsp/lossless.c,cosmetics: fix indent +74a12b10 iosbuild.sh: add WebPDecoder.framework + encoder +a9cc7621 Merge "iosbuild.sh: add WebPDecoder.framework + encoder" +fbba5bc2 optimize predictor #1 in plain-C For some reason, gcc has hard time inlining this one... +9ae0b3f6 Merge "SSE2: slightly (~2%) faster Predictor #1" +c1f97bd7 SSE2: slightly (~2%) faster Predictor #1 +ea664b89 SSE2: 10% faster Predictor #11 +be7dcc08 AnimEncoder: Correctly skip a frame when sub-rectangle is empty. +40885830 Fix assertions in WebPRescalerExportRow() +1d5046d1 iosbuild.sh: add WebPDecoder.framework + encoder +cec72014 jpegdec: correct ContextFill signature +8f38c72e fix a typo in WebPPictureYUVAToARGB's doc +33ca93f9 systematically call WebPDemuxReleaseIterator() on dec->prev_iter_ +76e19073 doc: use two's complement explicitly for uint8->int8 conversion +f91ba963 Anim_encoder: correctly handle enc->prev_candidate_undecided_ +25d74e65 WebPPictureDistortion(): free() -> WebPSafeFree() +03f1c008 mux/Makefile.am: add missing -lm +58410cd6 fix bug in RefineUsingDistortion() +e168af8c fix filtering auto-adjustment +ed9dec41 fix doc and code snippet for WebPINewDecoder() doc +3c49178f prevent 32b overflow for very large canvas_width / height +9595f290 fix anim_util.c compilation when HAVE_GIF is not defined. +7ec9552c Make gif transparent color to be transparent black +b3fb8bb6 slightly faster Predictor #11 in NEON +9871335f Add a CMake option for WEBP_SWAP_16BIT_CSP. +0ae32226 Fix missing cpu-features for Android. +ab4c8056 cpu.cmake: improve webp_check_compiler_flag output +eec5fa3a Provide support for CMake on Android studio 2.2. +004d5690 Split the main CMake file. +4fe5d588 Android.mk: use -fvisibility=hidden +bd63a31a vwebp: ensure setenv() is available in stdlib.h +363a5681 vwebp: handle window resizing properly +a0d2753f lower WEBP_MAX_ALLOCABLE_MEMORY default +31fe11a5 fix infinite loop in case of PARTITION0 overflow +532215dd Change the rule of picking UV mode in MBAnalyzeBestUVMode() +9c75dbd3 cwebp.1: improve some grammar +af2e05cb vwebp: Clear previous frame when a key triggers a redraw +26ffa296 Add descriptions of default configuration in help info. +7416280d Fix an unsigned integer overflow error in enc/cost.h +13cf1d2e Do token recording and counting in a single loop +eb9a4b97 Reset segment id if we decide not to update segment map +42ebe3b7 configure: fix NEON flag detection under gcc 6 +76ebbfff NEON: implement predictor #13 +95b12a08 Merge "Revert Average3 and Average4" +54ab2e75 Revert Average3 and Average4 +fe12330c 3-5% faster Predictor #5, #6, #7 and #10 for NEON +fbfb3bef ~2% faster predictor #10 for NEON +d4b7d801 lossless_sse2: use the local functions +a5e3b225 Lossless decoder SSE2 improvements. +58a1f124 ~2% faster predictor #12 in NEON. +906c3b63 Merge "Implement lossless transforms in NEON." +d23abe4e Implement lossless transforms in NEON. +2e6cb6f3 Give more flexibility to the predictor generating macro. +28e0bb70 Merge "Fix race condition in multi-threading initialization." +64704530 Fix race condition in multi-threading initialization. +bded7848 img2webp: fix default -lossless value and use pic.argb=1 +0e61a513 Merge "img2webp: convert a sequence of images to an animated webp" +1cc79e92 AnimEncoder: Correctly skip a frame when sub-rectangle is empty. +03f40955 img2webp: convert a sequence of images to an animated webp +ea72cd60 add missing 'extern' keyword for predictor dcl +67879e6d SSE implementation of decoding predictors. +34aee990 Merge "vwebp: make 'd' key toggle the debugging of fragments" +a41296ae Fix potentially uninitialized value. +c85adb33 vwebp: make 'd' key toggle the debugging of fragments +4239a148 Make the lossless predictors work on a batch of pixels. +bc18ebad fix extra 'const's in signatures +71e2f5ca Remove memcpy in lossless decoding. +7474d46e Do not use a register array in SSE. +67748b41 Improve latency of FTransform2. +16951b19 Merge "Provide an SSE implementation of ConvertBGRAToRGB" +6540cd0e Provide an SSE implementation of ConvertBGRAToRGB +de568abf Android.mk: use -fvisibility=hidden +3c2a61b0 remove some unneeded casts +9ac063c3 add dsp functions for SmartYUV +22efabdd Merge "smart_yuv: switch to planar instead of packed r/g/b processing" +1d6e7bf3 smart_yuv: switch to planar instead of packed r/g/b processing +0a3838ca fix bug in RefineUsingDistortion() +c0699515 webpmux -duration: set default 'end' value equal to 'start' +83cbfa09 Import: use relative pointer offsets +a1ade40e PreprocessARGB: use relative pointer offsets +fd4d090f ConvertWRGBToYUV: use relative pointer offsets +9daad459 ImportYUVAFromRGBA: use relative pointer offsets +f90c60d1 Merge "add a "-duration duration,start,end" option to webpmux" +3f182d36 add a "-duration duration,start,end" option to webpmux +342e15f0 Import: use relative pointer offsets +1147ab4e PreprocessARGB: use relative pointer offsets +e4cd4daf fix filtering auto-adjustment +e7152856 fix doc and code snippet for WebPINewDecoder() doc +de9fa507 ConvertWRGBToYUV: use relative pointer offsets +deb1b831 ImportYUVAFromRGBA: use relative pointer offsets +c284780f imageio_util: add ImgIoUtilCheckSizeArgumentsOverflow +e375080d gifdec,Remap: avoid out of bounds colormap read +c222a053 additional fix for stride type as size_t +bb233617 fix potential overflow when width * height * 4 >= (1<<32) +883d41fb gif2webp: fix crash with NULL extension data +cac9a36a gifdec,Remap: avoid out of bounds colormap read +4595e01f Revert "gifdec,Remap: avoid out of bounds colormap read" +fb52d443 gifdec: make some constants unsigned +f048d38d gifdec,Remap: avoid out of bounds colormap read +31b1e343 fix SSIM metric ... by ignoring too-dark area +2f51b614 introduce WebPPlaneDistortion to compute plane distortion +0104d730 configure: fix NEON flag detection under gcc 6 +265abbe9 Merge "additional fix for stride type as size_t" +f7601aa6 Merge "Introduce a generic WebPGetImageReader(type) function" +ce873320 Introduce a generic WebPGetImageReader(type) function +2a2773ea imageio/*dec,Read*: add input parameter checks +9f5c8eca additional fix for stride type as size_t +4eb5df28 remove unused stride fields from VP8Iterator +11bc423a MIN_LENGTH cleanups. +273d035a Merge "fix a typo in WebPPictureYUVAToARGB's doc" +4db82a17 Merge "fix potential overflow when width * height * 4 >= (1<<32)" +e2affacc fix potential overflow when width * height * 4 >= (1<<32) +dc789ada fix a typo in WebPPictureYUVAToARGB's doc +539f5a68 Fix non-included header in config.c. +aaf2a6a6 systematically call WebPDemuxReleaseIterator() on dec->prev_iter_ +20ef9915 Merge "imageio_util: add ImgIoUtilCheckSizeArgumentsOverflow" +bc86b7a8 imageio_util: add ImgIoUtilCheckSizeArgumentsOverflow +806f6279 gif2webp: fix crash with NULL extension data +68ae5b67 Add libwebp/src/mux/animi.h +28ce3043 Remove some errors when compiling the code as C++. +b34abcb8 Favor keeping the areas locally similar in spatial prediction mode selection +ba843a92 fix some SSIM calculations +51b71fd2 Merge "vwebp: ensure setenv() is available in stdlib.h" +fb01743a get_disto: fix the r/g/b order for luma calculation +bfab8947 vwebp: ensure setenv() is available in stdlib.h +9310d192 vwebp: handle window resizing properly +f79450ca Speedup ApplyMap. +cfdda7c6 Merge "prevent 32b overflow for very large canvas_width / height" +e36396ba Merge "get_disto: new option to compute SSIM map and convert to gray" +18a9a0ab Add an API to import a color-mapped image. +30d43706 Speed-up Combined entropy for palettized histograms. +36aa087b get_disto: new option to compute SSIM map and convert to gray +86a84b35 2x faster SSE2 implementation of SSIMGet +b8384b53 lower WEBP_MAX_ALLOCABLE_MEMORY default +1c364400 prevent 32b overflow for very large canvas_width / height +eee0cce1 Merge "Small LZ77 speedups." +5f1caf29 Small LZ77 speedups. +1effde7b fix anim_util.c compilation when HAVE_GIF is not defined. +a2fe9bf4 Speedup TrellisQuantizeBlock(). +573cce27 smartYUV improvements +21e7537a fix infinite loop in case of PARTITION0 overflow +053a1565 Merge "Change the rule of picking UV mode in MBAnalyzeBestUVMode()" +1377ac2e Change the rule of picking UV mode in MBAnalyzeBestUVMode() +7c1fb7d0 fix uint32_t initialization (0. -> 0) +bfff0bf3 speed-up SSIM calculation +64577de8 De-VP8L-ize GetEntropUnrefinedHelper. +a7be7328 Merge "refactor the PSNR / SSIM calculation code" +50c3d7da refactor the PSNR / SSIM calculation code +d6228aed indentation fix after I7055d3ee3bd7ed5e78e94ae82cb858fa7db3ddc0 +dd538b19 Remove unused declaration. +6cc48b17 Move some lossless logic out of dsp. +78363e9e Merge "Remove a redundant call to InitLeft() in VP8IteratorReset()" +ffd01929 Refactor VP8IteratorNext(). +c4f6d9c9 Remove a redundant call to InitLeft() in VP8IteratorReset() +c27d8210 Merge "smartYUV: simplify main loop" +07795296 smartYUV: simplify main loop +c9b45863 Split off common lossless dsp inline functions. +490ae5b1 smartYUV: improve initial state for faster convergence +894232be smartYUV: fix and simplify the over-zealous stop criterion +8de08483 Remove unused code in webpi.h +41cab7fe imageio/Android.mk: correct imagedec dependencies +82c91c70 Merge "libimageenc.a: extract image-saving code from dwebp" +af1ad3e2 libimageenc.a: extract image-saving code from dwebp +dd7309e3 Merge "doc: use two's complement explicitly for uint8->int8 conversion" +6105777e Merge "add gif2webp to CMake" +13ae011e doc: use two's complement explicitly for uint8->int8 conversion +4bda0cfb add gif2webp to CMake +6029c7fe Merge "remove mention of fragment, frgm, FRGM, etc." +545c147f remove mention of fragment, frgm, FRGM, etc. +5b46f7fc cwebp.1: improve some grammar +9e478f80 dec/vp8l.c: add assertions in EmitRescaledRowsRGBA/YUVA +43bd8958 Make gif transparent color to be transparent black +0887fc2d Merge "get_disto: add a '-o file' option to save a diff map" +0de48e18 get_disto: add a '-o file' option to save a diff map +0a57ad0d cosmetics: WebPSafeAlloc -> WebPSafeMalloc +0a4699bc Merge "WebPPictureDistortion(): free() -> WebPSafeFree()" +29fedbf5 Anim_encoder: correctly handle enc->prev_candidate_undecided_ +32dead4e WebPPictureDistortion(): free() -> WebPSafeFree() +85cd5d06 Smarter LZ77 for uniform regions. +6585075f Change PixelsAreSimilar() to handle black pixels correctly. +c0a27fd2 vwebp: Clear previous frame when a key triggers a redraw +57a5e3b6 webp_quality should return '0' in case of success. +7f1b897b Faster stochastic histogram merging. +48c810b8 Merge "remove WEBP_FORCE_ALIGNED and use memcpy() instead." +3884972e remove WEBP_FORCE_ALIGNED and use memcpy() instead. +485cac1a switch libimagedec.a and libimageio_util.a to avoid undefined symbol +005e15b1 Merge "{extras,mux}/Makefile.am: add missing -lm" +6ab496ed fix some 'unsigned integer overflow' warnings in ubsan +8a4ebc6a Revert "fix 'unsigned integer overflow' warnings in ubsan" +9d4f209f Merge changes I25711dd5,I43188fab +e44f5248 fix 'unsigned integer overflow' warnings in ubsan +27b5d991 Fix assertions in WebPRescalerExportRow() +74f6f9e7 Add descriptions of default configuration in help info. +aaf2530c {extras,mux}/Makefile.am: add missing -lm +1269dc7c Refactor VP8LColorCacheContains() +40872fb2 dec_neon,NeedsHev: micro optimization +7b54e26b Add a CMake option for WEBP_SWAP_16BIT_CSP. +d2223d8d Fix missing cpu-features for Android. +bf16a4b4 Merge "cpu.cmake: improve webp_check_compiler_flag output" +ee1057e3 cpu.cmake: improve webp_check_compiler_flag output +b551e587 cosmetics: add {}s on continued control statements +d2e4484e dsp/Makefile.am: put msa source in correct lib +c7f66c82 Merge "utils/thread.c,cosmetics: join a few lines" +98d8f295 Merge "examples/Makefile.am,cosmetics: sort binary targets" +39f4ffbc utils/thread.c,cosmetics: join a few lines +a86ce2b1 Merge "extras/Makefile.am: don't install libwebpextras" +6fa9fe24 extras/Makefile.am: don't install libwebpextras +0b2c58a9 Fix an unsigned integer overflow error in enc/cost.h +d7ce4a2e examples/Makefile.am,cosmetics: sort binary targets +386e4ba2 Reset segment id if we decide not to update segment map +7b87e848 Merge "Add MSA optimized YUV to RGB upsampling functions" +d3ddacb6 Add MSA optimized YUV to RGB upsampling functions +eb98d8d8 webp_quality: detect lossless format and features +ebee57f4 move imageio/example_util.[hc] (back to) examples/ +99542bbf webpdec: s/ExUtil// +da573cf4 imageio_util: s/ExUtil/ImgIoUtil/ +bdda5bd4 split example_util.h +15ed462b .gitignore: add extras/{get_disto,webp_quality} +7be57489 Merge "VP8EstimateQuality(): roughty estimate webp bitstream quality factor" +57020525 Makefile.vc: add missing imageio target +e8ab6a82 VP8EstimateQuality(): roughty estimate webp bitstream quality factor +fee7b3d6 Merge "'extras/get_disto' example: compute PSNR between two files" +1e7d4401 'extras/get_disto' example: compute PSNR between two files +4cecab63 pngdec.c,jpegdec.[hc]: remove unnecessary includes +259f0434 makefile.unix: normalize image decode lib name +ed34c39b fix: examples/libexample_dec.a => imageio/libexample_dec.a +33d8d0d4 Merge "move examples/{example_util,image_dec} to imageio/" +c960b82e Merge "extras.h: correct include guard" +fe3cd28a Merge ".gitignore: add .gradle, /build" +45fbeba5 Merge "Do token recording and counting in a single loop" +4f33c820 .gitignore: add .gradle, /build +c379b55a move examples/{example_util,image_dec} to imageio/ +5108d9aa extras.h: correct include guard +ad497fbc move src/extras to the top-level +0c0fb832 Do token recording and counting in a single loop +9ac74f92 Add MSA optimized rescaling functions +cb19dbc1 Add MSA optimized color transform functions +3f4042b5 WebPAnimEncoder: If 'minimize_size' and 'allow_mixed' on, try lossy + lossless. +5e2eb89e cosmetics,dsp/*msa.c: associate '*' with the type +5b60db5c FastMBAnalyze() for quick i16/i4 decision +567e6977 Add MSA optimized CollectHistogram function +c54ab8dd Add MSA optimized quantization functions +ec6f68c5 Merge "Remove QuantizeBlockWHT() in enc.c" +2a5c417c Apply the RLE heuristic to LZ77. +91b59e88 Remove QuantizeBlockWHT() in enc.c +fe572737 Add MSA optimized SSE functions +6b53ca87 cosmetics,(dec|enc)_sse2.c: fix indent +b15d00d9 Merge "Add MSA optimized encoder IntraChromaPreds function" +afe3cec8 Add MSA optimized encoder IntraChromaPreds function +fc8cad9f reduce the number of malloc/free cycles in huffman.c +7b4b05e0 Add MSA optimized encoder Intra16Preds function +c18787a0 Add MSA optimized encoder Intra4Preds function +479d1908 webpmux: Also print compression info per frame. +a80e8cfd Provide support for CMake on Android studio 2.2. +6c628410 Split the main CMake file. +bbb6ecd9 Merge "Add MSA optimized distortion functions" +7915396f Add MSA optimized distortion functions +652e944f Merge "build.gradle: remove tab" +c0991a14 io,EmitRescaledAlphaYUV: factor out a common expr +48bf5ed1 build.gradle: remove tab +bfef6c9f Merge tag 'v0.5.1' +3d97bb75 update ChangeLog (tag: v0.5.1, origin/0.5.1) +deb54d91 Clarify the expected 'config' lifespan in WebPIDecode() +435308e0 Add MSA optimized encoder transform functions +dce64bfa Add MSA optimized alpha filter functions +429120d0 Add MSA optimized color transform functions +c7e2d245 update ChangeLog (tag: v0.5.1-rc5) +55b2fede normalize the macros' "do {...} while (0)" constructs +701c772e Add MSA optimized colorspace conversion functions +c7eb06f7 Fix corner case in CostManagerInit. +f918cb10 fix rescaling bug: alpha plane wasn't filled with 0xff +ab7937a5 gif2webp: normalize the number of .'s in the help message +3cdec847 vwebp: normalize the number of .'s in the help message +bdf6241e cwebp: normalize the number of .'s in the help message +06a38c7b fix rescaling bug: alpha plane wasn't filled with 0xff +319e37be Improve lossless compression. +6a197937 Add MSA optimized intra pred chroma functions +447adbce 'our bug tracker' -> 'the bug tracker' +97b9e644 normalize the number of .'s in the help message +293d786f Added MSA optimized intra prediction 16x16 functions +0afa0ce2 Added MSA optimized intra prediction 4x4 functions +a6621bac Added MSA optimized simple edge filtering functions +bb50bf42 pngdec,ReadFunc: throw an error on invalid read +38063af1 decode.h,WebPGetInfo: normalize function comment +1ebf193c Added MSA optimized chroma edge filtering functions +9ad2352d Merge "Added MSA optimized edge filtering functions" +60751096 Added MSA optimized edge filtering functions +9e8e1b7b Inline GetResidual for speed. +7d58d1b7 Speed-up uniform-region processing. +8ec7032b simplify HistogramCombineEntropyBin() +23e29cb1 Merge "Fix a boundary case in BackwardReferencesHashChainDistanceOnly." into 0.5.1 +472a049b remove bin_map[] allocation altogether +0bb23b2c free -> WebPSafeFree() +a977b4b5 Merge "rewrite the bin_map clustering to use less memory" +3591ba66 rewrite the bin_map clustering to use less memory +e6ac450c utils.[hc]: s/MAX_COLOR_COUNT/MAX_PALETTE_SIZE/ +e7b91772 Merge "DecodeImageData(): change the incorrect assert" into 0.5.1 +2abfa54f DecodeImageData(): change the incorrect assert +5a48fcd8 Merge "configure: test for -Wfloat-conversion" +0174d18d Fix a boundary case in BackwardReferencesHashChainDistanceOnly. +6a9c262a Merge "Added MSA optimized transform functions" +cfbcc5ec Make sure to consider small distances in LZ77. +5e60c42a Added MSA optimized transform functions +3dc28d76 configure: test for -Wfloat-conversion +f2a0946a add some asserts to delimit the perimeter of CostManager's operation +9a583c66 fix invalid-write bug for alpha-decoding +f66512db make gradlew executable +6fda58f1 backward_references: quiet double->int warning +a48cc9d2 Merge "Fix a compression regression for images with long uniform regions." into 0.5.1 +cc2720c1 Merge "Revert an LZ77 boundary constant." into 0.5.1 +059aab4f Fix a compression regression for images with long uniform regions. +b0c7e49e Check more backward matches with higher quality. +a3611513 Revert an LZ77 boundary constant. +8190374c README: fix typo +7551db44 update NEWS +0fb2269c bump version to 0.5.1 +f4537610 update AUTHORS & .mailmap +3259571e Refactor GetColorPalette method. +1df5e260 avoid using tmp histogram in PreparePair() +7685123a fix comment typos +a246b921 Speedup backward references. +76d73f18 Merge "CostManager: introduce a free-list of ~10 intervals" +eab39d81 CostManager: introduce a free-list of ~10 intervals +4c59aac0 Merge "mips msa webp configuration" +043c33f1 Merge "Improve speed and compression in backward reference for lossless." +71be9b8c Merge "clarify variable names in HistogramRemap()" +0ba7fd70 Improve speed and compression in backward reference for lossless. +0481d42a CostManager: cache one interval and re-use it when possible +41b7e6b5 Merge "histogram: fix bin calculation" +96c3d624 histogram: fix bin calculation +fe9e31ef clarify variable names in HistogramRemap() +ce3c8247 disable near-lossless quantization if palette is used +e11da081 mips msa webp configuration +5f8f998d mux: Presence of unknown chunks should trigger VP8X chunk output. +cadec0b1 Merge "Sync mips32 and dsp_r2 YUV->RGB code with C verison" +d9637758 Compute the hash chain once and for all for lossless compression. +50a48665 Sync mips32 and dsp_r2 YUV->RGB code with C verison +eee788e2 Merge "introduce a common signature for all image reader function" +d77b877c introduce a common signature for all image reader function +ca8d9519 remove some obsolete TODOs +ae2a7222 collect all decoding utilities from examples/ in libexampledec.a +0b8ae852 Merge "Move DitherCombine8x8 to dsp/dec.c" +77cad885 Merge "ReadWebP: avoid conversion to ARGB if final format is YUVA" +ab8d6698 ReadWebP: avoid conversion to ARGB if final format is YUVA +f8b7ce9e Merge "test pointer to NULL explicitly" +5df6f214 test pointer to NULL explicitly +77f21c9c Move DitherCombine8x8 to dsp/dec.c +c9e6d865 Add gradle support +c65f41e8 Revert "Add gradle support" +bf731ede Add gradle support +08333b85 WebPAnimEncoder: Detect when canvas is modified, restore only when needed. +0209d7e6 Merge "speed-up MapToPalette() with binary search" +fdd29a3d speed-up MapToPalette() with binary search +cf4a651b Revert "Refactor GetColorPalette method." +0a27aca3 Merge changes Idfa8ce83,I19adc9c4 +f25c4406 WebPAnimEncoder: Restore original canvas between multiple encodes. +169004b1 Refactor GetColorPalette method. +576362ab VP8LDoFillBitWindow: support big-endian in fast path +ac49e4e4 bit_reader.c: s/VP8L_USE_UNALIGNED_LOAD/VP8L_USE_FAST_LOAD/ +d39ceb58 VP8LDoFillBitWindow: remove stale TODO +2ec2de14 Merge "Speed-up BackwardReferencesHashChainDistanceOnly." +3e023c17 Speed-up BackwardReferencesHashChainDistanceOnly. +f2e1efbe Improve near lossless compression when a prediction filter is used. +e15afbce dsp.h: fix ubsan macro name +e53c9ccb dsp.h: add WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW +af81fdb7 utils.h: quiet -fsanitize=undefined warnings +ea0be354 dsp.h: remove utils.h include +cd276aec utils/*.c: ../utils/utils.h -> ./utils.h +c8927131 utils/Makefile.am: add some missing headers +ea24e026 Merge "dsp.h: add WEBP_UBSAN_IGNORE_UNDEF" +369e264e dsp.h: add WEBP_UBSAN_IGNORE_UNDEF +0d020a78 Merge "add runtime NEON detection" +5ee2136a Merge "add VP8LAddPixels() to lossless.h" +47435a61 add VP8LAddPixels() to lossless.h +8fa6ac68 remove two ubsan warnings +74fb56fb add runtime NEON detection +4154a839 MIPS update to new Unfilter API +c80b9fc8 Merge "cherry-pick decoder fix for 64-bit android devices" +6235147e cherry-pick decoder fix for 64-bit android devices +d41b8c43 configure: test for -Wformat-* w/-Wformat present +5f95589f Fix WEBP_ALIGN in case the argument is a pointer to a type larger than a byte. +2309fd5c replace num_parts_ by num_parts_minus_one_ (unsigned) +9629f4bc SimplifySegments: quiet -Warray-bounds warning +de47492e Merge "update the Unfilter API in dsp to process one row independently" +2102ccd0 update the Unfilter API in dsp to process one row independently +e3912d56 WebPAnimEncoder: Restore canvas before evaluating blending possibility. +6e12e1e3 WebPAnimEncoder: Fix for single-frame optimization. +602f344a Merge changes I1d03acac,Ifcb64219 +95ecccf6 only apply color-mapping for alpha on the cropped area +47dd0708 anim_diff: Add an experimental option for max inter-frame diff. +aa809cfe only allocate alpha_plane_ up to crop_bottom row +31f2b8d8 WebPAnimEncoder: FlattenSimilarPixels(): look for similar +774dfbdc perform alpha filtering within the decoding loop +a4cae68d lossless decoding: only process decoded row up to last_row +238cdcdb Only call WebPDequantizeLevels() on cropped area +cf6c713a alpha: preparatory cleanup +b95ac0a2 Merge "VP8GetHeaders(): initialize VP8Io with sane value for crop/scale dimensions" +89231394 VP8GetHeaders(): initialize VP8Io with sane value for crop/scale dimensions +5828e199 use_8b_decode -> use_8b_decode_ +8dca0247 fix bug in alpha.c that was triggering a memory error in incremental mode +9a950c53 WebPAnimEncoder: Disable filtering when blending is used with lossy encoding. +eb423903 WebPAnimEncoder: choose max diff for framerect based on quality. +ff0a94be WebPAnimEncoder lossy: ignore small pixel differences for frame rectangles. +f8040084 gif2webp: Remove the 'prev_to_prev_canvas' buffer. +6d8c07d3 Merge "WebPDequantizeLevels(): use stride in CountLevels()" +d96fe5e0 WebPDequantizeLevels(): use stride in CountLevels() +ec1b2407 WebPPictureImport*: check output pointer +c0768769 Merge "Revert "Re-enable encoding of alpha plane with color cache for next release."" +41f14bcb WebPPictureImport*: check src pointer +64eed387 Pass stride parameter to WebPDequantizeLevels() +97934e24 Revert "Re-enable encoding of alpha plane with color cache for next release." +e88c4ca0 fix -m 2 mode-cost evaluation (causing partition0 overflow) +4562e83d Merge "add extra meaning to WebPDecBuffer::is_external_memory" +abdb109f add extra meaning to WebPDecBuffer::is_external_memory +875aec70 enc_neon,cosmetics: break long comment +71e856cf GetMBSSIM,cosmetics: fix alignment +a90edffb fix missing 'extern' for SSIM function in dsp/ +423ecaf4 move some SSIM-accumulation function for dsp/ +f08e6624 Merge "Fix FindClosestDiscretized in near lossless:" +0d40cc5e enc_neon,Disto4x4: remove an unnecessary transpose +e8feb20e Fix FindClosestDiscretized in near lossless: +82006430 anim_util: quiet static analysis warning +a6f23c49 Merge "AnimEncoder: Support progress hook and user data." +a5193774 Merge "Near lossless feature: fix some comments." +da98d31c AnimEncoder: Support progress hook and user data. +33357131 Near lossless feature: fix some comments. +0beed01a cosmetics: fix indent after 2f5e898 +6753f35c Merge "FTransformWHT optimization." +6583bb1a Improve SSE4.1 implementation of TTransform. +7561d0c3 FTransformWHT optimization. +7ccdb734 fix indentation after patch #328220 +6ec0d2a9 clarify the logic of the error path when decoding fails. +8aa352b2 Merge "Remove an unnecessary transposition in TTransform." +db860884 Merge "remove useless #include" +9960c316 Remove an unnecessary transposition in TTransform. +6e36b511 Small speedup in FTransform. +9dbd4aad Merge "fix C and SIMD flags completion." +e60853ea Add missing common_sse2.h file to makefile.unix +696eb2b0 fix C and SIMD flags completion. +2b4fe33e Merge "fix multiple allocation for transform buffer" +2f5e8986 fix multiple allocation for transform buffer +bf2b4f11 Regroup common SSE code + optimization. +4ed650a1 force "-pass 6" if -psnr or -size is used but -pass isn't. +3ef1ce98 yuv_sse2: fix -Wconstant-conversion warning +a7a03e9f Merge changes I4852d18f,I51ccb85d +5e122bd6 gif2webp: set enc_options.verbose = 0 w/-quiet +ab3c2583 anim_encode,DefaultEncoderOptions: init verbose +8f0dee77 Merge "configure: fix builtin detection w/-Werror" +4a7b85a9 cmake: fix builtin detection w/-Werror +b74657fb configure: fix builtin detection w/-Werror +3661b980 Add a CMakeLists.txt +75f4af4d remove useless #include +6c1d7631 avoid Yoda style for comparison +8ce975ac SSE optimization for vector mismatch. +7db53831 Merge tag 'v0.5.0' +37f04949 update ChangeLog (tag: v0.5.0-rc1, tag: v0.5.0, origin/0.5.0) +7e7b6ccc faster rgb565/rgb4444/argb output +4c7f565f update NEWS +1f62b6b2 update AUTHORS +e224fdc8 update mailmap +71100500 bump version to 0.5.0 +230a685e README: update help text, repo link +d48e427b Merge "demux: accept raw bitstreams" +99a01f4f Merge "Unify some entropy functions." +4b025f10 Merge "configure: disable asserts by default" +92cbddf8 Merge "fix PrintBlockInfo()" +ca509a33 Unify some entropy functions. +367bf903 fix PrintBlockInfo() +b0547ff0 move back common constants for lossless_enc*.c into the .h +fb4c7832 lossless: simpler alpha cleanup preprocessing +ba7f4b68 Merge "anim_diff: add brief description of options" +47ddd5a4 Move some codec logic out of ./dsp . +b4106c44 anim_diff: add brief description of options +357f455d yuv_sse2: fix 32-bit visual studio build +b9d80fa4 configure: disable asserts by default +7badd3da cosmetic fix: sizeof(type) -> sizeof(*var) +80ce27d3 Speed up 24-bit packing / unpacking in YUV / RGB conversions. +68eebcb0 remove a TODO about rotation +2dee2966 remove few obsolete TODO about aligned loads in SSE2 +e0c0bb34 remove TODO about unused ref_lf_delta[] +9cf1cc2b remove few TODO: * 256 -> RD_DISTO_MULT * don't use TDisto for UV mode picking +79189645 Merge changes from topic 'demux-fragment-cleanup' +47399f92 demux: remove GetFragment() +d3cfb79a demux: remove dead fragment related TODO +ab714b8a demux, Frame: remove is_fragment_ field +b105921c yuv_sse2, cosmetics: fix indent +466c92e8 demux,WebPIterator: remove fragment_num/num_fragments +11714ff1 demux: remove WebPDemuxSelectFragment +c0f7cc47 fix for bug #280: UMR in next->bits +578beeb8 Merge "enc/Makefile.am: add missing headers" +1a819f00 makefile.unix: make visibility=hidden the default +d4f9c2ef enc/Makefile.am: add missing headers +846caff4 configure: check for -fvisibility=hidden +3f3ea2c5 demux: accept raw bitstreams +d6dad5d0 man cwebp: add precision about exactness of the 'lossless' mode +46bb1e34 Merge "gifdec: remove utils.h include" +2b882e94 Merge "Makefile.vc: define WEBP_HAVE_GIF for gifdec.c" +892b9238 Merge "man/*, AUTHORS: clarify origin of the tool" +e5687a18 Merge "fix optimized build with -mcmodel=medium" +e56e6859 Makefile.vc: define WEBP_HAVE_GIF for gifdec.c +4077d944 gifdec: remove utils.h include +b5e30dac man/*, AUTHORS: clarify origin of the tool +b275e598 fix optimized build with -mcmodel=medium +64da45a9 cosmetics, cwebp: fix indent +038a060d Merge "add disto-based refinement for UV mode (if method = 1 or 2)" +2835089d Provide an SSE2 implementation of CombinedShannonEntropy. +e6c93519 add disto-based refinement for UV mode (if method = 1 or 2) +04507dc9 Merge "fix undefined behaviour during shift, using a cast" +793c5261 Merge "wicdec: add support for reading from stdin" +d3d16397 Optimize the heap usage in HistogramCombineGreedy. +202a710b fix undefined behaviour during shift, using a cast +14d27a46 improve method #2 by merging DistoRefine() and SimpleQuantize() +cb1ce996 Merge "10% faster table-less SSE2/NEON version of YUV->RGB conversion" +ac761a37 10% faster table-less SSE2/NEON version of YUV->RGB conversion +79fcf29a wicdec: add support for reading from stdin +015f173f Merge "cwebp: add support for stdin input" +a9947c32 cwebp: add support for stdin input +7eb01ff3 Merge "Improved alpha cleanup for the webp encoder when prediction transform is used." +fb8c9106 Merge "introduce WebPMemToUint32 and WebPUint32ToMem for memory access" +bd91af20 Merge "bit_reader: remove aarch64 BITS TODO" +6c702b81 Speed up hash chain initialization using memset. +4c60f63c make ReadPNG and ReadJPEG take a filename instead of a FILE +464ed10f bit_reader: remove aarch64 BITS TODO +d478e589 Merge "configure: update issue tracker" +69381113 Improved alpha cleanup for the webp encoder when prediction transform is used. +2c08aac8 introduce WebPMemToUint32 and WebPUint32ToMem for memory access +010ca3d1 Fix FindMatchLength with non-aligned buffers. +a90e1e3f README: add prerequisites for an autoconf build +458f0866 configure: update issue tracker +33914595 vwebp: work around the transparent background with GLUT bug +e4a7eed4 cosmetics: fix indent +08375129 Merge "Make a separate case for low_effort in CopyImageWithPrediction" +aa2eb2d4 Merge "cosmetics: fix indent" +b7551e90 cosmetics: fix indent +5bda52d4 Make a separate case for low_effort in CopyImageWithPrediction +66fa598a Merge "configure: fix intrinsics build w/older gcc" +5ae220be backward_references.c: Fixed compiler warning +1556da09 Merge "configure: restore 2 warnings" +71a17e58 configure: restore 2 warnings +9eeabc07 configure: fix intrinsics build w/older gcc +363babe2 Merge "fix some warning about unaligned 32b reads" +a1411782 Optimization in hash chain comparison for 64 bit Arrays were compared 32 bits at a time, it is now done 64 bits at a time. Overall encoding speed-up is only of 0.2% on @skal's small PNG corpus. It is of 3% on my initial 1.3 Mp desktop screenshot image. +829bd141 Combine Huffman cost and bit entropy into one loop +a7a954c8 Merge "lossless: make prediction in encoder work per scanline" +61b605b4 Merge "fix of undefined multiply (int32 overflow)" +239421c5 lossless: make prediction in encoder work per scanline +f5ca40e0 fix of undefined multiply (int32 overflow) +5cd2ef4c Merge changes from topic 'win-threading-compat' +76ce9187 Makefile.vc: enable WEBP_USE_THREAD for windows phone +d2afe974 thread: use CreateThread for windows phone +0fd0e12b thread: use WaitForSingleObjectEx if available +63fadc9f thread: use InitializeCriticalSectionEx if available +110ad583 thread: use native windows cond var if available +912c9fdf dec/webp: use GetLE(24|32) from utils +f1694481 utils/GetLE32: correct uint32 promotion +158763de Merge "always call WebPInitSamplers(), don't try to be smart" +3770f3bb Merge "cleanup the YFIX/TFIX difference by removing some code and #define" +a40f60a9 Merge "3% speed improvement for lossless webp encoder for low effort mode:" +ed1c2bc6 always call WebPInitSamplers(), don't try to be smart +b8c44f1a 3% speed improvement for lossless webp encoder for low effort mode: +997e1038 cleanup the YFIX/TFIX difference by removing some code and #define +d73d1c8b Merge "Make discarding invisible RGB values (cleanup alpha) the default." +1f9be97c Make discarding invisible RGB values (cleanup alpha) the default. +f240117b Make dwebp listen more to the -quiet flag +b37b0179 fix for issue #275: don't compare to out-of-bound pointers +21735e06 speed-up trivial one-symbol decoding case for lossless +397863bd Refactor CopyPlane() and CopyPixels() methods: put them in utils. +6ecd72f8 Re-enable encoding of alpha plane with color cache for next release. +1f7148a4 Merge "remove unused fields from WebPDecoderOptions and WebPBitstreamFeatures" +6ae395fa Merge "use ExReadFile() for ReadYUV()" +8076a00e gitignore list: add anim_diff. +1c1702d8 use ExReadFile() for ReadYUV() +775d3a37 remove unused fields from WebPDecoderOptions and WebPBitstreamFeatures +c13245c7 AnimEncoder: Add a GetError() method. +688b265d AnimDecoder API: Add a GetDemuxer() method. +1aa4e3d6 WebPAnimDecoder: add an option to enable multi-threaded decoding. +3584abca AnimDecoder: option to decode to common color modes. +afd5a62c Merge "mux.h does NOT need to include encode.h" +8550d443 Merge "migrate anim_diff tool from C++ to C89" +96201e50 migrate anim_diff tool from C++ to C89 +945cfa3b mux.h does NOT need to include encode.h +8da07e8d Merge "~2x faster SSE2 RGB24toY, BGR24toY, ARGBToY|UV" +bfd3fc02 ~2x faster SSE2 RGB24toY, BGR24toY, ARGBToY|UV +02432427 man/cwebp.1, cosmetics: escape '-'s +96f5b423 man/cwebp: group lossy-only options +52fdbdfe extract some RGB24 to Luma conversion function from enc/ to dsp/ +ab8c2300 add missing \n +8304179a sync NEWS with 0.4.4 +5bd04a08 sync versions with 0.4.4 +8f1fcc15 Merge "Move ARGB->YUV functions from dec/vp8l.c to dsp/yuv.c" +25bf2ce5 fix some warning about unaligned 32b reads +922268fd s/TIFF/WebP +fa8927ef Move ARGB->YUV functions from dec/vp8l.c to dsp/yuv.c +9b373598 Merge "for ReadXXXX() image-readers, use the value of pic->use_argb" +f7c507a5 Merge "remove unnecessary #include "yuv.h"" +7861578b for ReadXXXX() image-readers, use the value of pic->use_argb +14e4043b remove unnecessary #include "yuv.h" +469ba2cd vwebp: fix incorrect clipping w/NO_BLEND +4b9186b2 update issue tracker url +d64d376c change WEBP_ALIGN_CST value to 31 +f717b828 vp8l.c, cosmetics: fix indent after 95509f9 +927ccdc4 Merge "fix alignment of allocated memory in AllocateTransformBuffer" +fea94b2b fix alignment of allocated memory in AllocateTransformBuffer +5aa8d61f Merge "MIPS: rescaler code synced with C implementation" +e7fb267d MIPS: rescaler code synced with C implementation +93c86ed5 Merge "format_constants.h: MKFOURCC, correct cast" +5d791d26 format_constants.h: MKFOURCC, correct cast +65726cd3 dsp/lossless: Average2, make a constant unsigned +d26d9def Use __has_builtin to check clang support +12ec204e moved ALIGN_CST into util/utils.h and renamed WEBP_ALIGN_xxx +a2640838 Merge "rescaler: ~20% faster SSE2 implementation for lossless ImportRowExpand" +3fb600d5 Merge "wicdec: fix alpha detection w/64bpp BGRA/RGBA" +67c547fd rescaler: ~20% faster SSE2 implementation for lossless ImportRowExpand +99e3f812 Merge "large re-organization of the delta-palettization code" +95509f99 large re-organization of the delta-palettization code +74fb458b fix for weird msvc warning message +ae49ad86 Merge "SSE2 implementation of ImportRowShrink" +932fd4df SSE2 implementation of ImportRowShrink +badfcbaa wicdec: fix alpha detection w/64bpp BGRA/RGBA +35cafa6c Merge "iosbuild: fix linking with Xcode 7 / iOS SDK 9" +b0c9d8af label rename: NO_CHANGE -> NoChange +b4e731cd neon-implementation for rescaler code +db1321a6 iosbuild: fix linking with Xcode 7 / iOS SDK 9 +6dfa5e3e rescaler: better handling of the fxy_scale=0 special case. +55c05293 Revert "rescaler: better handling of the fxy_scale=0 special case." +9f226bf8 rescaler: better handling of the fxy_scale=0 special case. +f7b8f907 delta_palettization.*: add copyright +c1e1b710 Changed delta palette to compress better +0dd28267 Merge "Add delta_palettization feature to WebP" +48f66b66 Add delta_palettization feature to WebP +27933e2a anim_encoder: drop a frame if it has same pixels as the prev frame. +df9f6ec8 Merge "webpmux/DisplayInfo: send non-error output to stdout" +8af4993b Merge "rescaler_mips_dsp_r2: cosmetics, fix indent" +2b9d2495 Merge "rescaler: cosmetics, join two lines" +cc020a8c webpmux/DisplayInfo: send non-error output to stdout +a288e746 configure: add -Wshorten-64-to-32 +c4c3cf2d pngdec: fix type conversion warnings +bef8e97d webpmux: fix type conversion warning +5a84460d rescaler_mips_dsp_r2: cosmetics, fix indent +acde0aae rescaler: cosmetics, join two lines +306ce4fd rescaler: move the 1x1 or 2x1 handling one level up +cced974b remove _mm_set_epi64x(), which is too specific +56668c9f fix warnings about uint64_t -> uint32_t conversion +76a7dc39 rescaler: add some SSE2 code +1df1d0ee rescaler: harmonize function protos +9ba1894b rescaler: simplify ImportRow logic +5ff0079e fix rescaler vertical interpolation +cd82440e VP8LAllocateHistogramSet: align histogram[] entries +a406b1dd Merge "fix memory over-allocation in lossless rescaler init" +0fde33e3 add missing const in VP8InitFrame signature +ac7d5e8d fix memory over-allocation in lossless rescaler init +017f8ccc Loosen the buffer size checks for Y/U/V/A too. +15ca5014 loosen the padding check on buffer size +d623a870 dec_neon: add whitespace around stringizing operator +29377d55 dsp/mips: cosmetics: add whitespace around XSTR macro +eebaf97f dsp/mips: add whitespace around stringizing operator +d39dc8f3 Create a WebPAnimDecoder API. +03fb7522 gif2webp: print output file size +14efabbf Android: limit use of cpufeatures +7b83adbe preparatory cosmetics for Rescaler code fix and clean-up +77fb41c2 dec/vp8l/DecodeAlphaData: remove redundant cast +90fcfcd9 Insert less hash chain entries from the beginnings of long copies. +bd55604d SSE2: add yuv444 converters, re-using yuv_sse2.c +41a5d99d add a -quiet option to 'dwebp' +80ab3edb Merge "README: update dwebp help output after 1e595fe" +32b71b2e README: update dwebp help output after 1e595fe +3ec11827 use the DispatchAlpha() call from dsp +c5f00621 incorporate bzero() into WebPRescalerInit() instead of call site +3ebcdd41 remove duplicate "#include " +1e595fe1 dwebp: add -resize as a synonym for -scale +24a96932 dec: allow 0 as a scaling dimension +b9187242 utils/rescaler: add WebPRescalerGetScaledDimensions +923e8eda Merge "update NEWS" +020fd099 Merge "WebPPictureDistortion: support ARGB format for 'pic' when computing distortion." +6a5292f6 update NEWS +56a2e9f5 WebPPictureDistortion: support ARGB format for 'pic' when computing distortion. +0ae582e4 configure: test and add -Wunreachable-code +c2f9dc06 bit_writer: convert VP8L macro values to immediates +b969f888 Reduce magic in palette reordering +acb297e9 anim_diff: add a -raw_comparison flag +155c1b22 Merge changes I76f4d6fe,I45434639 +717e4d5a mips32/mipsDSPr2: function ImportRow rebased +7df93893 fix rescaling bug (uninitialized read, see bug #254). +5cdcd561 lossless_enc_neon: add VP8LTransformColor +a53c3369 lossless_neon: add VP8LTransformColorInverse +99131e7f Merge changes I9fb25a89,Ibc648e9e +c4556766 simplify the main loop for downscaling +2a010f99 lossless_neon: remove predictors 5-13 +ca221bbc ll_enc_neon: enable VP8LSubtractGreenFromBlueAndRed +585d93db Container spec: clarify ordering of ALPH chunk. +01d61fd9 lossless: ~20 % speedup +f722c8f0 lossless: Speed up ComputeCacheEntropy by 40 % +1ceecdc8 add a VP8LColorCacheSet() method for color cache +17eb6099 lossless: Allow copying from prev row in rle-mode. +f3a7a5bf lossless: bit writer optimization +d97b9ff7 Merge changes from topic 'lossless-enc-improvements' +0250dfcc msvc: fix pointer type warning in BitsLog2Floor +52931fd5 lossless: combine the Huffman code with extra bits +c4855ca2 lossless: Inlining add literal +8e9c94de lossless: simplify HashChainFindCopy heuristics +888429f4 lossless: 0.5 % compression density improvement +7b23b198 lossless: Add zeroes into the predicted histograms. +85b44d8a lossless: encoding, don't compute unnecessary histo +d92453f3 lossless: Remove about 25 % of the speed degradation +2cce0317 Faster alpha coding for webp +5e75642e lossless: rle mode not to accept lengths smaller than 4. +84326e4a lossless: Less code for the entropy selection +16ab951a lossless: 0.37 % compression density improvement +822f113e add WebPFree() to the API +0ae2c2e4 SSE2/SSE41: optimize SSE_16xN loops +39216e59 cosmetics: fix indent after 32462a07 +559e54ca Merge "SSE2: slightly faster FTransformWHT" +8ef9a63b SSE2: slightly faster FTransformWHT +f27f7735 lossless_neon: enable VP8LAddGreenToBlueAndRed +36e9c4bc SSE2: minor cosmetrics on in-loop filter code +4741fac4 dsp/lossless_*sse2: remove some unnecessary inlines +1819965e fix warning ("left shift of negative value") using a cast +70170014 SSE2: speed-up some lossless-encoding functions +abcb0128 Merge "SSE2: slightly faster (~5%) AddGreenToBlueAndRed()" +2df5bd30 Merge "Speedup to HuffmanCostCombinedCount" +9e356d6b SSE2: slightly faster (~5%) AddGreenToBlueAndRed() +fc6c75a2 SSE2: 53% faster TransformColor[Inverse] +49073da6 SSE2: 46% speed-up of TransformColor[Inverse] +32462a07 Speedup to HuffmanCostCombinedCount +f3d687e3 SSE4.1 implementation of some lossless encoding functions +bfc300c7 SSE4.1 implementation of some alpha-processing functions +7f9c98f2 Merge "sse2 in-loop: simplify SignedShift8b() a bit" +ef314a5d dec_sse2/GetNotHEV: micro optimization +a729cff9 sse2 in-loop: simplify SignedShift8b() a bit +422ec9fb simplify Load8x4() a bit +8df238ec Merge "remove some duplicate FlipSign()" +751506c4 remove some duplicate FlipSign() +65ef5afc Merge "lossless: 0.13% compression density gain" +2beef2f2 lossless: 0.13% compression density gain +3033f24c lossless: 0.06 % compression density improvement +64960da9 dec_neon: add VE8uv / VE16 +14dbd87b dec_neon: add HE8uv / HE16 +ac768011 introduce FTransform2 to perform two transforms at a time. +aa6065ae dec_neon: use vld1_dup(mem) rather than vdup(mem[0]) +8b63ac78 Merge "dec_neon: add TM16" +f51be09e Merge "dec_neon/TrueMotion: simply left border load" +dc48196b dec_neon: add TM16 +ea95b305 dec_neon/TrueMotion: simply left border load +f262d612 speed-up SetResidualSSE2 +bf46d0ac fix mips2 build target +929a0fdc enc_sse2/TTransform: simplify abs calculation +17dbd058 enc_sse2/CollectHistogram: simplify abs calculation +a6c15936 dec_neon: add DC16 intra predictors +03b4f50d Makefile.vc: add anim_diff build support. +1b989874 Merge changes I9cd84125,Iee7e387f,I7548be72 +acd7b5af Introduce a test tool anim_diff. +f274a96c dsp/enc_sse2: add luma4 intra predictors +040b11bd dsp/enc_sse2: add chroma intra predictors +aee021bb dsp/enc_sse2: add luma16 intra predictors +9e00a499 makefile.unix: remove superclean target +cefc9c09 makefile.unix: clean up after extras target +4c9af023 dec_neon: add DC8uvNoTopLeft +dd55b873 Merge "doc/webp-container-spec: update repo browser link" +f0486968 doc/webp-container-spec: update repo browser link +9287761d Merge "GetResidualCostSSE2: simplify abs calculation" +0e009366 dsp/cpu.c(x86): check maximum supported cpuid feature +b243a4bc GetResidualCostSSE2: simplify abs calculation +6d4602b8 Merge "fix typo: constitutes -> constitute" +5fe1fe37 fix typo: constitutes -> constitute +b83bd7c4 Merge "populate 'libwebpextras' with: import gray, rgb565 and rgb4444 functions" +b0114a32 Merge "histogram.h: cosmetics: remove unnecessary includes" +feab45ef gifdec: Move inclusion of webp/config.h to header. +dbba67d1 histogram.h: cosmetics: remove unnecessary includes +e978fec6 Merge "VP8LBitReader: fix remaining ubsan error with large shifts" +d6fe5884 Merge "ReconstructRow: move some one-time inits out of the main loop" +a21d647c ReconstructRow: move some one-time inits out of the main loop +7a01c3c3 VP8LBitReader: fix remaining ubsan error with large shifts +7fa67c9b change GetPixPairHash64() return type to uint32_t +ec1fb9f8 Merge "dsp/enc.c: cosmetics: move DST() def closer to use" +7073bfb3 Merge "split 64-mult hashing into two 32-bit multiplies" +0768b252 dsp/enc.c: cosmetics: move DST() def closer to use +6a48b8f0 Merge "fix MSVC size_t->int conversion warning" +1db07cde Merge "anim_encode: cosmetics: fix alignment" +e28271a3 anim_encode: cosmetics: fix alignment +7fe357b8 split 64-mult hashing into two 32-bit multiplies +af74c145 populate 'libwebpextras' with: import gray, rgb565 and rgb4444 functions +61214134 remove VP8Residual::cost unused field +e2544823 fix MSVC size_t->int conversion warning +b69a6c35 vwebp: don't redefine snprintf with VS2015+ +0ac29c51 AnimEncoder API: Consistent use of trailing underscores in struct. +d4845550 AnimEncoder API: Use timestamp instead of duration as input to Add(). +9904e365 dsp/dec_sse2: DC8uv / DC8uvNoLeft speedup +7df20497 dsp/dec_sse2: DC16 / DC16NoLeft speedup +8e515dfe Merge "makefile.unix: add some missing headers" +db12250f cosmetics: vp8enci.h: break long line +bf516a87 makefile.unix: add some missing headers +b44eda3f dsp: add DSP_INIT_STUB +03e76e96 clarify the comment about double-setting the status in SetError() +9fecdd71 remove unused EmitRGB() +43f010dd move ReconstructRow to top +82d98020 add a dec/common.h header to collect common enc/dec #defines +5d4744a2 Merge "enc_sse41: add Disto4x4 / Disto16x16" +e38886a7 mux.h: Bump up ABI version +46305ca6 configure: add --disable- +2fc8b658 CPPFLAGS->CFLAGS for detecting sse4.1 in preprocessor +1a338fb3 enc_sse41: add Disto4x4 / Disto16x16 +94055503 encoding SSE4.1 stub for StoreHistogram + Quantize + SSE_16xN +c64659e1 remove duplicate variables after the lossless{_enc}.c split +67ba7c7a enc_sse2: call local FTransform in CollectHistogram +18249799 dsp: s/VP8LSetHistogramData/VP8SetHistogramData/ +ede5e158 cosmetics: dsp/lossless.h: reorder prototypes +553051f7 dsp/lossless: split enc/dec functions +9064adc8 Merge "conditionally add -msse4.1 in Makefile.unix" +cecf5096 dsp/yuv*.c: rework WEBP_USE_ ifdef +6584d398 dsp/upsampling*.c: rework WEBP_USE_ ifdef +80809422 dsp/rescaler*.c: rework WEBP_USE_ ifdef +1d93ddec dsp/lossless*.c: rework WEBP_USE_ ifdef +73805ff2 dsp/filters*.c: rework WEBP_USE_ ifdef +fbdcef24 dsp/enc*.c: rework WEBP_USE_ ifdef +66de69c1 dsp/dec*.c: rework WEBP_USE_ ifdef +48e4ffd1 dsp/cost*.c: rework WEBP_USE_ ifdef +29fd6f90 dsp/argb*.c: rework WEBP_USE_ ifdef +80ff3813 dsp/alpha*.c: rework WEBP_USE_ ifdef +bf09cf1e conditionally add -msse4.1 in Makefile.unix +e9570dd9 stub for SSE4.1 support. +4a95384b Merge "dsp: add sse4.1 detection" +cabf4bd2 dsp: add sse4.1 detection +4ecba1ab thread.h: rename interface param +b8d706c8 Merge "sync versions with 0.4.3" +ae64a711 Merge "add shell for libwebpextras" +92a5da9c sync versions with 0.4.3 +9d4e2d16 Merge "~30% faster smart-yuv (-pre 4) with early-out criterion" +b1bdbbab ~30% faster smart-yuv (-pre 4) with early-out criterion +7efb9748 Merge "Disable NEON code on Native Client" +ac4f5784 Disable NEON code on Native Client +0873f85b AnimEncoder API: Support input frames in YUV(A) format. +5c176d2d add shell for libwebpextras +44bd9561 fix signature for VP8RecordCoeffTokens() +c9b8ea0e small cosmetics on TokenBuffer. +76394c09 Merge "MIPS: dspr2: added optimization for TrueMotion" +0f773693 WebPPictureRescale: add a note about 0 width/height +241bb5d9 MIPS: dspr2: added optimization for TrueMotion +6cef0e4f examples/Android.mk: add webpmux_example target +53c16ff0 Android.mk: add webpmux target +21852a00 Android.mk: add webpdemux target +8697a3bc Android.mk: add webpdecoder{,_static} targets +4a670491 Android.mk: split source lists per-directory +b5e79422 MIPS: dspr2: Added optimization for some convert functions +0f595db6 MIPS: dspr2: Added optimization for some convert functions +8a218b4a MIPS: [mips32|dspr2]: GetResidualCost rebased +ef987500 Speedup method StoreImageToBitMask by 5%. +602a00f9 fix iOS arm64 build with Xcode 6.3 +23820507 1-2% faster encoding by removing an indirection in GetResidualCost() +eddb7e70 MIPS: dspr2: added otpimization for DC8uv, DC8uvNoTop and DC8uvNoLeft +73ba2915 MIPS: dspr2: added optimization for functions RD4 and LD4 +c7129da5 Merge "4-5% faster encoding using SSE2 for GetResidualCost" +94380d00 MIPS: dspr2: added optimizaton for functions VE4 and DC4 +2a407092 4-5% faster encoding using SSE2 for GetResidualCost +17e19862 Merge "MIPS: dspr2: added optimization for simple filtering functions" +3ec404c4 Merge "dsp: normalize WEBP_TSAN_IGNORE_FUNCTION usage" +b969f5df dsp: normalize WEBP_TSAN_IGNORE_FUNCTION usage +d7b8e711 MIPS: dspr2: added optimization for simple filtering functions +235f774e Merge "MIPS: dspr2: Added optimization for function VP8LTransformColorInverse_C" +42a8a628 MIPS: dspr2: Added optimization for function VP8LTransformColorInverse_C +b442bef3 Merge "ApplyFiltersAndEncode: only copy lossless stats" +b510fbfe doc/webp-container-spec: note MSB order for chunk diagrams +9bc0f922 ApplyFiltersAndEncode: only copy lossless stats +3030f115 Merge "dsp/mips: add some missing TSan annotations" +dfcf4593 Merge "MIPS: dspr2: Added optimization for function VP8LAddGreenToBlueAndRed_C" +55c75a25 dsp/mips: add some missing TSan annotations +2cb879f0 MIPS: dspr2: Added optimization for function VP8LAddGreenToBlueAndRed_C +e1556010 move some cost tables from enc/ to dsp/ +c3a03168 Merge "picture_csp: fix build w/USE_GAMMA_COMPRESSION undefined" +39537d7c Merge "VP8LDspInitMIPSdspR2: add missing TSan annotation" +1dd419ce picture_csp: fix build w/USE_GAMMA_COMPRESSION undefined +43fd3543 VP8LDspInitMIPSdspR2: add missing TSan annotation +c7233dfc Merge "VP8LDspInit: remove memcpy" +0ec4da96 picture_csp::InitGammaTables*: add missing TSan annotations +35579a49 VP8LDspInit: remove memcpy +97f6aff8 VP8YUVInit: add missing TSan annotation +f9016d66 dsp/enc::InitTables: add missing TSan annotation +e3d9771a VP8EncDspCostInit*: add missing TSan annotations +d97c143d Merge "doc/webp-container-spec: cosmetics" +309b7908 MIPS: mips32: Added optimization for function SetResidualCoeffs +a987faed MIPS: dspr2: added optimization for function GetResidualCost +e7d3df23 doc/webp-container-spec: cosmetics +be6635e9 Merge "VP8TBufferClear: remove some misleading const's" +02971e72 Merge "VP8EmitTokens: remove unnecessary param void cast" +3b77e5a7 VP8TBufferClear: remove some misleading const's +aa139c8f VP8EmitTokens: remove unnecessary param void cast +c24d8f14 cosmetics: upsampling_sse2: add const to some casts +1829c42c cosmetics: lossless_sse2: add const to some casts +183168f3 cosmetics: enc_sse2: add const to some casts +860badca cosmetics: dec_sse2: add const to some casts +0254db97 cosmetics: argb_sse2: add const to some casts +1aadf856 cosmetics: alpha_processing_sse2: add const to some casts +1579de3c vwebp: clear canvas at the beginning of each loop +4b9fa5d0 Merge "webp-container-spec: clarify background clear on loop" +4c82284d Updated the near-lossless level mapping. +56039479 webp-container-spec: clarify background clear on loop +19f0ba0e Implement true-motion prediction in SSE2 +774d4cb7 make VP8PredLuma16[] array non-const +d7eabb80 Merge "MIPS: dspr2: Added optimization for function CollectHistogram" +fe42739c Use integers for kmin/kmax for simplicity. +b9df35f7 AnimEncode API: kmax=0 should imply all keyframes. +6ce296da MIPS: dspr2: Added optimization for function CollectHistogram +2c906c40 vwebp: remove unnecessary static Help() prototype +be0fd1d5 Merge "dec/vp8: clear 'dither_' on skipped blocks" +e96170fe Merge "vwebp/animation: display last frame on end-of-loop" +0f017b56 vwebp/animation: display last frame on end-of-loop +c86b40cc enc/near_lossless.c: fix alignment +66935fb9 dec/vp8: clear 'dither_' on skipped blocks +b7de7946 Merge "lossless_neon: enable subtract green for aarch64" +77724f70 SSE2 version of GradientUnfilter +416e1cea lossless_neon: enable subtract green for aarch64 +72831f6b Speedup AnalyzeAndInit for low effort compression. +a6597483 Speedup Analyze methods for lossless compression. +98c81386 Enable Near-lossless feature. +c6b24543 AnimEncoder API: Fix for kmax=1 and default kmin case. +022d2f88 add SSE2 variants for alpha filtering functions +2db15a95 Temporarily disable encoding of alpha plane with color cache. +1d575ccd Merge "Lossless decoding: Remove an unnecessary if condition." +cafa1d88 Merge "Simplify backward refs calculation for low-effort." +7afdaf84 Alpha coding: reorganize the filter/unfiltering code +4d6d7285 Simplify backward refs calculation for low-effort. +ec0d1be5 Cleaup Near-lossless code. +9814ddb6 Remove the post-transform near-lossless heuristic. +4509e32e Lossless decoding: Remove an unnecessary if condition. +f2ebc4a8 Merge "Regression fix for lossless decoding" +783a8cda Regression fix for lossless decoding +9a062b8e AnimEncoder: Bugfix for kmin = 1 and kmax = 2. +0f027a72 simplify smart RGB->YUV conversion code +0d5b334e BackwardReferencesHashChainFollowChosenPath: remove unused variable +f480d1a7 Fix to near lossless artefacts on palettized images. +d4615d08 Merge changes Ia1686828,I399fda40 +cb4a18a7 rename HashChainInit into HashChainReset +f079e487 use uint16_t for chosen_path[] +da091212 MIPS: dspr2: Added optimization for function FTransformWHT +b8c20135 Merge "wicdec: (msvs) quiet some /analyze warnings" +9b228b54 wicdec: (msvs) quiet some /analyze warnings +daeb276a Merge "MIPS: dspr2: Added optimization for MultARGBRow function" +cc087424 Merge "dsp/cpu: (msvs) add include for __cpuidex" +4a82aab5 Merge changes I87544e92,I0bb6cda5 +7a191398 dwebp/WritePNG: mark png variables volatile +775dfad2 dwebp: include setjmp.h w/WEBP_HAVE_PNG +47d26be7 dwebp: correct sign in format strings +f0e0677b VP8LEncodeStream: add an assert +c5f7747f VP8LColorCacheCopy: promote an int before shifting +0de5f33e dsp/cpu: (msvs) add include for __cpuidex +7d850f7b MIPS: dspr2: Added optimization for MultARGBRow function +54875293 MIPS: dspr2: added optimization for function QuantizeBlock +4fbe9cf2 dsp/cpu: (msvs) avoid immintrin.h on _M_ARM +3fd59039 simplify/reorganize arguments for CollectColorBlueTransforms +b9e356b9 Disable costly TraceBackwards for method=0. +a7e7caa4 MIPS: dspr2: added optimization for function TransformColorRed +2cb39180 Merge "MIPS: dspr2: added optimization for function TransformColorBlue" +279e6613 Merge "dsp/cpu: add include for _xgetbv() w/MSVS" +b6c0428e dsp/cpu: add include for _xgetbv() w/MSVS +d1c4ffae gif2webp: Move GIF decoding related code to a support library. +07c39559 Merge "AnimEncoder API: Add info in README.mux" +7b161973 MIPS: dspr2: added optimization for function TransformColorBlue +d7c4b02a cpu: fix AVX2 detection for gcc/clang targets +9d299469 AnimEncoder API: Add info in README.mux +d581ba40 follow-up: clean up WebPRescalerXXX dsp function +f8740f0d dsp: s/USE_INTRINSICS/WEBP_USE_INTRINSICS/ +ce73abe0 Merge "introduce a separate WebPRescalerDspInit to initialize pointers" +ab66beca introduce a separate WebPRescalerDspInit to initialize pointers +205c7f26 fix handling of zero-sized partition #0 corner case +cbcdd5ff Merge "move rescaler functions to rescaler* files in src/dsp/" +bf586e88 Merge changes I230b3532,Idf3057a7 +6dc79dc2 Merge "anim_encode: fix type conversion warnings" +11fce25a Merge "dec_neon: remove returns from void functions" +c4e63f99 Makefile.vc: add gif2webp target +4f43d38c enable NEON for Windows ARM builds +3f6615ac Makefile.vc: add rudimentary Windows ARM support +e7c5954c dec_neon: remove returns from void functions +f79c163b anim_encode: fix type conversion warnings +0f54f1ec Remove gif2webp_util which is no longer needed. +cbcbedd0 move rescaler functions to rescaler* files in src/dsp/ +ac79ed19 webpmux: remove experimental fragment handling +e8694d4d mux: remove experimental FRGM parsing +9e92b6ea AnimEncoder API: Optimize single-frame animated images +abbae279 Merge "Move over gif2webp to the new AnimEncoder API." +a28c4b36 MIPS: move WORK_AROUND_GCC define to appropriate place +012d2c60 MIPS: dspr2: added optimization for functions SSEAxB +67720c8b Move over gif2webp to the new AnimEncoder API. +9241ecf4 MIPS: dspr2: added optimization for function Average +9422211d Merge "Tune BackwardReferencesLz77 for low_effort (m=0)." +df40057b Merge "Speedup VP8LGetHistoImageSymbols for low effort (m=0) mode." +ea08466d Tune BackwardReferencesLz77 for low_effort (m=0). +b0b973c3 Speedup VP8LGetHistoImageSymbols for low effort (m=0) mode. +c6d32927 argb_sse2: cosmetics +67f601cd make the 'last_cpuinfo_used' variable names unique +b9489861 AnimEncoder API: Init method for default options. +856f8ec1 Merge "AnimEncoder API: Remove AnimEncoderFrameOptions." +c537514d Merge "AnimEncoder API: GenerateCandidates bugfix." +dc0ce039 Merge "AnimEncoder API: Compute change rectangle for first frame too." +f00b639b Merge "AnimEncoder API: In Assemble(), always set animation parameters." +29ed796c Merge "AnimEncoder lib cleanup: prev to prev canvas not needed." +9f0dd6e5 Merge "WebPAnimEncoder API: Header and implementation" +5e56bbe0 AnimEncoder API: Remove AnimEncoderFrameOptions. +b902c3ea AnimEncoder API: GenerateCandidates bugfix. +ef3c39bb AnimEncoder API: Compute change rectangle for first frame too. +eec423ab AnimEncoder API: In Assemble(), always set animation parameters. +ae1c046e AnimEncoder lib cleanup: prev to prev canvas not needed. +4b997ae4 WebPAnimEncoder API: Header and implementation +72208bec move argb_*.o build target to encoder list +95920538 Merge "multi-thread fix: lock each entry points with a static var" +4c1b300a Merge "SSE2 implementation of VP8PackARGB" +fbcc2004 Merge "add -Wformat-nonliteral and -Wformat-security" +80d950d9 add -Wformat-nonliteral and -Wformat-security +04c20e75 Merge "MIPS: dspr2: added optimization for function Intra4Preds" +a437694a multi-thread fix: lock each entry points with a static var +ca7f60db SSE2 implementation of VP8PackARGB +72d573f6 simplify the PackARGB signature +4e2589ff demux: restore strict fragment flag check +4ba8e074 Merge "webp-container-spec: remove references to fragments" +e752f0a6 Merge "demux: remove experimental FRGM parsing" +f8abb112 Merge changes I109ec4d9,I73fe7743 +ae2188a4 MIPS: dspr2: added optimization for function Intra4Preds +1f4b8642 move VP8EncDspARGBInit() call closer to where it's needed +14108d78 dec_neon: add DC8uvNoTop / DC8uvNoLeft +d8340da7 dec_neon: add DC8uv +a66e66c7 webp-container-spec: remove references to fragments +7ce8788b MIPS: dspr2: added optimization for function MakeARGB32 +012e623d demux: remove experimental FRGM parsing +87c3d531 method=0: Don't evaluate any predictor +6f4fcb98 Merge "MIPS: dspr2: added optimization for function ImportRow" +24284459 replace unneeded calls to HistogramCopy() by swaps +bdf7b40c MIPS: dspr2: added optimization for function ImportRow +e66a9225 Merge "MIPS: dspr2: added optimization for function ExportRowC" +c279fec1 MIPS: dspr2: added optimization for function ExportRowC +31a9cf64 Speedup WebP lossless compression for low effort (m=0) mode with following: - Disable Cross-Color transform. - Evaluate predictors #11 (paeth), #12 and #13 only. +9275d91c MIPS: dspr2: added optimization for function TrueMotion +26106d66 Merge "enc_neon: fix building with non-Xcode clang (iOS)" +1c4e3efe unroll the kBands[] indirection to remove a dereference in GetCoeffs() +a3946b89 enc_neon: fix building with non-Xcode clang (iOS) +8ed9c00d Merge "simplify the Histogram struct, to only store max_value and last_nz" +bad77571 simplify the Histogram struct, to only store max_value and last_nz +3cca0dc7 MIPS: dspr2: Added optimization for DCMode function +37e395fd MIPS: fix functions to use generic BPS istead of hardcoded value +9475bef4 PickBestUV: fix VP8Copy16x8 invocation +441f273f Merge changes I55f8da52,Id73a1e96 +4a279a68 cosmetics: add some missing != NULL comparisons +66ad3725 factorize BPS definition in dsp.h and add VP8Copy16x8 +432e5b55 make ALIGN_xxx naming consistent +57606047 encoder: switch BPS to 32 instead of 16 +1b66bbe9 MIPS: dspr2: added optimization for function TransformColor_C +c6d0f9e7 histogram: cosmetics +f399d307 Merge changes I6eac17e5,I32d2b514 +9de9074c dec_neon: add TM8uv +8e517eca bit_reader/kVP8NewRange: range_t -> uint8_t +e1857139 dsp: initialize VP8PredChroma8 in VP8DspInit() +e0c809ad Move Entropy methods to lossless.c +a96ccf8f iosbuild: add x64_64 simulator support +a0df5510 Remove handling for WEBP_HINT_GRAPH +413dfc0c Move static method definition before its usage. +0f235665 Update BackwardRefsWithLocalCache. +d69e36ec Remove TODOs from lossless encoder code. +fdaac8e0 Optmize VP8LGetBackwardReferences LZ77 references. +2f0e2ba8 MIPS: dspr2: added optimization for function Select +a3e79a46 Merge "WebPEncode: Support encoding same pic twice (even if modified)" +e4f4dddb WebPEncode: Support encoding same pic twice (even if modified) +cbc3fbb4 Merge "Updated VP8LGetBackwardReferences and color cache." +95a9bd85 Updated VP8LGetBackwardReferences and color cache. +54f2c14c MIPS: dspr2: added optimization for function FTransform +aa42f423 MIPS: dspr2: Added optimization for function VP8LSubtractGreenFromBlueAndRed +11a25f75 Merge "FlattenSimilarBlocks should only be tried when blending is possible." +5cccdadf FlattenSimilarBlocks should only be tried when blending is possible. +95ca44a7 MIPS: dspr2: added optimization for Disto4x4 +4171b672 backward_references.c: reindent after c8581b0 +c8581b06 Optimize BackwardReferences for RLE encoding. +5798eee6 MIPS: dspr2: unfilters bugfix (Ie7b7387478a6b5c3f08691628ae00f059cf6d899) +4167a3f5 Optimize backwardreferences +d18554c3 Merge "webp/types.h: use inline for clang++/-std=c++11" +7489b0e7 gif2webp: Add '-min-size' option to get best compression. +77bdddf0 Speed up BackwardReferences +6638710b webp/types.h: use inline for clang++/-std=c++11 +abf04205 Enable entropy based merge histo for (q<100) +572022a3 filters_mips_dsp_r2.c: disable unfilters +a28e21b1 MIPS: dspr2: Added optimization for function ClampedAddSubtractFull +18d5a1ef MIPS: dspr2: added optimization for function ClampedAddSubtractHalf +829a8c19 MIPS: dspr2: added optimization for ITransform +c94ed49e gif2webp: Use the default hint instead of WEBP_HINT_GRAPH. +653ace55 Increase the MAX_COLOR_CACHE_BITS from 9 to 10. +919220c7 Change the logic adjusting the Histogram bits. +53b096c0 Merge "Fix bug in VP8LCalculateEstimateForCacheSize." +e912bd55 Fix bug in VP8LCalculateEstimateForCacheSize. +541d7839 Merge "dec_neon: add RD4 intra predictor" +f8cd0672 Merge "Makefile.vc: add a 'legacy' RTLIBCFG option" +22881c99 dec_neon: add RD4 intra predictor +613d281e update NEWS +1304eb34 Merge "dec_neon: DC4: use pair-wise adds for top row" +34c20c06 Makefile.vc: add a 'legacy' RTLIBCFG option +7083006b Merge "dsp/dec_{neon,sse2}: VE4: normalize variable names" +0db9031c dsp/dec_{neon,sse2}: VE4: normalize variable names +b5bc1530 dec_neon: DC4: use pair-wise adds for top row +5b90d8fe Unify the API between VP8BitWriter and VP8LBitWriter +f7ada560 Merge changes I2e06907b,Ia9ed4ca6,I782282ff +5beb6bf0 Merge "dec_neon: add VE4 intra predictor" +eba6ce06 dec_neon: add DC4 intra predictor +79abfbd9 dec_neon: add TM4 intra predictor +fe395f0e dec_neon: add LD4 intra predictor +32de385e dec_neon: add VE4 intra predictor +72395ba9 Merge "Modify CostModel to allocate optimal memory." +65e5eb8a gif2webp: Support GIF_DISPOSE_RESTORE_PREVIOUS +e4c829ef gif2webp: Handle frames with odd offsets + disposal to background. +c2b5a039 Modify CostModel to allocate optimal memory. +b7a33d7e implement VE4/HE4/RD4/... in SSE2 +97c76f1f make VP8PredLuma4[] non-const and initialize array in VP8DspInit() +0ea8c6c2 Merge "PrintReg: output to stderr" +d7ff2f97 Merge "stopwatch.h: fix includes" +f85ec712 PrintReg: output to stderr +54edbf65 stopwatch.h: fix includes +139142e4 Optimize BackwardReferenceHashChainFollowPath. +5f36b68d enc/backward_references.c: fix indent +e0e9960d Merge "sync version numbers to 0.4.2 release" +64ac5144 sync version numbers to 0.4.2 release +c24f8954 Simplify and speedup Backward refs computation. +d1c359ef fix shared object build with -fvisibility=hidden +a4c3a31b WEBP_TSAN_IGNORE_FUNCTION: fix gcc compat warning +f358eeb8 add code for testing random incremental decoding in dwebp +80247291 mark some init function as being safe for thread_sanitizer. +79b5bdbf bit_reader.h: cosmetics: fix a typo +6c673681 Improved near-lossless mode. +0ce27e71 enc_mips32: workaround gcc-4.9 bug +aca1b98f enc/vp8l.c: fix indent +ca005027 Evaluate non-palette compression for palette image +c8a87bb6 AssignSegments: quiet -Warray-bounds warning +32f67e30 Merge "enc_neon: initialize vectors w/vdup_n_u32" +fabc65da 1-3% faster encoding optimizing SSE_NxN functions +7534d716 enc_neon: initialize vectors w/vdup_n_u32 +5f813912 Merge "Fix return code of EncodeImageInternal()" +e321abe4 Fix return code of EncodeImageInternal() +f82cb06a optimize palette ordering +f545feee don't set the alpha value for histogram index image +2d9b0a44 add WebPDispatchAlphaToGreen() to dsp +1bd4c2ad Merge "Change Entropy based Histogram Combine heuristic." +e295b8f1 Merge "iosbuild: cleanup" +1be4e760 Merge "iosbuild: output autoconf req. on failure" +d5e498d4 Change Entropy based Histogram Combine heuristic. +47a2d8e1 fix MSVC float->int conversion warning +041956f6 iosbuild: cleanup +767eb402 iosbuild: output autoconf req. on failure +35ad48b8 HistoHeapInit: correct positions allocation size +45d9635f lossless: entropy clustering for high qualities. +dc37df8c fix type warning for VS9_x64 +9f7d9e6d iosbuild: make iOS 6 the minimum requirement +fdd6528b Remove unused VP8LDecoder member variable +ea3bba5a Merge "rewrite Disto4x4 in enc_neon.c with intrinsic" +f060dfc4 add lossless incremental decoding support +ab70794d rewrite Disto4x4 in enc_neon.c with intrinsic +d4471637 MIPS: dspr2: added optimization for function FilterLoop24 +2aef54d4 Merge "prepare VP8LDecodeImage for incremental decode" +aed0f5a2 Merge "MIPS: dspr2: added optimization for function FilterLoop26" +28630685 prepare VP8LDecodeImage for incremental decode +248f3aed remove br->error_ field +49e15044 MIPS: dspr2: added optimization for function FilterLoop26 +38128cb9 iobuild.sh: only install .h files in Headers +c792d412 Premultiply with alpha during U/V downsampling +0cc811d7 gif2webp: Background color correction +d7167ff7 Amend the lossless spec according to issue #205, #206 and #224 +b901416b Record the lossless size stats. +cddd3340 Add a WebPExtractAlpha function to dsp +0716a98e fix indent after I0204949917836f74c0eb4ba5a7f4052a4797833b +f9ced95a Optimize lossless decoding for trivial(ARB) codes. +924fcfd9 Merge "webpmux: simplify InitializeConfig()" +c0a462ca webpmux: simplify InitializeConfig() +6986bb5e webpmux: fix indent +f89e1690 webpmux: fix exit status on numeric value parse error +2172cb62 Merge "webpmux: fix loop_count range check" +e3b343ec Merge "examples: warn on invalid numeric parameters" +0e23c487 webpmux: fix loop_count range check +6208338a Merge "fix loop bug in DispatchAlpha()" +d51f3e40 gif2webp: Handle frames with missing graphic control extension +690b491a fix loop bug in DispatchAlpha() +96d43a87 examples: warn on invalid numeric parameters +3101f537 MIPS: dspr2: added optimization for TransformOne +a6bb9b17 SSE2 for inverse Mult(ARGB)Row and ApplyAlphaMultiply +d84a8ffd Remove default initialization of decoder status. +be70b86c configure: simplify libpng-config invocation +e0a99321 Rectify bug in lossless incremental decoding. +e2502a97 MIPS: dspr2: added optimization for TransformAC3 +24e1072a MIPS: dspr2: added optimization for TransformDC +c0e84df8 Merge "Slightly faster lossless decoding (1%)" +8dd28bb5 Slightly faster lossless decoding (1%) +f0103595 MIPS: dspr2: added optimization for ColorIndexInverseTransforms +d3242aee make VP8LSetBitPos() set br->eos_ flag +a9decb55 Lossless decoding: fix eos_ flag condition +3fea6a28 fix erroneous dec->status_ setting +80b8099f MIPS: dspr2: add some specific mips code to commit I2c3f2b12f8df15b785fad5a9c56316e954ae0c53 +e5640625 Merge "further refine the COPY_PATTERN optim for DecodeAlpha" +854509fe enc/histogram.c: reindent after f4059d0 +34421964 Merge "~3-5% faster encoding optimizing PickBestIntra*()" +865069c1 further refine the COPY_PATTERN optim for DecodeAlpha +a5956228 added C-level optimization for DecodeAlphaData function +187d379d add a fallback to ALPHA_NO_COMPRESSION +a48a2d76 ~3-5% faster encoding optimizing PickBestIntra*() +a6140194 ExUtilReadFromStdin: (windows) open stdin in bin mode +e80eab1f webpmux: (windows) open stdout in binary mode +e9bfb116 cwebp: (windows) open stdout in binary mode +5927e15b example_util: add ExUtilSetBinaryMode +30f3b75b webpmux man page: Clarify some title, descriptions and examples +77d4c7e3 address cosmetic comments from patch #71380 +f75dfbf2 Speed up Huffman decoding for lossless +637b3888 dsp/lossless: workaround gcc-4.9 bug on arm +8323a903 dsp.h: collect gcc/clang version test macros +e6c4b52f move static initialization of WebPYUV444Converters[] to the Init function. +49911d4d Merge "fix indentation" +f4059d0c Code cleanup for HistogramRemap. +e632b092 fix indentation +f5c04d64 Merge "add a DispatchAlpha() for SSE2 that handles 8 pixels at a time" +fc98edd9 add a DispatchAlpha() for SSE2 that handles 8 pixels at a time +73d361dd introduce VP8EncQuantize2Blocks to quantize two blocks at a time +0b21c30b MIPS: dspr2: added optimization for EmitAlphaRGB +953acd56 enc_neon: enable QuantizeBlock for aarch64 +f4ae1437 MIPS: mips32: code rebase +56977154 MIPS: dspr2: added optimizations for VP8YuvTo* +2523aa73 SmartRGBYUV: fix odd-width problem with pixel replication +ee52dc4e fix some MSVC64 warning about float conversion +3fca851a cpu: check for _MSC_VER before using msvc inline asm +e2a83d71 faster RGB->YUV conversion function (~7% speedup) +de2d03e1 Merge "Add smart RGB->YUV conversion option -pre 4" +3fc4c539 Add smart RGB->YUV conversion option -pre 4 +b4dc4069 MIPS: dspr2: added optimization for (un)filters +137e6090 Merge "configure: add work around for gcc-4.9 aarch64 bug" +b61c9cec MIPS: dspr2: Optimization of some simple point-sampling functions +e2b8cec0 configure: add work around for gcc-4.9 aarch64 bug +98c54107 MIPS: mips32r2: added optimization for BSwap32 +dab702b3 Update PATENTS to reflect s/VP8/WebM/g +b564f7c7 Merge "MIPS: detect mips32r6 and disable mips32r1 code" +b7e5a5c4 MIPS: detect mips32r6 and disable mips32r1 code +63c2fc02 Correctly use the AC_CANONICAL_* macros +bb07022b Merge "cosmetics" +e300c9d8 cosmetics +0e519eea Merge "cosmetics: remove some extraneous 'extern's" +3ef0f08a Merge "vp8enci.h: cosmetics: fix '*' placement" +4c6dde37 bit_writer: cosmetics: rename kFlush() -> Flush() +f7b4c48b cosmetics: remove some extraneous 'extern's +b47fb00a vp8enci.h: cosmetics: fix '*' placement +b5a36cc9 add -near_lossless [0..100] experimental option +0524d9e5 dsp: detect mips64 & disable mips32 code +d3485d96 cwebp.1: fix quality description placement +29a9fe22 Merge tag 'v0.4.1' +8af27718 update ChangeLog (tag: v0.4.1, origin/0.4.1) +e09e9ff6 Record & log the image pre-processing time. +f59c0b4b iosbuild.sh: specify optimization flags +8d34ea3e update ChangeLog (tag: v0.4.1-rc1) +dbc3da66 makefile.unix: add vwebp.1 to the dist target +89a7c83c update ChangeLog +ffe67ee9 Merge "update NEWS for the next release" into 0.4.1 +2def1fe6 gif2webp: dust up the help message +fb668d78 remove -noalphadither option from README/vwebp.1 +e49f693b update NEWS for the next release +cd013580 Merge "update AUTHORS" into 0.4.1 +268d01eb update AUTHORS +85213b9b bump version to 0.4.1 +695f80ae Merge "restore mux API compatibility" into 0.4.1 +862d296c restore mux API compatibility +8f6f8c5d remove the !WEBP_REFERENCE_IMPLEMENTATION tweak in Put8x8uv +d713a696 Merge changes If4debc15,I437a5d5f into 0.4.1 +c2fc52e4 restore encode API compatibility +793368e8 restore decode API compatibility +b8984f31 gif2webp: fix compile with giflib 5.1.0 +222f9b1a gif2webp: simplify giflib version checking +d2cc61b7 Extend MakeARGB32() to accept Alpha channel. +4595b62b Merge "use explicit size of kErrorMessages[] arrays" +157de015 Merge "Actuate memory stats for PRINT_MEMORY_INFO" +fbda2f49 JPEG decoder: delay conversion to YUV to WebPEncode() call +0b747b1b use explicit size of kErrorMessages[] arrays +3398d81a Actuate memory stats for PRINT_MEMORY_INFO +6f3202be Merge "move WebPPictureInit to picture.c" +6c347bbb move WebPPictureInit to picture.c +fb3acf19 fix configure message for multi-thread +40b086f7 configure: check for _beginthreadex +1549d620 reorder the YUVA->ARGB and ARGB->YUVA functions correctly +c6461bfd Merge "extract colorspace code from picture.c into picture_csp.c" +736f2a17 extract colorspace code from picture.c into picture_csp.c +645daa03 Merge "configure: check for -Wformat-security" +abafed86 configure: check for -Wformat-security +fbadb480 split monolithic picture.c into picture_{tools,psnr,rescale}.c +c76f07ec dec_neon/TransformAC3: initialize vector w/vcreate +bb4fc051 gif2webp: Allow single-frame animations +46fd44c1 thread: remove harmless race on status_ in End() +5a1a7264 Merge "configure: check for __builtin_bswapXX()" +6781423b configure: check for __builtin_bswapXX() +6450c48d configure: fix iOS builds +6422e683 VP8LFillBitWindow: enable fast path for 32-bit builds +4f7f52b2 VP8LFillBitWindow: respect WEBP_FORCE_ALIGNED +e458badc endian_inl.h: implement htoleXX with BSwapXX +f2664d1a endian_inl.h: add BSwap16 +6fbf5345 Merge "configure: add --enable-aligned" +dc0f479d configure: add --enable-aligned +9cc69e2b Merge "configure: support WIC + OpenGL under mingw64" +257adfb0 remove experimental YUV444 YUV422 and YUV400 code +10f4257c configure: support WIC + OpenGL under mingw64 +380cca4f configure.ac: add AC_C_BIGENDIAN +ee70a901 endian_inl.h: add BSwap64 +47779d46 endian_inl.h: add BSwap32 +d5104b1f utils: add endian_inl.h +58ab6224 Merge "make alpha-detection loop in IsKeyFrame() in good x/y order" +9d562902 make alpha-detection loop in IsKeyFrame() in good x/y order +516971b1 lossless: Remove unaligned read warning +b8b596f6 Merge "configure.ac: add an autoconf version prerequisite" +34b02f8c configure.ac: add an autoconf version prerequisite +e59f5360 neon: normalize vdup_n_* usage +6ee7160d Merge changes I0da7b3d3,Idad2f278,I4accc305 +abc02f24 Merge "fix (uncompiled) typo" +bc03670f neon: add INIT_VECTOR4 +6c1c632b neon: add INIT_VECTOR3 +dc7687e5 neon: add INIT_VECTOR2 +4536e7c4 add WebPMuxSetCanvasSize() to the mux API +824eab10 fix (uncompiled) typo +1f3e5f1e remove unused 'shift' argument and QFIX2 define +8e867051 Merge "VP8LoadNewBytes: use __builtin_bswap32 if available" +1b6a2635 Merge "Fix handling of weird GIF with canvas dimension 0x0" +1da3d461 VP8LoadNewBytes: use __builtin_bswap32 if available +1582e402 Fix handling of weird GIF with canvas dimension 0x0 +b8811dac Merge "rename interface -> winterface" +db8b8b5f Fix logic in the GIF LOOP-detection parsing +25aaddc8 rename interface -> winterface +5584d9d2 make WebPSetWorkerInterface() check its arguments +a9ef7ef9 Merge "cosmetics: update thread.h comments" +c6af9991 Merge "dust up the help message" +0a8b8863 dust up the help message +a9cf3191 cosmetics: update thread.h comments +27bfeee4 QuantizeBlock SSE2 Optimization: +2bc0dc3e Merge "webpmux: warn when odd frame offsets are used" +3114ebe4 Merge changes Id8edd3c1,Id418eb96,Ide05e3be +c0726634 webpmux: warn when odd frame offsets are used +c5c6b408 Merge "add alpha dithering for lossy" +d5146784 examples/Android.mk: add cwebp +ca0fa7c7 Android.mk: move dwebp to examples/Android.mk +73d8fca0 Android.mk: add ENABLE_SHARED flag +6e93317f muxread: fix out of bounds read +8b0f6a48 Makefile.vc: fix CFLAGS assignment w/HAVE_AVX2=1 +bbe32df1 add alpha dithering for lossy +79020767 Merge "make error-code reporting consistent upon malloc failure" +77bf4410 make error-code reporting consistent upon malloc failure +7a93c000 **/Makefile.am: remove unused AM_CPPFLAGS +24e30805 Add an interface abstraction to the WebP worker thread implementation +d6cd6358 Merge "fix orig_rect==NULL case" +2bfd1ffa fix orig_rect==NULL case +059e21c1 Merge "configure: move config.h to src/webp/config.h" +f05fe006 properly report back encoding error code in WebPFrameCacheAddFrame() +32b31379 configure: move config.h to src/webp/config.h +90090d99 Merge changes I7c675e51,I84f7d785 +ae7661b3 makefiles: define WEBP_HAVE_AVX2 when appropriate +69fce2ea remove the special casing for res->first in VP8SetResidualCoeffs +6e61a3a9 configure: test for -msse2 +b9d2efc6 rename upsampling_mips32.c to yuv_mips32.c +bdfeebaa dsp/yuv: move sse2 functions to yuv_sse2.c +46b32e86 Merge "configure: set WEBP_HAVE_AVX2 when available" +88305db4 Merge "VP8RandomBits2: prevent signed int overflow" +73fee88c VP8RandomBits2: prevent signed int overflow +db4860b3 enc_sse2: prevent signed int overflow +3fdaf4d2 Merge "real fix for longjmp warning" +385e3340 real fix for longjmp warning +230a0555 configure: set WEBP_HAVE_AVX2 when available +a2ac8a42 restore original value_/range_ field order +5e2ee56f Merge "remove libwebpdspdecode dep on libwebpdsp_avx2" +61362db5 remove libwebpdspdecode dep on libwebpdsp_avx2 +42c447ae Merge "lossy bit-reader clean-up:" +479ffd8b Merge "remove unused #include's" +9754d39a Merge "strong filtering speed-up (~2-3% x86, ~1-2% for NEON)" +158aff9b remove unused #include's +09545eea lossy bit-reader clean-up: +ea8b0a17 strong filtering speed-up (~2-3% x86, ~1-2% for NEON) +6679f899 Optimize VP8SetResidualCoeffs. +ac591cf2 fix for gcc-4.9 warnings about longjmp + local variables +4dfa86b2 dsp/cpu: NaCl has no support for xgetbv +4c398699 Merge "cwebp: fallback to native webp decode in WIC builds" +33aa497e Merge "cwebp: add some missing newlines in longhelp output" +c9b340a2 fix missing WebPInitAlphaProcessing call for premultiplied colorspace output +57897bae Merge "lossless_neon: use vcreate_*() where appropriate" +6aa4777b Merge "(enc|dec)_neon: use vcreate_*() where appropriate" +0d346e41 Always reinit VP8TransformWHT instead of hard-coding +7d039fc3 cwebp: fallback to native webp decode in WIC builds +d471f424 cwebp: add some missing newlines in longhelp output +bf0e0030 lossless_neon: use vcreate_*() where appropriate +9251c2f6 (enc|dec)_neon: use vcreate_*() where appropriate +399b916d lossy decoding: correct alpha-rescaling for YUVA format +78c12ed8 Merge "Makefile.vc: add rudimentary avx2 support" +dc5b122f try to remove the spurious warning for static analysis +ddfefd62 Makefile.vc: add rudimentary avx2 support +a8911643 Merge "simplify VP8LInitBitReader()" +fdbcd44d simplify VP8LInitBitReader() +7c004287 makefile.unix: add rudimentary avx2 support +515e35cf Merge "add stub dsp/enc_avx2.c" +a05dc140 SSE2: yuv->rgb speed-up for point-sampling +178e9a69 add stub dsp/enc_avx2.c +1b99c09c Merge "configure: add a test for -mavx2" +fe728071 configure: add a test for -mavx2 +e46a247c cpu: fix check for __cpuidex availability +176fda26 fix the bit-writer for lossless in 32bit mode +541784c7 dsp.h: add a check for AVX2 / define WEBP_USE_AVX2 +bdb151ee dsp/cpu: add AVX2 detection +ab9f2f86 Merge "revamp the point-sampling functions by processing a full plane" +a2f8b289 revamp the point-sampling functions by processing a full plane +ef076026 use decoder's DSP functions for autofilter +2b5cb326 Merge "dsp/cpu: add AVX detection" +df08e67e dsp/cpu: add AVX detection +e2f405c9 Merge "clean-up and slight speed-up in-loop filtering SSE2" +f60957bf clean-up and slight speed-up in-loop filtering SSE2 +9fc3ae46 .gitattributes: treat .ppm as binary +3da924b5 Merge "dsp/WEBP_USE_NEON: test for __aarch64__" +c7164490 Android.mk: always include *_neon.c in the build +a577b23a dsp/WEBP_USE_NEON: test for __aarch64__ +54bfffca move RemapBitReader() from idec.c to bit_reader code +34168ecb Merge "remove all unused layer code" +f1e77173 remove all unused layer code +b0757db7 Code cleanup for VP8LGetHistoImageSymbols. +5fe628d3 make the token page size be variable instead of fixed 8192 +f948d08c memory debug: allow setting pre-defined malloc failure points +ca3d746e use block-based allocation for backward refs storage, and free-lists +1ba61b09 enable NEON intrinsics in aarch64 builds +b9d2bb67 dsp/neon.h: coalesce intrinsics-related defines +b5c75258 iosbuild: add support for iOSv7/aarch64 +9383afd5 Reduce number of memory allocations while decoding lossless. +888e63ed Merge "dsp/lossless: prevent signed int overflow in left shift ops" +8137f3ed Merge "instrument memory allocation routines for debugging" +2aa18736 instrument memory allocation routines for debugging +d3bcf72b Don't allocate VP8LHashChain, but treat like automatic object +bd6b8619 dsp/lossless: prevent signed int overflow in left shift ops +b7f19b83 Merge "dec/vp8l: prevent signed int overflow in left shift ops" +29059d51 Merge "remove some uint64_t casts and use." +e69a1df4 dec/vp8l: prevent signed int overflow in left shift ops +cf5eb8ad remove some uint64_t casts and use. +38e2db3e MIPS: MIPS32r1: Added optimization for HistogramAdd. +e0609ade dwebp: fix exit code on webp load failure +bbd358a8 Merge "example_util.h: avoid forward declaring enums" +8955da21 example_util.h: avoid forward declaring enums +6d6865f0 Added SSE2 variants for Average2/3/4 +b3a616b3 make HistogramAdd() a pointer in dsp +c8bbb636 dec_neon: relocate some inline-asm defines +4e393bb9 dec_neon: enable intrinsics-only functions +ba99a922 dec_neon: use positive tests for USE_INTRINSICS +69058ff8 Merge "example_util: add ExUtilDecodeWebPIncremental" +a7828e8b dec_neon: make WORK_AROUND_GCC conditional on version +3f3d717a Merge "enc_neon: enable intrinsics-only functions" +de3cb6c8 Merge "move LOCAL_GCC_VERSION def to dsp.h" +1b2fe14d example_util: add ExUtilDecodeWebPIncremental +ca49e7ad Merge "enc_neon: move Transpose4x4 to dsp/neon.h" +ad900abd Merge "fix warning about size_t -> int conversion" +4825b436 fix warning about size_t -> int conversion +42b35e08 enc_neon: enable intrinsics-only functions +f937e012 move LOCAL_GCC_VERSION def to dsp.h +5e1a17ef enc_neon: move Transpose4x4 to dsp/neon.h +c7b92a5a dec_neon: (WORK_AROUND_GCC) delete unused Load4x8 +8e5f90b0 Merge "make ExUtilLoadWebP() accept NULL bitstream param." +05d4c1b7 Merge "cwebp: add webpdec" +ddeb6ac8 cwebp: add webpdec +35d7d095 Merge "Reduce memory footprint for encoding WebP lossless." +0b896101 Reduce memory footprint for encoding WebP lossless. +f0b65c9a make ExUtilLoadWebP() accept NULL bitstream param. +9c0a60cc Merge "dwebp: move webp decoding to example_util" +1d62acf6 MIPS: MIPS32r1: Added optimization for HuffmanCost functions. +4a0e7390 dwebp: move webp decoding to example_util +c0220460 Merge "Bugfix: Incremental decode of lossy-alpha" +8c7cd722 Bugfix: Incremental decode of lossy-alpha +7955152d MIPS: fix error with number of registers. +b1dabe37 Merge "Move the HuffmanCost() function to dsp lib" +75b12006 Move the HuffmanCost() function to dsp lib +2772b8bd MIPS: fix assembler error revealed by clang's debug build +6653b601 enc_mips32: fix unused symbol warning in debug +8dec1209 enc_mips32: disable ITransform(One) in debug builds +98519dd5 enc_neon: convert Disto4x4 to intrinsics +fe9317c9 cosmetics: +953b0746 enc_neon: cosmetics +a9fc697c Merge "WIP: extract the float-calculation of HuffmanCost from loop" +3f84b521 Merge "replace some mult-long (vmull_u8) with mult-long-accumulate (vmlal_u8)" +4ae0533f MIPS: MIPS32r1: Added optimizations for ExtraCost functions. +b30a04cf WIP: extract the float-calculation of HuffmanCost from loop +a8fe8ce2 Merge "NEON intrinsics version of CollectHistogram" +95203d2d NEON intrinsics version of CollectHistogram +7ca2e74b replace some mult-long (vmull_u8) with mult-long-accumulate (vmlal_u8) +41c6efbd fix lossless_neon.c +8ff96a02 NEON intrinsics version of FTransform +0214f4a9 Merge "MIPS: MIPS32r1: Added optimizations for FastLog2" +baabf1ea MIPS: MIPS32r1: Added optimizations for FastLog2 +3d49871d NEON functions for lossless coding +3fe02915 MIPS: MIPS32r1: Added optimizations for SSE functions. +c503b485 Merge "fix the gcc-4.6.0 bug by implementing alternative method" +abe6f487 fix the gcc-4.6.0 bug by implementing alternative method +5598bdec enc_mips32.c: fix file mode +2b1b4d5a MIPS: MIPS32r1: Add optimization for GetResidualCost +f0a1f3cd Merge "MIPS: MIPS32r1: Added optimization for FTransform" +7231f610 MIPS: MIPS32r1: Added optimization for FTransform +869eaf6c ~30% encoding speedup: use NEON for QuantizeBlock() +f758af6b enc_neon: convert FTransformWHT to intrinsics +7dad095b MIPS: MIPS32r1: Added optimization for Disto4x4 (TTransform) +2298d5f3 MIPS: MIPS32r1: Added optimization for QuantizeBlock +e88150c9 Merge "MIPS: MIPS32r1: Add optimization for ITransform" +de693f25 lossless_neon: disable VP8LConvert* functions +4143332b NEON intrinsics for encoding +0ca2914b MIPS: MIPS32r1: Add optimization for ITransform +71bca5ec dec_neon: use vst_lane instead of vget_lane +bf061052 Intrinsics NEON version of TransformOne +19c6f1ba Merge "dec_neon: use vld?_lane instead of vset?_lane" +7a94c0cf upsampling_neon: drop NEON suffix from local functions +d14669c8 upsampling_sse2: drop SSE2 suffix from local functions +2ca42a4f enc_sse2: drop SSE2 suffix from local functions +d038e619 dec_sse2: drop SSE2 suffix from local functions +fa52d752 dec_neon: use vld?_lane instead of vset?_lane +c520e77d cosmetic: fix long line +4b0f2dae Merge "add intrinsics NEON code for chroma strong-filtering" +e351ec07 add intrinsics NEON code for chroma strong-filtering +aaf734b8 Merge "Add SSE2 version of forward cross-color transform" +c90a902e Add SSE2 version of forward cross-color transform +bc374ff3 Use histogram_bits to initalize transform_bits. +2132992d Merge "Add strong filtering intrinsics (inner and outer edges)" +5fbff3a6 Add strong filtering intrinsics (inner and outer edges) +d4813f0c Add SSE2 function for Inverse Cross-color Transform +26029568 dec_neon: add strong loopfilter intrinsics +cca7d7ef Merge "add intrinsics version of SimpleHFilter16NEON()" +1a05dfa7 windows: fix dll builds +d6c50d8a Merge "add some colorspace conversion functions in NEON" +4fd7c82e SSE2 variants of Subtract-Green: Rectify loop condition +97e5fac3 add some colorspace conversion functions in NEON +b9a7a45f add intrinsics version of SimpleHFilter16NEON() +daccbf40 add light filtering NEON intrinsics +af444608 fix typo in STORE_WHT +6af6b8e1 Tune HistogramCombineBin for large images. +af93bdd6 use WebPSafe[CM]alloc/WebPSafeFree instead of [cm]alloc/free +51f406a5 lossless_sse2: relocate VP8LDspInitSSE2 proto +0f4f721b separate SSE2 lossless functions into its own file +514fc251 VP8LConvertFromBGRA: use conversion function pointers +6d2f3527 dsp/dec: TransformDCUV: use VP8TransformDC +defc8e1b Merge "fix out-of-bound read during alpha-plane decoding" +fbed3643 Merge "dsp: reuse wht transform from dec in encoder" +d8467084 Merge "Add SSE2 version of ARGB -> BGR/RGB/... conversion functions" +207d03b4 fix out-of-bound read during alpha-plane decoding +d1b33ad5 2-5% faster trellis with clang/MacOS (and ~2-3% on ARM) +369c26dd Add SSE2 version of ARGB -> BGR/RGB/... conversion functions +df230f27 dsp: reuse wht transform from dec in encoder +80e218d4 Android.mk: fix build with APP_ABI=armeabi-v7a-hard +59daf083 Merge "cosmetics:" +53622008 cosmetics: +3e7f34a3 AssignSegments: quiet array-bounds warning +3c2ebf58 Merge "UpdateHistogramCost: avoid implicit double->float" +cf821c82 UpdateHistogramCost: avoid implicit double->float +312e638f Extend the search space for GetBestGreenRedToBlue +1c58526f Fix few nits +fef22704 Optimize and re-structure VP8LGetHistoImageSymbols +068b14ac Optimize lossless decoding. +5f0cfa80 Do a binary search to get the optimum cache bits. +24ca3678 Merge "allow 'cwebp -o -' to emit output to stdout" +e12f874e allow 'cwebp -o -' to emit output to stdout +2bcad89b allow some more stdin/stout I/O +84ed4b3a fix cwebp.1 typos after patch #69199 +65b99f1c add a -z option to cwebp, and WebPConfigLosslessPreset() function +30176619 4-5% faster trellis by removing some unneeded calculations. +687a58ec histogram.c: reindent after b33e8a0 +06d456f6 Merge "~3-4% faster lossless encoding" +c60de260 ~3-4% faster lossless encoding +42eb06fc Merge "few cosmetics after patch #69079" +82af8264 few cosmetics after patch #69079 +b33e8a05 Refactor code for HistogramCombine. +ca1bfff5 Merge "5-10% encoding speedup with faster trellis (-m 6)" +5aeeb087 5-10% encoding speedup with faster trellis (-m 6) +82ae1bf2 cosmetics: normalize VP8GetCPUInfo checks +e3dd9243 Merge "Refactor GetBestPredictorForTile for future tuning." +206cc1be Refactor GetBestPredictorForTile for future tuning. +3cb84062 Merge "speed-up trellis quant (~5-10% overall speed-up)" +b66f2227 Merge "lossy encoding: ~3% speed-up" +4287d0d4 speed-up trellis quant (~5-10% overall speed-up) +390c8b31 lossy encoding: ~3% speed-up +9a463c4a Merge "dec_neon: convert TransformWHT to intrinsics" +e8605e96 Merge "dec_neon: add ConvertU8ToS16" +4aa3e412 MIPS: MIPS32r1: rescaler bugfix +c16cd99a Speed up lossless encoder. +9d6b5ff1 dec_neon: convert TransformWHT to intrinsics +2ff0aae2 dec_neon: add ConvertU8ToS16 +77a8f919 fix compilation with USE_YUVj flag +4acbec1b Merge changes I3b240ffb,Ia9370283,Ia2d28728 +2719bb7e dec_neon: TransformAC3: work on packed vectors +b7b60ca1 dec_neon: add SaturateAndStore4x4 +b7685d73 Rescale: let ImportRow / ExportRow be pointer-to-function +e02f16ef dec_neon.c: convert TransformDC to intrinsics +9cba963f add missing file +8992ddb7 use static clipping tables +0235d5e4 1-2% faster quantization in SSE2 +b2fbc36c fix VC12-x64 warning +6e37cb94 Merge "cosmetics: backward_references.c: reindent after a7d2ee3" +a42ea974 cosmetics: backward_references.c: reindent after a7d2ee3 +6c327442 Merge "fix missing __BIG_ENDIAN__ definition on some platform" +a8b6aad1 fix missing __BIG_ENDIAN__ definition on some platform +fde2904b Increase initial buffer size for VP8L Bit Writer. +a7d2ee39 Optimize cache estimate logic. +7fb6095b Merge "dec_neon.c: add TransformAC3" +bf182e83 VP8LBitWriter: use a bit-accumulator +3f40b4a5 Merge "MIPS: MIPS32r1: clang macro warning resolved" +1684f4ee WebP Decoder: Mark some truncated bitstreams as invalid +acbedac4 MIPS: MIPS32r1: clang macro warning resolved +228e4877 dec_neon.c: add TransformAC3 +393f89b7 Android.mk: avoid gcc-specific flags with clang +32aeaf11 revamp VP8LColorSpaceTransform() a bit +0c7cc4ca Merge "Don't dereference NULL, ensure HashChain fully initialized" +391316fe Don't dereference NULL, ensure HashChain fully initialized +926ff402 WEBP_SWAP_16BIT_CSP: remove code dup +1d1cd3bb Fix decode bug for rgbA_4444/RGBA_4444 color-modes. +939e70e7 update AUTHORS file +8934a622 cosmetics: *_mips32.c +dd438c9a MIPS: MIPS32r1: Optimization of some simple point-sampling functions. PATCH [6/6] +53520911 Added support for calling sampling functions via pointers. +d16c6974 MIPS: MIPS32r1: Optimization of filter functions. PATCH [5/6] +04336fc7 MIPS: MIPS32r1: Optimization of function TransformOne. PATCH [4/6] +92d8fc7d MIPS: MIPS32r1: Optimization of function WebPRescalerImportRow. PATCH [3/6] +bbc23ff3 parse one row of intra modes altogether +a2f608f9 Merge "MIPS: MIPS32r1: Optimization of function WebPRescalerExportRow. [2/6]" +88230854 MIPS: MIPS32r1: Optimization of function WebPRescalerExportRow. [2/6] +c5a5b028 decode mt+incremental: fix segfault in debug builds +9882b2f9 always use fast-analysis for all methods. +000adac0 Merge "autoconf: update ax_pthread.m4" +2d2fc37d update .gitignore +5bf4255a Merge "Make it possible to avoid automagic dependencies" +c1cb1933 disable NEON for arm64 platform +73a304e9 Make it possible to avoid automagic dependencies +4d493f8d MIPS: MIPS32r1: Decoder bit reader function optimized. PATCH [1/6] +c741183c make WebPCleanupTransparentArea work with argb picture +5da18552 add a decoding option to flip image vertically +00c3c4e1 Merge "add man/vwebp.1" +2c6bb428 add man/vwebp.1 +ea59a8e9 Merge "Merge tag 'v0.4.0'" +7574bed4 fix comments related to array sizes +0b5a90fd dwebp.1: fix option formatting +effcb0fd Merge tag 'v0.4.0' +7c76255d autoconf: update ax_pthread.m4 +fff2a11b make -short work with -print_ssim, -print_psnr, etc. +68e7901d update ChangeLog (tag: v0.4.0-rc1, tag: v0.4.0, origin/0.4.0) +256e4333 update NEWS description with new general features +29625340 Merge "gif2webp: don't use C99 %zu" into 0.4.0 +3b9f9dd0 gif2webp: don't use C99 %zu +b5b2e3c7 cwebp: fix metadata output w/lossy+alpha +ad26df1a makefile.unix: clean up libgif2webp_util.a +c3b45570 update Changelog +ca841121 Merge "bump version to 0.4.0" into 0.4.0 +8c524db8 bump version to 0.4.0 +eec2398c update AUTHORS & .mailmap +b9bbf6a1 update NEWS for 0.4.0 +c72e0811 Merge "dec/webp.c: don't wait for data before reporting w/h" +5ad65314 dec/frame.c: fix formatting +f7fc4bc8 dec/webp.c: don't wait for data before reporting w/h +66a32af5 Merge "NEON speed up" +26d842eb NEON speed up +f307f98b Merge "webpmux: let -- stop parameter parsing" +fe051da7 Merge "README: add a section on gif2webp" +6fd2bd62 Merge "manpage pedantry" +4af19007 README: add a section on gif2webp +6f36ade9 manpage pedantry +f9016cb9 README: update dwebp options +b4fa0a47 webpmux: let -- stop parameter parsing +a9a20acf gif2webp: Add a multi-threaded encode option +495bef41 fix bug in TrellisQuantize +605a7127 simplify __cplusplus ifdef +33109f99 Merge "drop: ifdef __cplusplus checks from C files" +7f9de0b9 Merge changes I994a5587,I8467bb71,I13b50688,I1e2c9c7b +5459030b gif2webp: let -- stop parameter parsing +a4b0aa06 vwebp: let -- stop parameter parsing +98af68fe cwebp: let -- stop parameter parsing +a33831e2 dwebp: let -- stop parameter parsing +36301249 add some checks on error paths +ce4c7139 Merge "autoconf: add --disable-wic" +5227d991 drop: ifdef __cplusplus checks from C files +f6453559 dwebp.1: fix typo +f91034f2 Merge "cwebp: print metadata stats when no output file is given" +d4934553 gif2webp: Backward compatibility for giflib version <= 4.1.3 +4c617d32 gif2webp: Disable output of ICC profile by default +73b731fb introduce a special quantization function for WHT +41c0cc4b Make Forward WHT transform use 32bit fixed-point calculation +a3359f5d Only compute quantization params once +70490437 cwebp: print metadata stats when no output file is given +d513bb62 * fix off-by-one zthresh calculation * remove the sharpening for non luma-AC coeffs * adjust the bias a little bit to compensate for this +ad9dec0c Merge "cosmetics: dwebp: fix local function name format" +f737f037 Merge "dwebp: remove a dead store" +3c3a70da Merge "makefile.unix: install binaries in $(DESTDIR)/bin/" +150b655f Merge "Android.mk: add some release compile flags" +dbebd33b cosmetics: dwebp: fix local function name format +27749951 dwebp: remove a dead store +a01e04fe autoconf: add --disable-wic +5009b227 makefile.unix: install binaries in $(DESTDIR)/bin/ +bab30fca Merge "fix -print_psnr / ssim options" +ebef7fb3 fix -print_psnr / ssim options +cb637855 Merge "fix bug due to overzealous check in WebPPictureYUVAToARGB()" +8189885b Merge "EstimateBestFilter: use an int to iterate WEBP_FILTER_TYPE" +4ad7d335 Android.mk: add some release compile flags +c12e2369 cosmetics: fix a few typos +6f104034 fix bug due to overzealous check in WebPPictureYUVAToARGB() +3f6c35c6 EstimateBestFilter: use an int to iterate WEBP_FILTER_TYPE +cc55790e Merge changes I8bb7a4dc,I2c180051,I021a014f,I8a224a62 +c536afb5 Merge "cosmetics: fix some typos" +cbdd3e6e add a -dither dithering option to the decoder +e8124012 Updated iosbuild.sh for XCode 5.x +4931c329 cosmetics: fix some typos +05aacf77 mux: add some missing casts +617d9348 enc/vp8l: add a missing cast +46db2865 idec: add some missing casts +b524e336 ErrorStatusLossless: correct return type +cb261f79 fix a descaling bug for vertical/horizontal U/V interpolation +bcb3955c Merge changes I48968468,I181bc736 +73f52133 gif2webp: Add a mixed compression mode +6198715e demux: split chunk parsing from ParseVP8X +d2e3f4e6 demux: add a tail pointer for chunks +87cffcc3 demux: cosmetics: s/has_frames/is_animation/ +e18e6677 demux: strictly enforce the animation flag +c4f39f4a demux: cosmetics: remove a useless break +61cb884d demux: (non-exp) fail if the fragmented flag is set +ff379db3 few % speedup of lossless encoding +df3649a2 remove all disabled code related to P-frames +6d0cb3de Merge "gif2webp: kmin = 0 should suppress key-frame addition." +36555983 gif2webp: kmin = 0 should suppress key-frame addition. +7708e609 Merge "detect flatness in blocks and favor DC prediction" +06b1503e Merge "add comment about the kLevelsFromDelta[][] LUT generation" +5935259c add comment about the kLevelsFromDelta[][] LUT generation +e3312ea6 detect flatness in blocks and favor DC prediction +ebc9b1ee Merge "VPLBitReader bugfix: Catch error if bit_pos > LBITS too." +96ad0e0a VPLBitReader bugfix: Catch error if bit_pos > LBITS too. +a014e9c9 tune quantization biases toward higher precision +1e898619 add helpful PrintBlockInfo() function +596a6d73 make use of 'extern' consistent in function declarations +c8d48c6e Merge "extract random utils to their own file util/random.[ch]" +98aa33cf extract random utils to their own file util/random.[ch] +432a723e Merge "swig: add basic go bindings" +fab618b5 Merge "rename libwebp.i -> libwebp.swig" +e4e7fcd6 swig: add basic go bindings +d3408720 Merge "fast auto-determined filtering strength" +f8bfd5cd fast auto-determined filtering strength +ac0bf951 small clean-up in ExpandMatrix() +1939607e rename libwebp.i -> libwebp.swig +43148b6c filtering: precompute ilimit and hev_threshold +18f992ec simplify f_inner calculation a little +241d11f1 add missing const +86c0031e add a 'format' field to WebPBitstreamFeatures +dde91fde Demux: Correct the extended format validation +5d6c5bd2 add entry for '-resize' option in cwebp's man +7c098d18 Use some gamma-curve range compression when computing U/V average +0b2b0504 Use deterministic random-dithering during RGB->YUV conversion +8a2fa099 Add a second multi-thread method +7d6f2da0 Merge "up to 20% faster multi-threaded decoding" +266f63ea Merge "libwebp.jar: build w/Java 1.6 for Android compat" +0532149c up to 20% faster multi-threaded decoding +38efdc2e Simplify the gif2webp tool: move the optimization details to util +de899516 libwebp.jar: build w/Java 1.6 for Android compat +cb221552 Decode a full row of bitstream before reconstructing +dca8a4d3 Merge "NEON/simple loopfilter: avoid q4-q7 registers" +9e84d901 Merge "NEON/TransformWHT: avoid q4-q7 registers" +fc10249b NEON/simple loopfilter: avoid q4-q7 registers +2f09d63e NEON/TransformWHT: avoid q4-q7 registers +77585a2b Merge "use a macrofunc for setting NzCoeffs bits" +d155507c Merge "use HINT_GRAPH as image_hint for gif source" +9c561646 Merge "only print GIF_DISPOSE_WARNING once" +05879865 use HINT_GRAPH as image_hint for gif source +0b28d7ab use a macrofunc for setting NzCoeffs bits +f9bbc2a0 Special-case sparse transform +00125196 gif2webp: detect and flatten uniformly similar blocks +0deaf0fa only print GIF_DISPOSE_WARNING once +6a8c0eb7 Merge "small optimization in segment-smoothing loop" +f7146bc1 small optimization in segment-smoothing loop +5a7533ce small gif2webp fix +4df0c89e Merge changes Ic697660c,I27285521 +5b2e6bd3 Android.mk: add a dwebp target +f910a84e Android.mk: update build flags +63f9aba4 special-case WHT transform when there's only DC +80911aef Merge "7-8% faster decoding by rewriting GetCoeffs()" +606c4304 gif2webp: Improved compression for lossy animated WebP +fb887f7f gif2webp: Different kmin/kmax defaults for lossy and lossless +2a981366 7-8% faster decoding by rewriting GetCoeffs() +92d47e4c improve VP8L signature detection by checking the version bits too +5cd43e43 Add -incremental option to dwebp +54b8e3f6 webpmux: DisplayInfo(): remove unnecessary error checks. +40ae3520 fix memleak in WebPIDelete() +d9662658 mux.h doc: WebPMuxGetFrame() can return WEBP_MUX_MEMORY_ERROR too. +0e6747f8 webpmux -info: display dimensions and has_alpha per frame +d78a82c4 Sanity check for underflow +8498f4bf Merge "remove -Wshadow warnings" +e89c6fc8 Avoid a potential memleak +3ebe1757 Merge "break down the proba 4D-array into some handy structs" +6a44550a break down the proba 4D-array into some handy structs +2f5e8934 remove -Wshadow warnings +bf3a29b3 Merge "add proper WEBP_HAVE_GIF and WEBP_HAVE_GL flags" +2b0a7593 Merge "fix some warnings from static analysis" +22dd07ce mux.h: Some doc corrections +79ff0346 add proper WEBP_HAVE_GIF and WEBP_HAVE_GL flags +d51f45f0 fix some warnings from static analysis +d134307b fix conversion warning on MSVC +d538cea8 gif2webp: Support a 'min' and 'max' key frame interval +80b54e1c allow search with token buffer loop and fix PARTITION0 problem +b7d4e042 add VP8EstimateTokenSize() +10fddf53 enc/quant.c: silence a warning +399cd456 Merge "fix compile error on ARM/gcc" +9f24519e encoder: misc rate-related fixes +c663bb21 Merge "simplify VP8IteratorSaveBoundary() arg passing" +fa46b312 Demux.h: Correct a method name reference +f8398c9d fix compile error on ARM/gcc +f691f0e4 simplify VP8IteratorSaveBoundary() arg passing +42542be8 up to 6% faster encoding with clang compiler +93402f02 multi-threaded segment analysis +7e2d6595 Merge "remove the PACK() bit-packing tricks" +c13fecf9 remove the PACK() bit-packing tricks +2fd091c9 Merge "use NULL for lf_stats_ testing, not bool" +b11c9d62 dwebp: use default dct_method +4bb8465f Merge "(de)mux.h: wrap pseudo-code in /* */" +cfb56b17 make -pass option work with token buffers +5416aab4 (de)mux.h: wrap pseudo-code in /* */ +35dba337 use NULL for lf_stats_ testing, not bool +733a7faa enc->Iterator memory cleanup +e81fac86 Add support for "no blend" in webpmux binary +3b80bc48 gif2webp: Separate out each step into a method +bef7e9cc Add doc precision about demux object keeping pointers to data. +61405a14 dwebp: enable stdout output with WIC +6eabb886 Merge "Animated WebP: add "do no blend" option to spec" +be20decb fix compilation for BITS 24 +e58cc137 Merge "dwebp: s/unsigned char/uint8_t/" +72501d43 dwebp: s/unsigned char/uint8_t/ +2c9633e8 Merge "gif2webp: Insert independent frames at regular intervals." +f0d6a14b gif2webp: Insert independent frames at regular intervals. +b25a6fbf yuv.h: fix indent +ede3602e Merge "cosmetics: fix indent" +3a65122a dwebp: fix stdout related output +388a7249 cosmetics: fix indent +4c7322c8 Merge "dsp: msvc compatibility" +d50c7e32 Merge "5-7% faster SSE2 versions of YUV->RGB conversion functions" +b8ab7847 Merge "simplify upsampler calls: only allow 'bottom' to be NULL" +df6cebfa 5-7% faster SSE2 versions of YUV->RGB conversion functions +ad6ac32d simplify upsampler calls: only allow 'bottom' to be NULL +a5e8afaf output to stdout if file name is "-" +f358450f dsp: msvc compatibility +43a7c8eb Merge "cosmetics" +4c5f19c1 Merge "bit_reader.h: cosmetics" +f72fab70 cosmetics +14dd5e78 fix const-ness +b20aec49 Merge "Support for 'do not blend' option in vwebp" +dcf65222 Support for 'do not blend' option in vwebp +d5bad033 Animated WebP: add "do no blend" option to spec +a2f5f73d Merge "Support for "Do not blend" in mux and demux libraries" +e081f2f3 Pack code & extra_bits to Struct (VP8LPrefixCode). +6284854b Support for "Do not blend" in mux and demux libraries +f486aaa9 Merge "slightly faster ParseIntraMode" +d1718632 slightly faster ParseIntraMode +3ceca8ad bit_reader.h: cosmetics +69257f70 Create LUT for PrefixEncode. +988b7084 add WebPWorkerExecute() for convenient bypass +06e24987 Merge "VP8EncIterator clean-up" +de4d4ad5 VP8EncIterator clean-up +7bbe9529 Merge "cosmetics: thread.c: drop a redundant comment" +da411485 cosmetics: thread.c: drop a redundant comment +feb4b6e6 thread.h: #ifdef when checking WEBP_USE_THREAD +8924a3a7 thread.c: drop WebPWorker prefix from static funcs +1aed8f2a Merge "fix indent" +4038ed15 fix indent +1693fd9b Demux: A new state WEBP_DEMUX_PARSE_ERROR +8dcae8b3 fix rescaling-with-alpha inaccuracy +11249abf Merge changes I9b4dc36c,I4e0eef4d +52508a1f Mux: support parsing unknown chunks within a frame/fragment. +05db0572 WebPMuxSetChunk: remove unused variable +8ba1bf61 Stricter check for presence of alpha when writing lossless images +a03c3516 Demux: WebPIterator now also denotes if the frame has alpha. +6df743a3 Decoder: handle fragments case correctly too. +faa4b07e Support for unknown chunks in mux library +7d60bbc6 Speed up HashChainFindCopy function. +66740140 Speedup Alpha plane encoding. +b7346a1e 0.1 % speedup to decoding +c606182e webp-container-spec: Tighten language added by last +a34a5029 pngdec: output error messages from libpng +e84c625d Merge "Detect canvas and image size mismatch in decoder." +f626fe2e Detect canvas and image size mismatch in decoder. +f5fbdee0 demux: stricter image bounds check +30c8158a add extra assert in Huffman decode code +8967b9f3 SSE2 for lossless decoding (critical) functions. +699d80ea Jump-lookup for Huffman coding +c34307ab fix some VS9 warnings about type conversion +eeada35c pngdec: add missing include +54b65108 gif2webp: If aligning to even offsets, extra pixels should be transparent +0bcf5ce3 Merge "remove a malloc() in case we're using only FILTER_NONE for alpha" +2c07143b remove a malloc() in case we're using only FILTER_NONE for alpha +a4d5f59d Faster lossless decoding +fd53bb75 Merge "alternate LUT-base reverse-bits code" +d1c166ef Merge "Container spec: a clarification on background color." +fdb91779 Rename a method +5e967532 Container spec: a clarification on background color. +30e77d0f Merge branch '0.3.0' +1b631e29 alternate LUT-base reverse-bits code +24cc307a ~20% faster lossless decoding +313d853f Speedup for decoding lossless WebP photographs: +24ee098a change the bytes_per_pixels_ field into more evocative use_8b_decode +2a04b034 update ChangeLog (tag: v0.3.1-rc2, tag: v0.3.1) +7288950b Regression fix for alpha channels using color cache: +2e377b53 wicdec: silence a format warning +ad9e42a6 muxedit: silence some uninitialized warnings +3307c163 Don't set alpha-channel to 0xff for alpha->green uplift +5130770c Merge "wicdec: silence a format warning" +a37eff47 Regression fix for alpha channels using color cache: +241cf99b Merge "muxedit: silence some uninitialized warnings" +c8f9c84d Regression fix for alpha unfiltering: +14cd5c6c muxedit: silence some uninitialized warnings +a368db81 dec/vp8l: quiet vs9 x64 type conversion warning +ffae9f31 wicdec: silence a format warning +8cf0701e Alpha encoding: never filter in case of NO_COMPRESSION +825e73b1 update ChangeLog (tag: v0.3.1-rc1) +abf6f691 update NEWS +5a92c1a5 bump version to 0.3.1 +86daf77c store top Y/U/V samples in packed fashion +67bc353e Revert "add WebPBlendAlpha() function to blend colors against background" +068db59e Intertwined decoding of alpha and RGB +38cc0114 Simplify forward-WHT + SSE2 version +3fa595a5 Support decoding upto given row in DECODE_DATA_FUNC +520f005f DequantizeLevels(): Add 'row' and 'num_rows' args +47374b82 Alpha unfilter for given set of rows +f32097e0 probe input file and quick-check for WebP format. +a2aed1d0 configure: improve gl/glut library test +c7e89cbb update copyright text +a00380d2 configure: remove use of AS_VAR_APPEND +a94a88dd fix EXIF parsing in PNG +a71e5d84 add doc precision for WebPPictureCopy() and WebPPictureView() +8287012e remove datatype qualifier for vmnv +e1908430 fix a memory leak in gif2webp +0b18b9ee fix two minor memory leaks in webpmux +db5095d5 remove some cruft from swig/libwebp.jar +850e956f README: update swig notes +bddd9b0a swig/python: add minimal documentation +d573a8d5 swig: add python encode support +6b931875 swig/java: reduce wrapper function code duplication +6fe536f4 swig/java: rework uint8_t typemap +a2ea4643 Fix the bug in ApplyPalette. +7bb28d2a webp/lossless: fix big endian BGRA output +f036d4bf Speed up ApplyPalette for ARGB pixels. +8112c8cf remove some warnings: +cc128e0b Further reduce memory to decode lossy+alpha images +07db70d2 fix for big-endian +eda8a7de gif2webp: Fix signed/unsigned comparison mismatch +31f346fe Makefile.vc: fix libwebpdemux dll variable typo +6c76d28e swig: add python (decode) support +b4f5bb6c swig: cosmetics +498d4dd6 WebP-Lossless encoding improvements. +26e72442 swig: ifdef some Java specific code +8ecec686 configure: add warning related flags +e676b043 configure: add GLUT detection; build vwebp +b0ffc437 Alpha decoding: significantly reduce memory usage +20aa7a8d configure: add --enable-everything +b8307cc0 configure.ac: add some helper macros +980e7ae9 Remove the gcc compilation comments +7f25ff99 gif2webp: Fix ICC and XMP support +d8e53211 Add missing name to AUTHORS +11edf5e2 Demux: Fix a potential memleak +c7b92184 don't forward declare enums +7a650c6a prevent signed int overflow in left shift ops +31bea324 add precision about dynamic output reallocation with IDecoder +c22877f7 Add incremental support for extended format files +5051245f Makefile.vc: have 'all' target build everything +8191deca Makefile.vc: flags cleanup +b9d74735 Makefile.vc: drop /FD flag +5568dbcf update gitignore +f4c7b654 WebPEncode: An additional check. Start VP8EncLoop/VP8EncTokenLoop only if VP8EncStartAlpha succeeded. +1fb04bec pngdec: Avoid a double-free. +dcbb1ca5 add WebPBlendAlpha() function to blend colors against background +bc9f5fbe configure.ac: add AM_PROG_AR for automake >= 1.12 +bf867bf2 Tuned cross_color parameter (step) for lower qual +90e2ec5a Merge "probe input file and quick-check for WebP format." +7180d7ff Merge "update copyright text" +830f72b7 probe input file and quick-check for WebP format. +2ccf58d6 configure: improve gl/glut library test +d640614d update copyright text +c2113ad4 Merge "configure: remove use of AS_VAR_APPEND" +9326a56f configure: remove use of AS_VAR_APPEND +ea63d619 fix a type warning on VS9 x86 +bec11092 fix EXIF parsing in PNG +b6e65f3d Merge "fix warnings for vs9 x64" +438946dc fix warnings for vs9 x64 +f4710e3b collect macroblock reconstruction data in VP8MBData struct +23d28e21 add doc precision for WebPPictureCopy() and WebPPictureView() +518f2cd7 cosmetics: gif2webp: fix indent +af358e68 Merge "remove datatype qualifier for vmnv" +3fe91635 remove datatype qualifier for vmnv +764fdffa fix a memory leak in gif2webp +3e59a74d fix two minor memory leaks in webpmux +47b9862f Merge "README: update swig notes" +325d15ff remove some cruft from swig/libwebp.jar +4a7627c2 README: update swig notes +5da81e33 Merge "swig/python: add minimal documentation" +f39e08f2 Merge "swig: add python encode support" +6ca4a3e3 Merge "swig/java: reduce wrapper function code duplication" +8f8702b0 Merge "swig/java: rework uint8_t typemap" +91413be2 reduce memory for VP8MB and remove bitfields use +7413394e Fix the memory leak in ApplyFilters. +2053c2cf simplify the alpha-filter testing loop +825b64db swig/python: add minimal documentation +14677e11 swig: add python encode support +a5c297c8 swig/java: reduce wrapper function code duplication +ad4a367d swig/java: rework uint8_t typemap +0d25876b use uint8_t for inv_palette[] +afa3450c Fix the bug in ApplyPalette. +2d6ac422 Merge "webp/lossless: fix big endian BGRA output" +2ca83968 webp/lossless: fix big endian BGRA output +742110cc Speed up ApplyPalette for ARGB pixels. +2451e47d misc code cleanup +83db4043 Merge "swig: add python (decode) support" +eeeea8b5 Merge "swig: cosmetics" +d5f9b8f3 Merge "libwebp: fix vp8 encoder mem alloc offsetting" +d8edd835 libwebp: fix vp8 encoder mem alloc offsetting +8983b83e remove use of bit-fields in VP8FInfo +87a4fca2 remove some warnings: +ba8f74e2 Merge "fix for big-endian" +a65067fa Merge "Further reduce memory to decode lossy+alpha images" +64c84486 Further reduce memory to decode lossy+alpha images +332130b9 Mux: make a few methods static +44370617 fix for big-endian +5199eab5 Merge "add uncompressed TIFF output support" +a3aede97 add uncompressed TIFF output support +f975b67f Merge "gif2webp: Fix signed/unsigned comparison mismatch" +5fbc734b Merge "GetFeatures: Detect invalid VP8X/VP8/VP8L data" +d5060c87 Merge "mux.h: A comment fix + some consistency fixes" +352d0dee GetFeatures: Detect invalid VP8X/VP8/VP8L data +3ef79fef Cosmetic: "width * height" +043e1ae4 gif2webp: Fix signed/unsigned comparison mismatch +5818cff7 mux.h: A comment fix + some consistency fixes +1153f888 Merge "swig: ifdef some Java specific code" +3eeedae1 Makefile.vc: fix libwebpdemux dll variable typo +f980faf4 swig: add python (decode) support +7f5f42bb swig: cosmetics +8eae188a WebP-Lossless encoding improvements. +c7247c4c swig: ifdef some Java specific code +4cb234d5 Merge "Mux: make ValidateForSingleImage() method static" +ed6f5308 Merge "Add GetCanvasSize() method to mux" +1d530c9a Mux: make ValidateForSingleImage() method static +bba4c2b2 configure: add warning related flags +fffefd18 Add GetCanvasSize() method to mux +732da8d0 Merge "configure: add GLUT detection; build vwebp" +0e513f7a configure: add GLUT detection; build vwebp +55d1c150 Merge "Alpha decoding: significantly reduce memory usage" +13d99fb5 Merge "configure: add --enable-everything" +2bf698fe Merge "configure.ac: add some helper macros" +edccd194 Alpha decoding: significantly reduce memory usage +3cafcc9a configure: add --enable-everything +4ef14477 configure.ac: add some helper macros +a4e1cdbb Remove the gcc compilation comments +6393fe4b Cosmetic fixes +9c4ce971 Simplify forward-WHT + SSE2 version +878b9da5 fix missed optim +00046171 VP8GetInfo(): Check for zero width or height. +9bf31293 align VP8Encoder::nz_ allocation +5da165cf fix CheckMode() signature +0ece07dc Merge "explicitly pad bitfields to 32-bits" +9dbc9d19 explicitly pad bitfields to 32-bits +5369a80f Merge "prevent signed int overflow in left shift ops" +70e39712 Merge "cosmetics: remove unnecessary ';'s" +d3136ce2 Merge "don't forward declare enums" +b26e5ad5 gif2webp: Fix ICC and XMP support +46089b20 Add missing name to AUTHORS +94328d64 Demux: Fix a potential memleak +96e948d7 don't forward declare enums +f4f90880 prevent signed int overflow in left shift ops +0261545e cosmetics: remove unnecessary ';'s +7ebdf110 Merge "Fix few missing comparisons to NULL" +1579989e Fix few missing comparisons to NULL +ea1b21cf Cleaned up VP8GetHeaders() so that it parses only frame header +b66caee4 dwebp: add support for BMP output +ff885bfe add precision about dynamic output reallocation with IDecoder +79241d5a Merge "Makefile.vc: have 'all' target build everything" +ac1c729b Merge "Makefile.vc: flags cleanup" +118a055c Merge "Makefile.vc: drop /FD flag" +ecad0109 Merge "update gitignore" +a681b4f4 Rename PRE_VP8 state to WEBP_HEADER +ead4d478 Add incremental support for extended format files +69d0f926 Makefile.vc: have 'all' target build everything +52967498 Makefile.vc: flags cleanup +c61baf0c Makefile.vc: drop /FD flag +3a15125d update gitignore +5167ca47 Merge "WebPEncode: An additional check. Start VP8EncLoop/VP8EncTokenLoop only if VP8EncStartAlpha succeeded." +67708d67 WebPEncode: An additional check. Start VP8EncLoop/VP8EncTokenLoop only if VP8EncStartAlpha succeeded. +b68912af pngdec: Avoid a double-free. +82abbe12 Merge "configure.ac: add AM_PROG_AR for automake >= 1.12" +e7d9548c add WebPBlendAlpha() function to blend colors against background +ed4dc717 configure.ac: add AM_PROG_AR for automake >= 1.12 +df4a406d Merge branch '0.3.0' +1e0d4b8c Update ChangeLog (tag: v0.3.0-rc7, tag: v0.3.0) +d52b405d Cosmetic fixes +6cb4a618 misc style fix +68111ab0 add missing YUVA->ARGB automatic conversion in WebPEncode() +e9a7990b Cosmetic fixes +403bfe82 Container spec: Clarify frame disposal +2aaa423b Merge "add missing YUVA->ARGB automatic conversion in WebPEncode()" +07d87bda add missing YUVA->ARGB automatic conversion in WebPEncode() +142c4629 misc style fix +3e7a13a0 Merge "Container spec: clarify the background color field" into 0.3.0 +14af7745 container doc: add a note about the 'ANMF' payload +cc635efa Container spec: clarify the background color field +e3e33949 container doc: move RIFF description to own section +4299f398 libwebp/mux: fix double free +33f9a692 Merge "demux: keep a frame tail pointer; used in AddFrame" into 0.3.0 +a2a7b959 use WebPDataCopy() instead of re-coding it. +6f18f12f demux: keep a frame tail pointer; used in AddFrame +e5af49e9 add doc precision about WebPParseHeaders() return codes +db46daab Merge "Makefile.vc: fix dynamic builds" into 0.3.0 +53c77afc Merge "gif2webp: Bgcolor fix for a special case" into 0.3.0 +a5ebd143 gif2webp: Bgcolor fix for a special case +6378f238 Merge "vwebp/animation: fix background dispose" into 0.3.0 +3c8eb9a8 fix bad saturation order in QuantizeBlock +04c7a2ec vwebp/animation: fix background dispose +81a50695 Makefile.vc: fix dynamic builds +5f25c396 update ChangeLog (tag: v0.3.0-rc6) +14d42af2 examples: don't use C99 %zu +5ccf1fe5 update ChangeLog +2560c243 update NEWS +f43bafc3 Merge changes Iecccb09c,If5ee9fd2,I3e181ce4 into 0.3.0 +a788644f dwebp: warn when decoding animated webp's +302efcdb Decode: return more meaningful error for animation +ad452735 WebPBitstreamFeatures: add has_animation field +783dfa49 disable FRGM decoding for good in libwebpmux +4b956be0 Update ChangeLog +ad8b86d7 update NEWS +3e084f63 Merge "demux cosmetics: comments/rename internal function" into 0.3.0 +d3f8c621 Merge "move WebPFeatureFlags declaration" into 0.3.0 +7386fe50 Merge "libwebp{demux,mux}: install mux_types.h" into 0.3.0 +d6cd4e90 Merge "bump decode abi" into 0.3.0 +17f8da5c bump decode abi +97684ae2 Merge "add doc precision about WebPDemuxPartial()" into 0.3.0 +f933fd2a move WebPFeatureFlags declaration +289bc47b libwebp{demux,mux}: install mux_types.h +224e8d46 add doc precision about WebPDemuxPartial() +4c18e80c demux cosmetics: comments/rename internal function +7cfd1bf1 update AUTHORS +401f7b85 Merge "speed-up lossless (~3%) with ad-hoc histogram cost evaluation" into 0.3.0 +1fc8ffca Merge "makefile.unix: dist related changes" into 0.3.0 +8a89c6ed Merge changes I466c377f,Ib761ebd3,I694857fc into 0.3.0 +f4ffb2d5 speed-up lossless (~3%) with ad-hoc histogram cost evaluation +723847d5 gif2webp: only write error messages to stderr +701b9e2a makefile.unix: dist related changes +bb85b437 Merge "update NEWS" into 0.3.0 +59423a24 gif2webp: fix crash on open failure with libgif5 +9acb17de gif2webp: silence a unused param warning +7d9fdc23 Merge "README updates" into 0.3.0 +5621934e Merge "build: fix install race on shared headers" into 0.3.0 +70809d89 Merge "bump version to 0.3.0" into 0.3.0 +d851cd1d demux: make the parse a bit more strict +28bb4107 update NEWS +cef93882 bump version to 0.3.0 +9048494d build: fix install race on shared headers +1e67e8ef README updates +42b611a4 Merge "configure: drop experimental from mux/demux" into 0.3.0 +096a8e32 Merge "vwebp: add color profile support" into 0.3.0 +ddfee5dc vwebp: add color profile support +0d6927d3 Merge "Mark fragment options as experimental in webpmux" into 0.3.0 +5dbd4030 Mark fragment options as experimental in webpmux +a0a6648c configure: drop experimental from mux/demux +ee65bad8 Merge "add support for BITS > 32" into 0.3.0 +744930db add support for BITS > 32 +7dd288f0 cwebp: fix build +19a8dd01 Merge "Makefile.vc: add vwebp.exe target" into 0.3.0 +50eeddad Merge "examples: normalize icc related program arguments" into 0.3.0 +757f637f Merge "Makefile.vc: add libwebpdecoder target" into 0.3.0 +b65c4b7c Makefile.vc: add libwebpdecoder target +f8db7b4a Merge "vwebp: replace doubles w/floats where appropriate" into 0.3.0 +d99aa56f Makefile.vc: add vwebp.exe target +013023e7 vwebp: replace doubles w/floats where appropriate +9b3db894 README.mux: add version reference +7b6a26cf Merge "cwebp: output metadata statistics" into 0.3.0 +d8dc72a0 examples: normalize icc related program arguments +7bfc9056 Merge "make alpha unfilter work in-place" into 0.3.0 +0037b2d2 Merge "add LUT-free reference code for YUV->RGB conversion." into 0.3.0 +166bf744 Merge "demux: disable fragment parsing" into 0.3.0 +126974b4 add LUT-free reference code for YUV->RGB conversion. +0aef3ebd make alpha unfilter work in-place +14ef5005 Merge "Remove 'status: experimental' from container spec" into 0.3.0 +d40c98e1 Merge "webpmux binary: tiny style fix" into 0.3.0 +0bc42689 cwebp: output metadata statistics +bc039803 Merge "autoconf: normalize experimental define" into 0.3.0 +d1e21b13 Remove 'status: experimental' from container spec +7681bb96 webpmux binary: tiny style fix +a3dd3d0f avoid installing example_util.h +252320e2 demux: disable fragment parsing +537bde05 autoconf: normalize experimental define +5e338e0b Merge changes I33e8a613,I8e8a7b44 into 0.3.0 +d9d0ea1b Merge changes If21e3ec7,I991fc30b into 0.3.0 +627f5ca6 automake: add reference to libwebp for mux/demux +eef73d07 don't consolidate proba stats too often +05ec4cc2 libwebp{,decoder}.pc: add pthread flags +1bfcf5bf add libwebpmux.pc +26ca843d add libwebpdemux.pc +69e25906 Merge "Tune Lossless compression for lower qualities." +0478b5d2 Tune Lossless compression for lower qualities. +39f7586f add a mention of parallel alpha encoding in the NEWS +5a21d967 Merge "1.5x-2x faster encoding for method 3 and up" +9bfbdd14 1.5x-2x faster encoding for method 3 and up +27dc741b Correct frame options order in README.mux +be2fd173 Mux: fix a scenario with bad ANMF/FRGM size +19eb012c Merge "Demux: Add option to get frame count using GetI()" +7368b8cb Merge "WebPGetFeatures() out of if condition for clarity." +f604c9a4 Merge "fix windows build" +153f94e8 fix windows build +847b4924 Merge "vwebp: use magenta for 'i'nfo display" +25ea46bd Merge "vwebp: add keyboard shortcuts to help output" +bea7ccaf vwebp: use magenta for 'i'nfo display +8fab161a webpmux: correct -frame param order in help output +03cc23d6 vwebp: add keyboard shortcuts to help output +068eba8d Demux: Add option to get frame count using GetI() +988b8f56 WebPGetFeatures() out of if condition for clarity. +6933d910 Merge "gif2webp: Be lenient about background color index." +4d0f7c55 Merge "WebPGetFeatures() behavior change:" +fdeeb01d gif2webp: Be lenient about background color index. +ad250320 Merge "multi-threaded alpha encoding for lossy" +4e32d3e1 Merge "fix compilation of token.c" +f817930a multi-threaded alpha encoding for lossy +88050351 fix compilation of token.c +fc816219 code using the actual values for num_parts_, not the ones from config +72655350 Merge "move the config check from .c to .h" +dd9e76f7 move the config check from .c to .h +956b217a WebPGetFeatures() behavior change: +df02e4ce WebPDemuxGetI behavior change: +633c004d Merge "rebalance method tools (-m) for methods [0..4]" +58ca6f65 rebalance method tools (-m) for methods [0..4] +7648c3cc Merge "describe rd-opt levels introduce VP8RDLevel enum" +67fb1003 Merge "autoconf: enable silent-rules by default" +a5042a32 GetVersion() methods for mux and demux +5189957e describe rd-opt levels introduce VP8RDLevel enum +4e094ace autoconf: enable silent-rules by default +b7eaa85d inline VP8LFastLog2() and VP8LFastSLog2 for small values +5cf7792e split quant_levels.c into decoder and encoder version +e5d3ffe2 Merge "Update code example in README.mux" +ac5a9156 Update code example in README.mux +38a91e99 Add example code snippet for demux API +5f557f3c README.mux: add info about Demux API and vwebp +c0ba0903 backward_references: avoid signed integer overflow +943386db disable SSE2 for now +9479fb7d lossless encoding speedup +ec2030a8 merge two lines together +b67956c0 Merge "Remove ReadOneBit() and ReadSymbolUnsafe()" +1667bded Remove ReadOneBit() and ReadSymbolUnsafe() +3151669b wicdec + dwebp cosmetics: normalize formatting +92668da6 change default filtering parameters: * type is now 'strong' * strength is now '60' +b7490f85 introduce WEBP_REFERENCE_IMPLEMENTATION compile option +33838857 faster decoding (3%-6%) +5c3e381b Merge "add a -jpeg_like option" +c2311046 remove unused declaration of VP8Zigzag +36152957 Merge "wicdec: add alpha support for paletted formats" +c9f16490 wicdec: add alpha support for paletted formats +1262f81e Merge "wicdec: silence some warnings" +e7ea61eb wicdec: silence some warnings +23c0f354 fix missing intptr_t->int cast for MSVC +e895059a add a -jpeg_like option +1f803f64 Merge "Tune alpha quality mapping to more reasonable values." +1267d498 Tune alpha quality mapping to more reasonable values. +043076e2 Merge "speed-up lossless in BackwardTrace" +f3a44dcd remove one malloc from TraceBackwards() +0fc1a3a0 speed-up lossless in BackwardTrace +7c732e59 cwebp: centralize WebPCleanupTransparentArea() +7381254e Merge "wicdec: add ICC profile extraction" +e83ff7de wicdec: add ICC profile extraction +146c6e3b Merge "cosmetics: pngdec: normalize default label location" +a8f549d7 Merge "manpages: italicize option parameters" +e118db83 Merge "encode.h: note the need to free() WebPMemoryWriter" +1dfee6db cosmetics: pngdec: normalize default label location +14c38200 manpages: italicize option parameters +7defbfad encode.h: note the need to free() WebPMemoryWriter +88d382a0 cwebp: cleanup after memory_writer +12d6cecf fix extra space in dwebp.1 man +b01681a9 Fix for demuxer frame iteration: +56c12aa6 Demuxer creation fix: +66c810bc add a -yuv option to dwebp (very similar to -pgm) +841a3ba5 Merge "Remove -Wshadow warnings." +8fd02527 Merge "upsampling_neon.c: fix build" +6efed268 Remove -Wshadow warnings. +60904aa6 Merge "allow WebPINewRGB/YUVA to be passed a NULL output buffer." +b7adf376 allow WebPINewRGB/YUVA to be passed a NULL output buffer. +27f8f742 upsampling_neon.c: fix build +06b9cdf1 gitignore: add IOS related directories +f112221e Merge "Fix more comments for iobuild.sh" +fe4d25dd Fix more comments for iobuild.sh +1de3e252 Merge "NEON optimised yuv to rgb conversion" +090b708a NEON optimised yuv to rgb conversion +daa06476 Merge "Add ios build script for building iOS library." +79fe39e2 Add ios build script for building iOS library. +126c035f remove some more -Wshadow warnings +522e9d61 Merge "cwebp: enable '-metadata'" +76ec5fa1 cwebp: enable '-metadata' +aeb91a9d Merge "cosmetics: break a few long lines" +be7c96b0 cosmetics: break a few long lines +cff8ddb6 Merge "add libwebpdecoder.pc" +93148ab8 Merge "libwebp.pc.in: detab" +6477f955 Merge "Makefile.vc: normalize path separator" +bed1ed7c add libwebpdecoder.pc +46168b2d libwebp.pc.in: detab +a941a346 Fixed few nits in the build files. +dd7a49b2 Makefile.vc: normalize path separator +9161be86 Merge "cwebp: extract WIC decoding to its own module" +08e7c58e Merge "Provide an option to build decoder library." +0aeba528 Provide an option to build decoder library. +757ebcb1 catch malloc(0)/calloc(0) with an assert +152ec3d2 Merge "handle malloc(0) and calloc(0) uniformly on all platforms" +a452a555 cwebp: extract WIC decoding to its own module +2b252a53 Merge "Provide option to swap bytes for 16 bit colormodes" +94a48b4b Provide option to swap bytes for 16 bit colormodes +42f8f934 handle malloc(0) and calloc(0) uniformly on all platforms +8b2152c5 Merge "add an extra assert to check memory bounds" +0d19fbff remove some -Wshadow warnings +cd22f655 add an extra assert to check memory bounds +8189feda Merge "Add details and reference about the YUV->RGB conversion" +1d2702b1 Merge "Formatting fixes in lossless bitstream spec" +8425aaee Formatting fixes in lossless bitstream spec +a556cb1a Add details and reference about the YUV->RGB conversion +d8f21e0b add link to SSIM description on Wikipedia +18e9167e Merge "WebP-lossless spec clarifications:" +98e25b9b Merge "cwebp: add -metadata option" +f01c2a53 WebP-lossless spec clarifications: +f4a97970 Merge "Disto4x4 and Disto16x16 in NEON" +47b7b0ba Disto4x4 and Disto16x16 in NEON +7eaee9f1 cwebp: add -metadata option +36c52c2c tiffdec: use toff_t for exif ifd offset +7c8111e4 Merge "cwebp/tiffdec: add TIFF metadata extraction" +e6409adc Remove redundant include from dsp/lossless code. +1ab5b3a7 Merge "configure: fix --with-gifincludedir" +03c749eb configure: fix --with-gifincludedir +8b650635 multiple libgif versions support for gif2webp +476e293f gif2webp: Use DGifOpenFileName() +b50f277b tiffdec: correct format string +2b9048e3 Merge "tiffdec: check error returns for width/height" +a1b5a9a3 Merge "cwebp/tiff: use the first image directory" +079423f5 tiffdec: check error returns for width/height +d62824af Merge "cwebp/jpegdec: add JPEG metadata extraction" +03afaca4 Merge "cwebp: add PNG metadata extraction" +2c724968 cwebp/jpegdec: add JPEG metadata extraction +dba64d91 cwebp: add PNG metadata extraction +1f075f89 Lossless spec corrections/rewording/clarifications +2914ecfd cwebp/tiffdec: add TIFF metadata extraction +d82a3e33 More corrections/clarifications in lossless spec: +bd002557 cwebp/tiff: use the first image directory +df7aa076 Merge "Cleanup around jpegdec" +0f57dcc3 decoding speed-up (~1%) +bcec339b Lossless bitstream clarification: +6bf20874 add examples/metadata.c +207f89c0 Merge "configure: add libwebpdemux status to summary" +1bd287a6 Cleanup around jpegdec +91455679 Merge "cosmetics: use '== 0' in size checks" +d6b88b76 cosmetics: use '== 0' in size checks +d3dace2f cosmetics: jpegdec +2f69af73 configure: add libwebpdemux status to summary +1c1c5646 cwebp: extract tiff decoding to its own module +6a871d66 cwebp: extract jpeg decoding to its own module +2ee228f9 cwebp: extract png decoding to its own module +4679db00 Merge "cwebp: add metadata framework" +63aba3ae cwebp: add metadata framework +931bd516 lossless bitstream: block size bits correction +e4fc4c1c lossless bitstream: block size bits correction +d65ec678 fix build, move token.c to src/enc/ +657f5c91 move token buffer to its own file (token.c) +c34a3758 introduce GetLargeValue() to slim-fast GetCoeffs(). +d5838cd5 faster non-transposing SSE2 4x4 FTransform +f76191f9 speed up GetResidualCost() +ba2aa0fd Add support for BITS=24 case +2e7f6e8e makefile.unix: Dependency on libraries +dca84219 Merge "Separate out mux and demux code and libraries:" +23782f95 Separate out mux and demux code and libraries: +bd56a01f configure: add summary output +90e5e319 dwebp manual: point to webpmux, gif2webp. +540790ca gif2webp.c: add a note about prerequisites +d1edf697 cwebp man page: meaning of '-q' for lossy/lossless +79efa1d0 Add man page for gif2webp utility +2243e40c Merge "gif2webp build support with autoconf tools" +c40efca1 gif2webp build support with autoconf tools +6523e2d4 WebP Container: +4da788da Merge "simplify the fwd transform" +42c3b550 simplify the fwd transform +41a6ced9 user GLfloat instead of float +b5426119 fix indentation +68f282f7 * handle offset in anim viewer 'vwebp' * fix gif2webp to handle disposal method and odd offset correctly +118cb312 Merge "add SSE2 version of Sum of Square error for 16x16, 16x8 and 8x8 case" +8a7c3cc8 Merge "Change the order of -frame argument to be more natural" +99e0a707 Merge "Simplify the texture evaluation Disto4x4()" +0f923c3f make the bundling work in a tmp buffer +e5c3b3f5 Simplify the texture evaluation Disto4x4() +48600084 Change the order of -frame argument to be more natural +35bfd4c0 add SSE2 version of Sum of Square error for 16x16, 16x8 and 8x8 case +a7305c2e Clarification for unknown chunks +4c4398e2 Refine WebP Container Spec wrt unknown chunks. +2ca642e0 Rectify WebPMuxGetFeatures: +7caab1d8 Some cosmetic/comment fixes. +60b2651a Merge "Write a GIF to WebP converter based on libgif." +c7127a4d Merge "Add NEON version of FTransformWHT" +11b27212 Write a GIF to WebP converter based on libgif. +e9a15a37 ExUtilWriteFile() to write memory segment to file +74356eb5 Add a simple cleanup step in mux assembly: +51bb1e5d mux.h: correct WebPDemuxSelectFragment() prototype +22a0fd9d Add NEON version of FTransformWHT +fa30c863 Update mux code to match the spec wrt animation +d9c5fbef by-pass Analysis pass in case segments=1 +d2ad4450 Merge changes Ibeccffc3,Id1585b16 +5c8be251 Merge "Chunk fourCCs for XMP/EXIF" +a00a3daf Use 'frgm' instead of 'tile' in webpmux parameters +81b8a741 Design change in ANMF and FRGM chunks: +f903cbab Chunk fourCCs for XMP/EXIF +812933d6 Tune performance of HistogramCombine +52ad1979 Animation specification in container spec +001b9302 Image fragment specification in container spec +391f9db9 Ordering of description of bits in container spec +d5735776 Metadata specification in container spec +1c4609b1 Merge commit 'v0.2.1' +0ca584cb Merge "Color profile specification in container spec" +e8b41ad1 add NEON asm version for WHT inverse transform +af6f0db2 Color profile specification in container spec +a61a824b Merge "Add NULL check in chunk APIs" +0e8b7eed fix WebPPictureView() unassigned strides +75e5f17e ARM/NEON: 30% encoding speed-up +02b43568 Add NULL check in chunk APIs +a0770727 mux struct naming +6c66dde8 Merge "Tune Lossless encoder" +ab5ea217 Tune Lossless encoder +74fefc8c Update ChangeLog (tag: v0.2.1, origin/0.2.0) +92f8059c Rename some chunks: +3bb4bbeb Merge "Mux API change:" +d0c79f05 Mux API change: +abc06044 Merge "update NEWS" into 0.2.0 +57cf313b update NEWS +25f585c4 bump version to 0.2.1 +fed7c048 libwebp: validate chunk size in ParseOptionalChunks +552cd9bc cwebp (windows): fix alpha image import on XP +b14fea99 autoconf/libwebp: enable dll builds for mingw +4a8fb272 [cd]webp: always output windows errors +d6621580 fix double to float conversion warning +72b96a69 cwebp: fix jpg encodes on XP +734f762a VP8LAllocateHistogramSet: fix overflow in size calculation +f9cb58fb GetHistoBits: fix integer overflow +b30add20 EncodeImageInternal: fix uninitialized free +3de58d77 fix the -g/O3 discrepancy for 32bit compile +77aa7d50 fix the BITS=8 case +e5970bda Make *InitSSE2() functions be empty on non-SSE2 platform +ef5cc47e make *InitSSE2() functions be empty on non-SSE2 platform +c4ea259d make VP8DspInitNEON() public +8344eadf Merge "libwebp: validate chunk size in ParseOptionalChunks" +4828bb93 Merge "cwebp (windows): fix alpha image import on XP" +30763333 libwebp: validate chunk size in ParseOptionalChunks +70481898 AccumulateLSIM: fix double -> float warnings +eda8ee4b cwebp (windows): fix alpha image import on XP +c6e98658 Merge "add EXPERIMENTAL code for YUV-JPEG colorspace" +f0360b4f add EXPERIMENTAL code for YUV-JPEG colorspace +f86e6abe add LSIM metric to WebPPictureDistortion() +c3aa215a Speed up HistogramCombine for lower qualities. +1765cb1c Merge "autoconf/libwebp: enable dll builds for mingw" +a13562e8 autoconf/libwebp: enable dll builds for mingw +9f469b57 typo: no_fancy -> no_fancy_upsampling +1a27f2f8 Merge "fix double to float conversion warning" +cf1e90de Merge "cwebp: fix jpg encodes on XP" +f2b5d19b [cd]webp: always output windows errors +e855208c fix double to float conversion warning +ecd66f77 cwebp: fix jpg encodes on XP +7b3eb372 Tune lossless compression to get better gains. +ce8bff45 Merge "VP8LAllocateHistogramSet: fix overflow in size calculation" +ab5b67a1 Merge "EncodeImageInternal: fix uninitialized free" +7fee5d12 Merge "GetHistoBits: fix integer overflow" +a6ae04d4 VP8LAllocateHistogramSet: fix overflow in size calculation +80237c43 GetHistoBits: fix integer overflow +8a997235 EncodeImageInternal: fix uninitialized free +0b9e6829 minor cosmetics +a792b913 fix the -g/O3 discrepancy for 32bit compile +73ba4357 Merge "detect and merge similar segments" +fee66275 detect and merge similar segments +0c44f415 src/webp/*.h: don't forward declare enums in C++ +d7a5ac86 vwebp: use demux interface +931e0ea1 Merge "replace 'typedef struct {} X;" by "typedef struct X X; struct X {};"" +8f216f7e remove cases of equal comparison for qsort() +28d25c82 replace 'typedef struct {} X;" by "typedef struct X X; struct X {};" +2afee60a speed up for ARM using 8bit for boolean decoder +5725caba new segmentation algorithm +2cf1f815 Merge "fix the BITS=8 case" +12f78aec fix the BITS=8 case +6920c71f fix MSVC warnings regarding implicit uint64 to uint32 conversions +f6c096aa webpmux binary: Rename 'xmp' option to 'meta' +ddfe871a webpmux help correction +b7c55442 Merge "Make *InitSSE2() functions be empty on non-SSE2 platform" +1c04a0d4 Common APIs for chunks metadata and color profile. +2a3117a1 Merge "Create WebPMuxFrameInfo struct for Mux APIs" +5c3a7231 Make *InitSSE2() functions be empty on non-SSE2 platform +7c6e60f4 make *InitSSE2() functions be empty on non-SSE2 platform +c7eb4576 make VP8DspInitNEON() public +ab3234ae Create WebPMuxFrameInfo struct for Mux APIs +e3990fd8 Alignment fixes +e55fbd6d Merge branch '0.2.0' +4238bc0a Update ChangeLog (tag: v0.2.0) +c655380c dec/io.c: cosmetics +fe1958f1 RGBA4444: harmonize lossless/lossy alpha values +681cb30a fix RGBA4444 output w/fancy upsampling +f06c1d8f Merge "Alignment fix" into 0.2.0 +f56e98fd Alignment fix +6fe843ba avoid rgb-premultiply if there's only trivial alpha values +528a11af fix the ARGB4444 premultiply arithmetic +a0a48855 Lossless decoder fix for a special transform order +62dd9bb2 Update encoding heuristic w.r.t palette colors. +6f4272b0 remove unused ApplyInverseTransform() +93bf0faa Update ChangeLog (tag: v0.2.0-rc1) +5934fc59 update AUTHORS +014a711d update NEWS +43b0d610 add support for ARGB -> YUVA conversion for lossless decoder +33705ca0 bump version to 0.2.0 +c40d7ef1 fix alpha-plane check + add extra checks +a06f8023 MODE_YUVA: set alpha to opaque if the image has none +52a87dd7 Merge "silence one more warning" into 0.2.0 +3b023093 silence one more warning +f94b04f0 move some RGB->YUV functions to yuv.h +4b71ba03 README: sync [cd]webp help output +c9ae57f5 man/dwebp.1: add links to output file format details +292ec5cc quiet a few 'uninitialized' warnings +4af3f6c4 fix indentation +9b261bf5 remove the last NOT_HAVE_LOG2 instances +323dc4d9 remove use of log2(). Use VP8LFastLog2() instead. +8c515d54 Merge "harness some malloc/calloc to use WebPSafeMalloc and WebPSafeCalloc" into 0.2.0 +d4b4bb02 Merge changes I46090628,I1a41b2ce into 0.2.0 +bff34ac1 harness some malloc/calloc to use WebPSafeMalloc and WebPSafeCalloc +a3c063c7 Merge "extra size check for security" into 0.2.0 +5e796300 Merge "WebPEncode: clear stats at the start of encode" into 0.2.0 +f1edf62f Merge "rationalize use of color-cache" into 0.2.0 +c1933317 extra size check for security +906be657 rationalize use of color-cache +dd1c3873 Add image-hint for low-color images. +4eb7aa64 Merge "WebPCheckMalloc() and WebPCheckCalloc():" into 0.2.0 +80cc7303 WebPCheckMalloc() and WebPCheckCalloc(): +183cba83 check VP8LBitWriterInit return +cbfa9eec lossless: fix crash on user abort +256afefa cwebp: exit immediately on version mismatch +475d87d7 WebPEncode: clear stats at the start of encode +a7cc7291 fix type and conversion warnings +7d853d79 add stats for lossless +d39177b7 make QuantizeLevels() store the sum of squared error +5955cf5e replace x*155/100 by x*101581>>16 +7d732f90 make QuantizeLevels() store the sum of squared error +e45a446a replace x*155/100 by x*101581>>16 +159b75d3 cwebp output size consistency: +cbee59eb Merge commit 'v0.1.99' +1889e9b6 dwebp: report -alpha option +3bc3f7c0 Merge "dwebp: add PAM output support" into 0.2.0 +d919ed06 dwebp: add PAM output support +85e215d3 README/manpages/configure: update website link +c3a207b9 Update ChangeLog (tag: v0.1.99) +d1fd7826 Merge "add extra precision about default values and behaviour" into 0.2.0 +efc826e0 add extra precision about default values and behaviour +9f29635d header/doc clean up +ff9fd1ba Makefile.vc: fix webpmux.exe *-dynamic builds +8aacc7b0 remove INAM, ICOP, ... chunks from the test webp file. +2fc13015 harmonize authors as "Name (mail@address)" +4a9f37b7 Merge "update NEWS" into 0.2.0 +7415ae13 makefile.unix: provide examples/webpmux target +ce82cedc update NEWS +641e28e8 Merge "man/cwebp.1: wording, change the date" into 0.2.0 +c37c23e5 README: cosmetics +3976dcd5 man/cwebp.1: wording, change the date +3e5bbe1c Merge "rename 'use_argb_input' to 'use_argb'" into 0.2.0 +ce90847a Merge "add some padding bytes areas for later use" into 0.2.0 +2390dabc Merge "fixing the findings by Frederic Kayser to the bitstream spec" into 0.2.0 +02751591 add a very crude progress report for lossless +a4b9b1c6 Remove some unused enum values. +dd108176 rename 'use_argb_input' to 'use_argb' +90516ae8 add some padding bytes areas for later use +d03b2503 fixing the findings by Frederic Kayser to the bitstream spec +ce156afc add missing ABI compatibility checks +9d45416a Merge "Doc: container spec text tweaks" into 0.2.0 +4e2e0a8c Doc: container spec text tweaks +f7f16a29 add ABI compatibility check +2a775570 Merge "swig: add WebPEncodeLossless* wrappers" into 0.2.0 +a3ec6225 mux.h: remove '* const' from function parameters +31426eba encode.h: remove '* const' from function parameters +9838e5d5 decode.h: remove '* const' from function parameters +4972302d swig: add WebPEncodeLossless* wrappers +9ff00cae bump encoder/decoder versions +c2416c9b add lossless quick encoding functions to the public API +4c1f5d64 Merge "NEWS: mention decode_vp8.h is no longer installed" into 0.2.0 +6cb2277d NEWS: mention decode_vp8.h is no longer installed +d5e5ad63 move decode_vp8.h from webp/ to dec/ +8d3b04a2 Merge "header clean-up" into 0.2.0 +02201c35 Merge "remove one malloc() by making color_cache non dynamic" into 0.2.0 +d708ec14 Merge "move MIN/MAX_HISTO_BITS to format_constants.h" into 0.2.0 +ab2da3e9 Merge "add a malloc() check" into 0.2.0 +2d571bd8 add a malloc() check +7f0c178e remove one malloc() by making color_cache non dynamic +6569cd7c Merge "VP8LFillBitWindow: use 64-bit path for msvc x64 builds" into 0.2.0 +23d34f31 header clean-up +2a3ab6f9 move MIN/MAX_HISTO_BITS to format_constants.h +985d3da6 Merge "shuffle variables in HashChainFindCopy" into 0.2.0 +cdf885c6 shuffle variables in HashChainFindCopy +c3b014db Android.mk: add missing lossless files +8c1cc6b5 makefile.unix dist: explicitly name installed includes +7f4647ee Merge "clarify the colorspace naming and byte ordering of decoded samples" into 0.2.0 +cbf69724 clarify the colorspace naming and byte ordering of decoded samples +857650c8 Mux: Add WebPDataInit() and remove WebPImageInfo +ff771e77 don't install webp/decode_vp8.h +596dff78 VP8LFillBitWindow: use 64-bit path for msvc x64 builds +3ca7ce98 Merge "doc: remove non-finalized chunk references" into 0.2.0 +1efaa5a3 Merge "bump versions" into 0.2.0 +51fa13e1 Merge "README: update cwebp help output" into 0.2.0 +12f9aede README: update cwebp help output +f0b5defb bump versions +4c42a61b update AUTHORS +6431a1ce doc: remove non-finalized chunk references +8130c4cc Merge "build: remove libwebpmux from default targets/config" +23b44438 Merge "configure: broaden test for libpng-config" +85bff2cd Merge "doc: correct lossless prefix coding table & code" +05108f6e Merge "More spec/code matching in mux:" +6808e69d More spec/code matching in mux: +bd2b46f5 Merge "doc/webp-container-spec: light cosmetics" +20ead329 doc/webp-container-spec: light cosmetics +1d40a8bc configure: add pthread detection +b5e9067a fix some int <-> size_t mix for buffer sizes +e41a7596 build: remove libwebpmux from default targets/config +0fc2baae configure: broaden test for libpng-config +45b8272c Merge "restore authorship to lossless bitstream doc" +06ba0590 restore authorship to lossless bitstream doc +44a09a3c add missing description of the alpha filtering methods +63db87dd Merge "vwebp: add checkboard background for alpha display" +a73b8978 vwebp: add checkboard background for alpha display +939158ce Merge "vwebp: fix info display" +b35c07d9 vwebp: fix info display +48b39eb1 fix underflow for very short bitstreams +7e622984 cosmetics: param alignment, manpage wording +1bd7dd50 Merge changes I7b0afb0d,I7ecc9708 +ac69e63e Merge "Updated cwebp man's help for Alpha & Lossless." +c0e8859d Get rid of image_info_ from WebPChunk struct. +135ca69e WebP Container Spec: +eb6f9b8a Updated cwebp man's help for Alpha & Lossless. +0fa844fb cosmetic fixes on assert and 'const' where applicable +7f22bd25 check limit of width * height is 32 bits +16c46e83 autoconf/make: cosmetics: break long lines +ab22a07a configure: add helper macro to define --with-* +c17699b3 configure: add libtiff test +0e09732c Merge "cwebp: fix crash with yuv input + lossless" +88a510ff Merge "fix big-endian VP8LWriteBits" +da99e3bf Merge "Makefile.vc: split mux into separate lib" +7bda392b cwebp: fix crash with yuv input + lossless +f56a369a fix big-endian VP8LWriteBits +54169d6c Merge "cwebp: name InputFileFormat members consistently" +e2feefa9 Makefile.vc: split mux into separate lib +27caa5aa Merge "cwebp: add basic TIFF support" +d8921dd4 cwebp: name InputFileFormat members consistently +6f76d246 cwebp: add basic TIFF support +4691407b Merge changes If39ab7f5,I3658b5ae +cca7c7b8 Fixed nit: 10 -> 10.f +5d09a244 WebPMuxCreate() error handling: +777341c3 Fix a memleak in WebPMuxCreate() +61c9d161 doc: correct lossless prefix coding table & code +4c397579 Merge "mark VP8{,L}{GetInfo,CheckSignature} as WEBP_EXTERN" +e4e36cc6 Merge "Mux: Allow only some frames/tiles to have alpha." +ad2aad3c Merge "WebP Decoding error handling:" +97649c8f Mux: Allow only some frames/tiles to have alpha. +f864be3b Lower the quality settings for Alpha encoding. +3ba81bbe WebP Decoding error handling: +fcc69923 add automatic YUVA/ARGB conversion during WebPEncode() +802e012a fix compilation in non-FANCY_UPSAMPLING mode +e012dfd9 make width/height coding match the spec +228d96a5 mark VP8{,L}{GetInfo,CheckSignature} as WEBP_EXTERN +637a314f remove the now unused *KeepA variants +d11f6fcc webpmux returns error strings rather than numbers +fcec0593 makefile.unix: cwebp: fix OSX link +6b811f1b Merge "doc: remove lossless pdf" +c9634821 doc: remove lossless pdf +b9ae4f0d cosmetics after mux changes b74ed6e, b494ad5 +b494ad50 Mux: only allow adding frame/tiles at the end. +2c341b0e Merge "Added image characteristic hint for the codec." +d373076a Added image characteristic hint for the codec. +2ed2adb5 Merge "msvc: add intrinsic based BitsLog2Floor" +e595e7c5 Merge "add demux.c to the makefiles" +da47b5bd Merge "demux: add {Next,Prev}Chunk" +e5f46742 add demux.c to the makefiles +4708393c demux: add {Next,Prev}Chunk +e8a0a821 demux: quiet msvc warnings +7f8472a6 Update the WebP Container Spec. +31b68fe6 cleanup WebPPicture struct and API +9144a186 add overflow check before calling malloc() +81720c91 consistency cosmetics +2ebe8394 Merge "Add kramdown version information to README" +71443084 enc/vp8l.c: fix build +b7ac19fe Add kramdown version information to README +efdcb667 Merge "Edit for consistency, usage and grammar." +08220102 Enable alpha in vvwebp +8de9a084 Merge "Mux API change:" +b74ed6e7 Mux API change: +233a589e take picture->argb_stride into account for lossless coding +04e33f17 Edit for consistency, usage and grammar. +a575b4bc Merge "cosmetics: add missing const" +8d99b0f4 Merge "cosmetics: remove unimplemented function proto" +69d02217 cosmetics: add missing const +5b08318b cosmetics: remove unimplemented function proto +b7fb0ed5 Log warning for unsupported options for lossless. +e1f769fe msvc: add intrinsic based BitsLog2Floor +8a69c7d8 Bug-fix: Clamp backward dist to 1. +b5b6ac97 Merge "Bring the special writer 'WebPMemoryWriter' to public API" +a6a1909f Merge "Fix floating point exception with cwebp -progress" +f2cee067 Fix floating point exception with cwebp -progress +91b7a8c7 Bring the special writer 'WebPMemoryWriter' to public API +310e2972 support resize and crop for RGBA input +a89835d3 Merge changes Ice662960,Ie8d7aa90,I2d996d5e,I01c04772 +ce614c0c Merge "dec/vp8: avoid setting decoder status twice" +900285da dec/vp8: avoid setting decoder status twice +8227adc8 Merge changes I6f02b0d0,I5cbc9c0a,I9dd9d4ed,Id684d2a1 +dcda59c1 Merge "demux: rename SetTile to SelectTile" +622ef12e demux: rename SetTile to SelectTile +81ebd375 Merge "demux: add {Next,Prev}Frame" +02dd37a2 demux: add {Next,Prev}Frame +4b79fa59 Merge "Limit the maximum size of huffman Image to 16MB." +9aa34b34 Manually number "chapters," as chapter numbers are used in the narrative. +2a4c6c29 Re-wrap at <= 72 columns +a45adc19 Apply inline emphasis and monospacing, per gdoc / PDF +91011206 Incorporate gdoc changes through 2012-06-08 +7a182487 Removed CodeRay syntax declarations ... +b3ec18c5 Provide for code-block syntax highlighting. +709d7702 Replace high ASCII artifacts (curly quotes, etc.). +930e8abb Lossless WebP doc largely ported to markdown text. +18cae37b msvc: silence some build warnings +b3923084 Limit the maximum size of huffman Image to 16MB. +f180df2a Merge "libwebp/demux: add Frame/Chunk iteration" +2bbe1c9a Merge "Enable lossless encoder code" +d0601b01 Merge changes I1d97a633,I81c59093 +78f3e345 Enable lossless encoder code +d974a9cc Merge "libwebp/demux: add simple format parsing" +26bf2232 Merge "libwebp: add WebPDemux stub functions" +2f666688 Merge "modify WebPParseHeaders to allow reuse by GetFeatures" +b402b1fb libwebp/demux: add Frame/Chunk iteration +ad9ada3b libwebp/demux: add WebPDemuxGetI +2f2d4d58 libwebp/demux: add extended format parsing +962dcef6 libwebp/demux: add simple format parsing +f8f94081 libwebp: add WebPDemux stub functions +fb47bb5c Merge "NumNamedElements() should take an enum param." +7c689805 Fix asserts in Palette and BackwardReference code. +fbdcb7ea NumNamedElements() should take an enum param. +fb4943bd modify WebPParseHeaders to allow reuse by GetFeatures +3697b5ce write an ad-hoc EncodeImageInternal variant +eaee9e79 Bug-Fix: Decode small (less than 32 bytes) images. +0bceae48 Merge "cwebp: fix alpha reporting in stats output" +0424b1ef Rebase default encoding settings. +c71ff9e3 cwebp: fix alpha reporting in stats output +e2ffe446 Merge "Stop indefinite recursion for Huffman Image." +70eb2bd6 Stop indefinite recursion for Huffman Image. +f3bab8eb Update vwebp +6d5c797c Remove support for partial files in Mux. +f1df5587 WebPMuxAssemble() returns WebPData*. +814a0639 Rename 'Add' APIs to 'Set'. +bbb0218f Update Mux psuedo-code examples. +4fc4a47f Use WebPData in MUX set APIs +c67bc979 Merge "add WebPPictureImportRGBX() and WebPPictureImportBGRX()" +27519bc2 add WebPPictureImportRGBX() and WebPPictureImportBGRX() +f80cd27e factorize code in Import() +9b715026 histogram: add log2 wrapper +8c34378f Merge "fix some implicit type conversion warnings" +42f6df9d fix some implicit type conversion warnings +250c16e3 Merge "doc: update lossless pdf" +9d9daba4 Merge "add a PDF of the lossless spec" +8fbb9188 prefer webp/types.h over stdint.h +0ca170c2 doc: update lossless pdf +0862ac6e add a PDF of the lossless spec +437999fb introduce a generic WebPPictureHasTransparency() function +d2b6c6c0 cosmetic fixes after Idaba281a +b4e6645c Merge "add colorspace for premultiplied alpha" +48f82757 add colorspace for premultiplied alpha +069f903a Change in lossless bit-stream. +5f7bb3f5 Merge "WebPReportProgress: use non-encoder specific params" +f18281ff WebPReportProgress: use non-encoder specific params +9ef32283 Add support for raw lossless bitstream in decoder. +7cbee29a Fix bug: InitIo reseting fancy_upsampling flag. +880fd98c vwebp: fix exit w/freeglut +1875d926 trap two unchecked error conditions +87b4a908 no need to have mux.h as noinst clause in enc/ +88f41ec6 doc: fix bit alignment in VP8X chunk +52f5a4ef Merge "fix bug with lossy-alpha output stride" +3bde22d7 fix bug with lossy-alpha output stride +42d61b6d update the spec for the lossy-alpha compression methods. +e75dc805 Move some more defines to format_constants.h +c13f6632 Move consts to internal header format_constants.h +7f2dfc92 use a bit-set transforms_seen_ instead of looping +18da1f53 modulate alpha-compression effort according to config.method +f5f2fff6 Merge "Alpha flag fix for lossless." +c975c44e Alpha flag fix for lossless. +4f067fb2 Merge "Android: only build dec_neon with NEON support" +255c66b4 Android: only build dec_neon with NEON support +8f9117a9 cosmetics: signature fixes +39bf5d64 use header-less lossless bitstream for alpha channel +75d7f3b2 Merge "make input data be 'const' for VP8LInverseTransform()" +9a721c6d make input data be 'const' for VP8LInverseTransform() +9fc64edc Disallow re-use of same transformation. +98ec717f use a function pointer for ProcessRows() +f7ae5e37 cosmetics: join line +140b89a3 factor out buffer alloc in AllocateARGBBuffers() +a107dfa8 Rectify WebPParseOptionalChunks(). +237eab67 Add two more color-spaces for lossless decoding. +27f417ab fix orthographic typo +489ec335 add VP8LEncodeStream() to compress lossless image stream +fa8bc3db make WebPEncodingSetError() take a const picture +638528cd bitstream update for lossy alpha compression +d73e63a7 add DequantizeLevels() placeholder +ec122e09 remove arch-dependent rand() +d40e7653 fix alignment +1dd6a8b6 Merge "remove tcoder, switch alpha-plane compression to lossless" +3e863dda remove tcoder, switch alpha-plane compression to lossless +8d77dc29 Add support for lossless in mux: +831bd131 Make tile size a function of encoding method. +778c5228 Merge "remove some variable shadowing" +817c9dce Few more HuffmanTreeToken conversions. +37a77a6b remove some variable shadowing +89c07c96 Merge "normalize example header includes" +4aff411f Merge "add example_util.[hc]" +00b29e28 normalize example header includes +061263a7 add example_util.[hc] +c6882c49 merge all tree processing into a single VP8LProcessTree() +9c7a3cf5 fix VP8LHistogramNumCodes to handle the case palette_code_bits == 0 +b5551d2e Merge "Added HuffmanTreeCode Struct for tree codes." +8b85d01c Added HuffmanTreeCode Struct for tree codes. +093f76d8 Merge "Allocate single memory in GetHuffBitLengthsAndCodes." +41d80494 Allocate single memory in GetHuffBitLengthsAndCodes. +1b04f6d2 Correct size in VP8L header. +2924a5ae Makefile.vc: split object lists based on directory +c8f24165 Merge "add assert(tokens)" +43239947 add assert(tokens) +9f547450 Catch an error in DecodeImageData(). +ac8e5e42 minor typo and style fix +9f566d1d clean-up around Huffman-encode +c579a710 Introduce CHUNK_SIZE_BYTES in muxi.h. +14757f8a Make sure huffman trees always have valid symbols +41050618 makefile.unix: add support for building vwebp +48b37721 Merge "fixed signed/unsigned comparison warning" +57f696da Merge "EncodeImageInternal: fix potential leak" +d972cdf2 EncodeImageInternal: fix potential leak +5cd12c3d fixed signed/unsigned comparison warning +cdca30d0 Merge "cosmetics: shorten long line" +e025fb55 cosmetics: shorten long line +22671ed6 Merge "enc/vp8l: fix double free on error" +e1b9b052 Merge "cosmetics: VP8LCreateHuffmanTree: fix indent" +a8e725f8 enc/vp8l: fix double free on error +27541fbd cosmetics: VP8LCreateHuffmanTree: fix indent +1d38b258 cwebp/windows: use MAKE_REFGUID where appropriate +817ef6e9 Merge "cwebp: fix WIC/Microsoft SDK compatibility issue" +902d3e3b cwebp: fix WIC/Microsoft SDK compatibility issue +89d803c4 Merge "Fix a crash due to wrong pointer-integer arithmetic." +cb1bd741 Merge "Fix a crash in lossless decoder." +de2fe202 Merge "Some cleanup in VP8LCreateHuffmanTree() (and related functions CompareHuffmanTrees() and SetBitDepths()): - Move 'tree_size' initialization and malloc for 'tree + tree_pool' outside the loop. - Some renames/tweaks for readability." +ce69177a Fix a crash due to wrong pointer-integer arithmetic. +e40a3684 Fix a crash in lossless decoder. +3927ff3a remove unneeded error condition for WebPMuxNumNamedElements() +2c140e11 Some cleanup in VP8LCreateHuffmanTree() (and related functions CompareHuffmanTrees() and SetBitDepths()): - Move 'tree_size' initialization and malloc for 'tree + tree_pool' outside the loop. - Some renames/tweaks for readability. +861a5b7b add support for animation +eb5c16cc Merge "Set correct encode size in encoder's stats." +4abe04a2 fix the return value and handle missing input file case. +2fafb855 Set correct encode size in encoder's stats. +e7167a2b Provide one entry point for backward references. +c4ccab64 Print relevant lossless encoding stats in cwebp. +e3302cfd GetHuffBitLengthsAndCodes: reduce level of indirection +b5f2a9ed enc/vp8l: fix uninitialized variable warning +7885f8b2 makefile.unix: add lossless encoder files +1261a4c8 Merge "cosmetics" +3926b5be Merge "dsp/cpu.c: Android: fix crash on non-neon arm builds" +834f937f dsp/cpu.c: Android: fix crash on non-neon arm builds +126e1606 cosmetics +e38602d2 Merge branch 'lossless_encoder' +e8d3d6a0 split StoreHuffmanCode() into smaller functions +d0d88990 more consolidation: introduce VP8LHistogramSet +1a210ef1 big code clean-up and refactoring and optimization +41b5c8ff Some cosmetics in histogram.c +ada6ff77 Approximate FastLog between value range [256, 8192] +ec123ca3 Forgot to update out_bit_costs to symbol_bit_costs at one instance. +cf33ccd1 Evaluate output cluster's bit_costs once in HistogramRefine. +781c01f4 Simple Huffman code changes. +a2849bc5 Lossless decoder: remove an unneeded param in ReadHuffmanCodeLengths(). +b39e7487 Reducing emerging palette size from 11 to 9 bits. +bfc73db4 Move GetHistImageSymbols to histogram.c +889a5786 Improve predict vs no-predict heuristic. +01f50663 code-moving and clean-up +31035f3b reduce memory usage by allocating only one histo +fbb501b8 Restrict histo_bits to ensure histo_image size is under 32MB +8415ddf3 further simplification for the meta-Huffman coding +e4917299 A quick pass of cleanup in backward reference code +83332b3c Make transform bits a function of encode method (-m). +72920caa introduce -lossless option, protected by USE_LOSSLESS_ENCODER +c6ac4dfb Run TraceBackwards for higher qualities. +412222c8 Make histo_bits and transform_bits function of quality. +149b5098 Update lossless encoder strategy: +0e6fa065 cache_bits passed to EncodeImageInternal() +e38b40a9 Factorize code for clearing HtreeGroup. +6f4a16ea Removing the indirection of meta-huffman tables. +3d33ecd1 Some renaming/comments related to palette in lossless encoder. +4d02d586 Lossless encoder: correction in Palette storage +4a636235 fix a memleak in EncodeImageInternal() +0993a611 Full and final fix for prediction transform +afd2102f Fix cross-color transform in lossless encoder +b96d8740 Need to write a '0' bit at the end of transforms. +54dad7e5 Color cache size should be counted as 0 when cache bits = 0 +4f0c5caf Fix prediction transform in lossless encoder. +36dabdad Fix memory leak in method EncodeImageInternal for histogram_image. +352a4f49 Get rid of PackLiteralBitLengths() +d673b6b9 Change the predictor function to pass left pixel +b2f99465 Fix CopyTileWithPrediction() +84547f54 Add EncodeImageInternal() method. +6b38378a Guard the lossless encoder (in flux) under a flag +09f7532c Fix few nits (const qualifiers) +648be393 Added implementation for various lossless functions +32714ce3 Add VP8L prefix to backward ref & histogram methods. +fcba7be2 Fixed header file tag (WEBP_UTILS_HUFFMAN_ENCODE_H_) +bc703746 Add backward_ref, histogram & huffman encode modules from lossless. +fdccaadd Fixing nits +227110c4 libwebp interface changes for lossless encoding. +50679acf minor style fixes +b38dfccf remove unneeded reference to NUM_LITERAL_CODES +8979675b harmonize header description +c04eb7be tcoder.c: define NOT_HAVE_LOG2 for MSVC builds +9a214fa1 Merge "VP8[L]GetInfo: check input pointers" +5c5be8ba VP8[L]GetInfo: check input pointers +0c188fec Merge changes I431acdfe,I713659b7 +b3515c62 mux: drop 'chunk' from ChunkInfo member names +aea7923c muxi.h: remove some unused defines +01422492 update NEWS file for next release +29e3f7ec Merge "dec: remove deprecated WebPINew()" +4718e449 Merge "muxedit: a few more size_t changes" +82654f96 Merge "muxedit: remove a few redundant NULL checks" +02f27fbd dec: remove deprecated WebPINew() +ccddb3fc muxedit: remove a few redundant NULL checks +a6cdf710 muxedit: a few more size_t changes +a3846892 Merge "mux: remove unused LIST_ID" +11ae46ae alpha.c: quiet some size_t -> int conversion warnings +dee46692 mux: remove unused LIST_ID +03f1f493 mux: add version checked entry points +6a0abdaa Merge "doc: tile/alpha corrections" +c8139fbe Merge "few cosmetics" +68338737 Merge "lossless: remove some size_t -> int conversions" +5249e94a doc: tile/alpha corrections +d96e722b huffman: quiet int64 -> int conversion warning +532020f2 lossless: remove some size_t -> int conversions +23be6edf few cosmetics +1349edad Merge "configure: AC_ARG_* use AS_HELP_STRING" +bfbcc60a configure: AC_ARG_* use AS_HELP_STRING +1427ca8e Merge "Makefile.am: header file maintenance" +087332e3 Merge "remove unused parameter 'round' from CalcProba()" +9630e168 remove unused parameter 'round' from CalcProba() +92092eaa Merge "bit_reader.h: correct include" +a87fc3f6 Merge "mux: ensure # images = # tiles" +53af99b1 Merge "mux: use size_t consistently" +39a57dae Makefile.am: header file maintenance +1bd0bd0d bit_reader.h: correct include +326a3c6b mux: ensure # images = # tiles +95667b8d mux: use size_t consistently +231ec1fb Removing the indirection of meta-huffman tables. +15ebcbaa check return pointer from MuxImageGetListFromId +b0d6c4a7 Merge "configure: remove test for zlib.h" +8cccac50 Merge "dsp/lossless: silence some build warnings" +b08819a6 dsp/lossless: silence some build warnings +7ae22521 Android.mk: SSE2 & NEON updates +0a49e3f3 Merge "makefile.unix add missing header files" +2e75a9a1 Merge "decode.h: use size_t consistently" +fa13035e configure: remove test for zlib.h +d3adc81d makefile.unix add missing header files +262fe01b Merge "makefile.unix & Android.mk: cosmetics" +4cce137e Merge "enc_sse2 add missing stdlib.h include" +80256b85 enc_sse2 add missing stdlib.h include +9b3d1f3a decode.h: use size_t consistently +64083d3c Merge "Makefile.am: cosmetics" +dceb8b4d Merge changes If1331d3c,I86fe3847 +0e33d7bf Merge "webp/decode.h: fix prototypes" +fac0f12e rename BitReader to VP8LBitReader +fbd82b5a types.h: centralize use of stddef.h +2154835f Makefile.am: cosmetics +1c92bd37 vp8io: use size_t for buffer size +90ead710 fix some more uint32_t -> size_t typing +cbe705c7 webp/decode.h: fix prototypes +3f8ec1c2 makefile.unix & Android.mk: cosmetics +217ec7f4 Remove tabs in configure.ac +b3d35fc1 Merge "Android.mk & Makefile.vc: add new files" +0df04b9e Android.mk & Makefile.vc: add new files +e4f20c5b Merge "automake: replace 'silent-rules' w/AM_SILENT_RULES" +8d254a09 cosmetics +6860c2ea fix some uint32_t -> size_t typing +4af1858a Fix a crash due to max symbol in a tree >= alphabet size +6f01b830 split the VP8 and VP8L decoding properly +f2623dbe enable lossless decoder +b96efd7d add dec/vp8i.h changes from experimental +19f6398e add dec/vp8l{i.h,.c} from experimental +c4ae53c8 add utils/bit_reader.[hc] changes from experimental +514d0089 add dsp/lossless.[hc] from experimental +9c67291d add utils/huffman.[hc] from experimental +337914a0 add utils/color_cache.[hc] from experimental +b3bf8fe7 the read-overflow code-path wasn't reporting as an error +1db888ba take colorspace into account when cropping +61c2d51f move the rescaling code into its own file and make enc/ and dec/ use it. +efc2016a Make rescaler methods generic +3eacee81 Move rescaler methods out of io.c. +a69b893d automake: replace 'silent-rules' w/AM_SILENT_RULES +6f7bf645 issue 111: fix little-endian problem in bit-reader +ed278e22 Removed unnecessary lookup +cd8c3ba7 fix some warnings: down-cast and possibly-uninitialized variable +0a7102ba ~1% improvement of alpha compression +3bc1b141 Merge "Reformat container doc" +dc17abdc mux: cosmetics +cb5810df Merge "WebPMuxGetImage: allow image param to be NULL" +506a4af2 mux: cosmetics +135e8b19 WebPMuxGetImage: allow image param to be NULL +de556b68 Merge "README.mux: reword some descriptions" +0ee2aeb9 Makefile.vc: use batch mode rules +d9acddc0 msvc: move {i,p}db creation to object directory +237c9aa7 Merge "expose WebPFree function for DLL builds" +b3e4054f silence msvc debug build warning +45feb55d expose WebPFree function for DLL builds +11316d84 README.mux: reword some descriptions +4be52f4a factorize WebPMuxValidate +14f6b9f6 mux: light cleanup +5e96a5db add more param checks to WebPPictureDistortion() +8abaf820 Merge "silence some type size related warnings" +1601a39b silence some type size related warnings +f3abe520 Merge "idec: simplify buffer size calculation" +a9c5cd4c idec: simplify buffer size calculation +7b06bd7f Merge "configure/automake: add silent-rules option" +e9a7d145 Reformat container doc +d4e5c7f3 configure/automake: add silent-rules option +5081db78 configure/automake: no -version-info for convenience libs +85b6ff68 Merge "idec: fix WebPIUpdate failure" +7bb6a9cc idec: fix internal state corruption +89cd1bb8 idec: fix WebPIUpdate failure +01b63806 4-5% faster decoding, optimized byte loads in arithmetic decoder. +631117ea Merge "cosmetics & warnings" +a0b2736d cosmetics & warnings +f73947f4 use 32bit for storing dequant coeffs, instead of 16b. +b9600308 Merge "store prediction mode array as uint8_t[16], not int[16]." +7b67881a store prediction mode array as uint8_t[16], not int[16]. +cab8d4dc Merge "NEON TransformOne" +ba503fda NEON TransformOne +9f740e3b Merge "gcc warning fix: remove the 'const' qualifier." +f76d3587 gcc warning fix: remove the 'const' qualifier. +e78478d6 Merge "webpmux: make more use of WebPData" +f85bba3d Merge "manpages: add BUGS section" +48a43bbf Merge "makefile.unix: variable cosmetics" +c274dc96 makefile.unix: variable cosmetics +1f7b8595 re-organize the error-handling in the main loop a bit +1336fa71 Only recompute level_cost_[] when needed +771ee449 manpages: add BUGS section +0f7820e6 webpmux: make more use of WebPData +974aaff3 examples: logging updates +6c14aadd Merge "better token buffer code" +f4054250 better token buffer code +18d959fa Merge "mux: add WebPData type" +eec4b877 mux: add WebPData type +0de3096b use 16bit counters for recording proba counts +7f23678d fix for LevelCost + little speed-up +7107d544 further speed-up/cleanup of RecordCoeffs() and GetResidualCost() +fd221040 Introduce Token buffer (unused for now) +5fa148f4 Merge "speed-up GetResidualCost()" +28a9d9b4 speed-up GetResidualCost() +11e7dadd Merge "misc cosmetics" +378086bd misc cosmetics +d61479f9 add -print_psnr and -print_ssim options to cwebp. +2e3e8b2e add a WebPCleanupTransparentArea() method +552c1217 Merge "mux: plug some memory leaks on error" +a2a81f7d Merge "fix Mach-O shared library build" +b3482c43 Merge "fix gcc-4.0 apple 32-bit build" +e4e3ec19 fix gcc-4.0 apple 32-bit build +b0d2fecf mux: plug some memory leaks on error +f0d2c7a7 pass of cosmetics +b309a6f9 fix Mach-O shared library build +241ddd38 doc: delete mux container pdf +8b1ba272 doc: update VP8 decode guide link +7e4371c5 WebPMuxCreate: fix unchecked malloc +eb425586 Merge "have makefile.unix clean up src/webp/*~ too" +a85c3631 Merge "correct EncodeAlpha documentation" +a33842fd Merge "Update webp container spec with alpha filter options." +8d6490da Incremental support for some of the mux APIs. +b8375abd have makefile.unix clean up src/webp/*~ too +b5855fc7 correct EncodeAlpha documentation +dba37fea Update webp container spec with alpha filter options. +2e74ec8b fix compile under MINGW +716d1d7f fix suboptimal MAX_LEN cut-off limit +57cab7b8 Harmonize the alpha-filter predictions at boundary +3a989534 Merge "Fix bug for Alpha in RGBA_4444 color-mode." +8ca2076d Introduce a 'fast' alpha mode +221a06bb Fix bug for Alpha in RGBA_4444 color-mode. +ad1e163a cosmetics: normalize copyright headers +c77424d7 cosmetics: light include cleanup +9d0e17c9 fix msvc build breakage after 252028a +7c4c177c Some readability fixes for mux library +d8a47e66 Merge "Add predictive filtering option for Alpha." +252028aa Add predictive filtering option for Alpha. +9b69be1c Merge "Simplify mux library code" +a056170e Simplify mux library code +992187a3 improve log2 test +e852f832 update Android.mk file list +a90cb2be reduce number of copies and mallocs in alpha plane enc/dec +b1662b05 fix some more type conversion warnings w/MSVC +223d8c60 fix some uint64_t -> int conversion warnings with MSC +c1a0437b Merge "simplify checks for enabling SSE2 code" +f06817aa simplify checks for enabling SSE2 code +948d4fe9 silence a msvc build warning +91179549 vwebp: msvc build tweaks +7937b409 simple WebP viewer, based on OpenGL +6aac1df1 add a bunch of missing 'extern "C"' +421eb99d Merge "Remove assigned-but-not-used variable "br"" +91e27f45 better fitting names for upsampling functions +a5d7ed5c Remove assigned-but-not-used variable "br" +f62d2c94 remove unused 'has_alpha' from VP8GetInfo() signature +08e86582 trap alpha-decoding error +b361eca1 add cut-off to arith coder probability update. +8666a93a Some bug-fixes for images with alpha. +273a12a0 fix off-by-1 diff in case cropping and simple filtering +2f741d1e webpmux: ReadImage: fix ptr free in error case +721f3f48 fix alpha decode +60942c8c fix the has_alpha_ order +30971c9e Implement progress report (and user abort) +eda520a9 cosmetics after 9523f2a +38bd5bb5 Merge "Better alpha support in webpmux binary" +ccbaebfe Merge "Updated the includes to relative paths." +d71fbdcc fix small typo in error message array +cdf97aa2 Better alpha support in webpmux binary +885f25bc Updated the includes to relative paths. +a0ec9aac Update WebP encoder (cwebp) to support Alpha. +667b769a Fixed the include for types.h within mux.h +9523f2a5 Add Alpha Encode support from WebPEncode. +16612ddd Merge "Add Alpha Decode support from WebPDecode." +d117a940 Add Alpha Decode support from WebPDecode. +67228734 cosmetics after e1947a9 +e1947a92 Add Alpha encode/decode code. +afc4c5d6 simplify code by introducing a CopyPlane() helper func +113b3128 Merge "MUX API Updates" +c398f595 MUX API Updates +5acf04ef remove orphan source file +059f03ef Merge "dec: validate colorspace before using as array index" +70a03989 Merge "factorize some code" +9b243b3d factorize some code +372e2b46 Correct a bug in ReadPNG() with GRAY_ALPHA images +469d6eb9 Merge "Makefile.am: remove redundant noinst_HEADERS" +9fe3372f dec: validate colorspace before using as array index +8962030f remove orphan source file +ced3e3f4 Makefile.am: remove redundant noinst_HEADERS +964387ed use WEBP_INLINE for inline function declarations +90880a11 Merge "manpages: break long lines" +b5910895 Merge "manpages: minor formatting updates" +4c451e4a Merge "Rectify the Chunk parsing logic." +04e84cf1 examples: slight cleanup +099717ce manpages: break long lines +1daf39bb manpages: minor formatting updates +abd030b5 fix missing "(void)" in function signature +f6a7d758 remove useless test +f07b2138 Rectify the Chunk parsing logic. +b8634f7d webpmux: fix lib link order +42c2e682 Fix missing coma (on uncompiled code) +d8329d41 Android.mk: add missing source files +13a54df5 Merge "More aggressive copy-edit; add TODO; validate HTML5" +868b96ae More aggressive copy-edit; add TODO; validate HTML5 +767afea2 configure: check for a symbol contained in libpng +408b8918 Merge "Linewrap at 72 cols. Casual copy-edit." +3ae318c7 Merge "Restore (most) emphasis; add emphasis to normative RFC 2119 terms (MUST, etc.)" +918eb2d8 Merge "Basic container doc source clean-up; fix lists and pseudocode blocks." +03bec9e0 Linewrap at 72 cols. Casual copy-edit. +2678d819 Restore (most) emphasis; add emphasis to normative RFC 2119 terms (MUST, etc.) +428674da Basic container doc source clean-up; fix lists and pseudocode blocks. +6a77d928 Merge "Makefile.vc: cosmetics" +28c38e8c Merge "Makefile.vc: condense directory creation rules" +55be2cf8 Initial import of container spec document, from pdftotext transform. +a82a788b Makefile.vc: cosmetics +c8f41ce5 Makefile.vc: condense directory creation rules +2b877cd0 Some fixes to Makefile.vc to support the src\mux directory. +3eb969b3 Merge "Add Makefile.vc for Mux library & binary." +e78e971e Add Makefile.vc for Mux library & binary. +6aedde58 Add manual for WebPMux tool. +8a360d0a Merge "Added WebPMux Binary." +a4f32cae Added WebPMux Binary. +f3bf4c76 Added Mux Container Spec & README for MUX-API. +9f761cfa Changed function signature for WebPMuxCreate +5f31b5ec Merge "Add Mux library for manipulating WebP container." +2315785f Add Mux library for manipulating WebP container. +7e198abb update ChangeLog (tag: v0.1.3) +dfc9c1ea Harmonize the dates +28ad70c5 Fix PNG decoding bug +846e93c5 Update AUTHORS & add .mailmap +563e52d6 cosmetics after '76036f5 Refactor decoder library' +76036f54 Refactor decoder library +377ef43c configure.ac: update AC_INIT params +7a8d8762 use a user-visible MACRO for max width/height. +d4e9f559 NEON decode support in WebP +0ee683b5 update libtool version-info +fdbe02c5 windows: match _cond_destroy logic w/return variable name +206b686b README: correct advanced decode api pseudo-code +6a32a0f5 make VP8BitReader a typedef, for better re-use +b112e836 create a libwebputils under src/utils +ee697d9f harmonize the include guards and #endif comments +a1ec07a6 Fixing compiler error in non x86 arch. +dcfa509a Fixed recursive inclusion of bit_writer.h and vp8enci.h. +e06ac088 create a separate libwebpdsp under src/dsp +ebeb412a use unsigned int for bitfields +341cc56a make kNewRange a static array +227a91e5 README: minor wording update +05bd8e6a add man pages to dist +812dfa1a bump up versions in preparations for 0.1.3 +a5b78c81 wrap alpha-related options under WEBP_EXPERIMENTAL_FEATURES flag +34dc7907 regen ChangeLog for 0.1.3-rc2 +7c436630 Silence some (more) Visual Studio warnings. +60306e8c add top-level gitattributes +2aa6b80e Slience some Visual Studio warnings. +4cbbb290 Merge "bump up version for next freeze" +a3291674 bump up version for next freeze +c7e86aba cosmetics: fix comment line lengths +c9e037ab makefile.unix: add simple dist target +87d58ce9 makefile.unix: rule maintenance +d477de77 mend +fac15ec7 Update NEWS & README for next release V0.1.3 +6215595c Merge "add a -partition_limit option to limit the number of bits used by intra4x4" +3814b76c Merge "reorganize chunk-parsing code" +900286e0 add a -partition_limit option to limit the number of bits used by intra4x4 +cd12b4b0 add the missing cost for I4/I16 mode selection +dfcc2136 reorganize chunk-parsing code +3cf20306 initialize pointers to function within VP8DspInit() +d21b4795 Merge "windows: add decode threading support" +473ae953 fix hang on thread creation failure +fccca420 windows: add decode threading support +a31f843a Use the exact PNG_INCLUDES/PNG_LIBS when testing for -lpng +ad9b45f1 Merge "Makefile.vc: rule maintenance" +565a2cab Makefile.vc: rule maintenance +2d0da681 makefile.unix: disable Wvla by default +fc7815d6 multi-thread decoding: ~25-30% faster +acd8ba42 io->teardown() was not always called upon error +c85527b1 Merge "Makefile.vc: add DLL configs" +e1e9be35 cosmetics: spelling/grammar in README and lib headers +b4d0ef8f Makefile.vc: add DLL configs +998754a7 remove unused nb_i4_ and nb_i16_ fields. +9f01ce3a rename WebPDecBuffer::memory -> private_memory +fb5d659b fix an overflow bug in LUT calculation +d646d5c7 swig: add WebPDecodeARGB +78aeed40 add missing WebPDecodeARGBInto() and switch ARGB4444 to RGBA4444 as was intended +cd7c5292 explicitly mark library functions as extern +19db59f8 add support for RGB565, ARGB4444 and ARGB colorspace (decoder) +c915fb2a encoder speed-up: hardcode special level values +c558bdad Rename and improve the API to retrieve decoded area +bf599d74 Merge "makefile.unix: disable -Wvla by default" +c9ea03d7 SSE2 version of strong filtering +993af3e2 makefile.unix: disable -Wvla by default +3827e1bc Merge "examples: (windows/WIC) add alpha support" +e291fae0 SSE2 functions for the fancy upsampler. +a06bbe2e add WebPISetIOHooks() to set some custom hooks on the incremental decoder object. +7643a6f2 Merge "makefile.unix: use uname to detect OSX environment" +5142a0be export alpha channel (if present) when dumping to PGM format +14d5731c makefile.unix: use uname to detect OSX environment +08057062 examples: quiet warnings +3cfe0888 examples: (windows/WIC) add alpha support +13ed94b8 add compile warning for variable-length-array +5a18eb1a Merge "add Advanced Decoding Interface" +5c4f27f9 add missing \n +f4c4e416 80 cols fix +d2603105 add Advanced Decoding Interface +bd2f65f6 sse2 version of the complex filter +96ed9ce0 perform two idct transforms at a time when possible +01af7b69 use aligned stored +0e1d1fdf Merge "Makefile.vc: add experimental target" +2a1292a6 Makefile.vc: add experimental target +23bf351e Enable decode SSE2 for Visual Studio +131a4b7b dec/dsp_sse2: fix visual studio compile +00d9d680 swig: file reorganization +7fc7e0d9 Merge "swig/java: basic encode support" +3be57b16 fix MSVC compile for WEBP_EXPERIMENTAL_FEATURES +40a7e347 dec/dsp: disable sse2 for Visual Studio builds +e4d540c8 add SSE2 code for transform +54f2170a swig/java: basic encode support +c5d4584b call function pointers instead of C-version +ea43f045 Merge "configure: mingw32 targets: test for WIC support" +a11009d7 SSE2 version of simple in-loop filtering +42548da9 shave one unneeded filter-cache line +31f9dc6f configure: mingw32 targets: test for WIC support +19559699 Merge "split expression in two." +415dbe46 split expression in two. +e29072a8 configure: test for zlib only w/--enable-experimental +b2b0090b Simplify Visual Studio ifdefs +ca7a2fd6 Add error reporting from encoding failures. +6c9405db Merge "Makefile.vc: require CFG with clean target" +0424ecd9 Makefile.vc: require CFG with clean target +003417c7 Enable SSE2 for Visual Studio builds +af10db4a little speed up for VP8BitUpdate() +e71418f8 more MSVC files to ignore +46d90363 cosmetics +edf59ab3 typo fix +72229f5f Add support for x64 and SSE2 builds under Windows. +92e5c6e1 VP8GetInfo() + WebPResetDecParams() +416b7a6b raise the fixed-point precision for the rescaler +aa87e4e0 fix alignment +eb66670c disable WEBP_EXPERIMENTAL_FEATURES +c5ae7f65 typo fix: USE_ => WEBP_ +d041efae swig: add libwebp.jar/libwebp_java_wrap.c +f6fb3877 add swig interface +e9273902 align buffer for double too +842c009b fix -strong option +d0a70387 Merge "cosmetics" +fc0a02e5 fix the dichotomy loop +38369c03 cosmetics +8dfc4c6f factorize and unify GetAlpha() between the C and SSE2 version +6d0e66c2 prepare experimentation with yuv444 / 422 +79cc49f5 add a --enable-experimental option to './configure' +d7575238 sse2 version of CollectHistogram() +c1c728d6 add an extra #ifdef WEBP_EXPERIMENTAL_FEATURES to avoid 'unused variable' warning +60c61d2d always call VP*EncDeleteAlpha() unconditionnally, for simplicity +0f8c6384 simply don't call WriteExtensions() if WEBP_EXPERIMENTAL_FEATURES is not defined +47c661d5 rename swap -> swap_rb +10d55bbb move chunk[] declaration out of the for() loop +517cec21 fix indentation +f7d9e261 fix merge problems +8fd42b3a add a stride 'a_stride' for the alpha plane +b8dcbf2f fix alpha-plane copy and crop methods +cdef89de fix some 'unused variable' warning +fb29c262 SSE2 version of the fwd transform and the squared sum metric +2ab4b72f EXPERIMENTAL: add support for alpha channel +cfbf88a6 add SSE2 functions. ~2x faster encoding on average. +e7ff3f9a merge two ITransforms together when applicable and change the TTransform to return the sum directly. +ca554137 fix WebPIDecGetRGB() to accept any RGB(A) mode, not just MODE_RGB +8aa50efd fix some 'man' typos +d3f3bdda update ChangeLog (tag: v0.1.2) +d7e9a69c update contributor list +261abb8e add a 'superclean' section +276ae825 Remove files not mean to be in git, and update .gitignore +24868455 build: prepare libwebp.pc +14ceb6e8 add "-version" description to man pages +b247a3b2 Create the m4 directory, and also place .gitignore in there for libtool. +cdd734c9 Resolve automake warnings +c5fa726e build: add pkgconfig files +b20aaca2 build: just use autoreconf, avoid calling tools manually +4b0b0d66 cwebp: use modern functions +efbc6c41 update Android.mk +7777570b better version of ChangeLog +fa70d2b7 update version number in the DOC +f8db5d5d more C89-fixes +0de013b3 fix typos +650ffa3b add version getters for decoder and encoder +be4867d2 doc for incremental decoding +56732a1b add idec.obj in MSVC makefile +208afb5e add c++ guards +8bf76fe0 add incremental decoding +1f288328 'inline' isn't defined in strict ansi c89 +8b77c632 move the quantization function to dsp.c +b2c3575c add a 'last_y' field to WebPDecParams +2654c3da correctly pass along the exact same status returned from ParsePartitions +4704146a add missing precision in the man +6d978a6c add error messages +6463e6ab add some install instructions, and fix intel-mac flags +05fb7bfc Merge ".gitignore: initial version" +c33f0195 .gitignore: initial version +e532b9ab Makefile: allow out of tree builds +4c0da7aa enable sparse dc/ac transforms +07dbb8d5 clarify the return logic +5c69e1bb fix bigger-by-1 array +7c5267e3 fix a (harmless) typo: non_zero_ -> non_zero_ac_ +bc752135 fix missing free() +af3e2aaa remove trailing spaces +13e50da6 make the bitreader preload at least 8bits, instead of post-load them (this makes initialization easier and will be helpful for incremental decoding). Modify ParsePartitions() to accommodate for truncated input. +f4888f77 emit 9 - nb_bits trailing zeros instead of 8 +3db65255 separate block-parsing into a visible VP8DecodeMB() +a871de02 add missing extern "C" +b3ce8c52 remove a gcc warning about type pun by using a proper union'd type +e1863715 update after addition of webpi.h +3e856e2d Extract some useful functions around decoding buffer WebPDecParams. +d5bc05a4 make the filtering process match libvpx and ffvp8 +dd60138d add man pages for cwebp(1) and dwebp(1) +c4fa3644 fix header +5b70b378 * add an option to bypass_filtering in VP8Io. +b97a4003 simplify QuantizeBlock code a bit +84b58ebb add more checks around picture allocation +b65a3e10 remove absolute_delta_ field and syntax code +0744e842 Dont' open output file until we're sure the input file is valid +d5bd54c7 fix typo and buggy line +f7a9549d Add a simple top-level makefile.unix for quick & easy build. +5f36b944 update the doc for the -f option +f61d14aa a WebP encoder converts PNG & JPEG to WebP +81c96621 oops: forgotten call to Initialize() + move the error message to a more useful place +87ffa005 typo: fix a missing 'R', was confusing. +b04b857a * add decoding measurement using stopwatch.h (use -v option) * support PNG output through WIC on Win32 +746a4820 * make (*put)() hook return a bool for abort request. * add an enum for VP8Status() to make things clearer +73c973e6 * strengthen riff/chunk size checks * don't consider odd-sized chunks being an error +1dc4611a add support for PNG output (default) regularize include guards +860641df fix a typo: sizeof(kYModeProbaInter0) => sizeof(kUVModeProbaInter0) +3254fc52 fix some petty constness fix the ./configure file too +504d3393 fix eof_ mis-initialization +2bc0778f leftover Makefile.* from previous commit +d2cf04e4 move Makefile.am one level below, to src/dec fix typos here and there dwebp is now an installed program +ade92de8 typo: vp8.h -> decode_vp8.h +d7241241 forgot to declare types.h to be installed +6421a7a4 move the decoder sourcetree to a sub-location src/dec to make room for future libs sources +a9b3eab6 correct layout name is IMC4. +2330522c handle corner case of zero-dimensions +280c3658 make VP8Init() handle short buffers (< 2 bytes) correctly +b1c9e8b4 handle error cases more robustly +0e94935c Merge "table-less version of clip_8b()" +1e0a2d25 table-less version of clip_8b() +e12109ee dwebp: change -yuv option to -raw change the layout to IMC2 +d72180a4 speed-up fancy upscaler +9145f3bc reset eof_ at construction time +a7ee0559 simplify the logic of GetCoeffs() +f67b5939 lot of cosmetics +ea27d7c6 fix endian problem on PowerPC +beb0a1ba fix signature of VP8StoreBlock +b128c5e2 Merge "fancy chroma upscaling" +6a37a2aa fancy chroma upscaling +ff565edc fix two numeric typos +5a936a0a use uintptr_t for casting pointers to ints +e14a0301 for cross_compiling=yes to prevent executing any binary +83b545ee add vc9+ makefile +296f6914 fix output loop for small height +cbfbb5c3 convert to plain-C +f09f96ee Fix declaration after statement warning +5981ee55 Fix UV plane ac/dc quantizer transposition +c8d15efa convert to ANSI-C +c3f41cb4 Initial commit diff --git a/third-party/webp/libwebp/Makefile.am b/third-party/webp/libwebp/Makefile.am new file mode 100644 index 0000000000..e1c1dd4046 --- /dev/null +++ b/third-party/webp/libwebp/Makefile.am @@ -0,0 +1,9 @@ +ACLOCAL_AMFLAGS = -I m4 +SUBDIRS = sharpyuv src imageio man +EXTRA_DIST = COPYING autogen.sh + +if BUILD_EXTRAS + SUBDIRS += extras +endif + +SUBDIRS += examples diff --git a/third-party/webp/libwebp/Makefile.vc b/third-party/webp/libwebp/Makefile.vc new file mode 100644 index 0000000000..33b68dd57c --- /dev/null +++ b/third-party/webp/libwebp/Makefile.vc @@ -0,0 +1,528 @@ +# +# Stem for static libs and DLLs +# +LIBWEBPDECODER_BASENAME = libwebpdecoder +LIBWEBP_BASENAME = libwebp +LIBWEBPMUX_BASENAME = libwebpmux +LIBWEBPDEMUX_BASENAME = libwebpdemux +LIBSHARPYUV_BASENAME = libsharpyuv + +!IFNDEF ARCH +!IF ! [ cl 2>&1 | find "x86" > NUL ] +ARCH = x86 +!ELSE IF ! [ cl 2>&1 | find "x64" > NUL ] +ARCH = x64 +!ELSE IF ! [ cl 2>&1 | find "ARM" > NUL ] +ARCH = ARM +!ELSE +!ERROR Unable to auto-detect toolchain architecture! \ +If cl.exe is in your PATH rerun nmake with ARCH=. +!ENDIF +!ENDIF + +!IF "$(ARCH)" == "x86" +PLATFORM_LDFLAGS = /SAFESEH +!ENDIF + +############################################################# +## Nothing more to do below this line! + +NOLOGO = /nologo +CCNODBG = cl.exe $(NOLOGO) /O2 /DNDEBUG +CCDEBUG = cl.exe $(NOLOGO) /Od /Zi /D_DEBUG /RTC1 +CFLAGS = /I. /Isrc $(NOLOGO) /W3 /EHsc /c +CFLAGS = $(CFLAGS) /DWIN32 /D_CRT_SECURE_NO_WARNINGS /DWIN32_LEAN_AND_MEAN +LDFLAGS = /LARGEADDRESSAWARE /MANIFEST:EMBED /NXCOMPAT /DYNAMICBASE +LDFLAGS = $(LDFLAGS) $(PLATFORM_LDFLAGS) +LNKDLL = link.exe /DLL $(NOLOGO) +LNKEXE = link.exe $(NOLOGO) +LNKLIB = lib.exe $(NOLOGO) +RCNODBG = rc.exe $(NOLOGO) /l"0x0409" # 0x409 = U.S. English +RCDEBUG = $(RCNODBG) /D_DEBUG + +!IF "$(ARCH)" == "ARM" +CFLAGS = $(CFLAGS) /DWINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP /DWEBP_USE_THREAD +!ELSE +CFLAGS = $(CFLAGS) /DHAVE_WINCODEC_H /DWEBP_USE_THREAD +!ENDIF + +CFGSET = FALSE +!IF "$(OBJDIR)" == "" +OUTDIR = ..\obj\ +!ELSE +OUTDIR = $(OBJDIR) +!ENDIF + +############################################################## +# Runtime library configuration +!IF "$(RTLIBCFG)" == "static" +RTLIB = /MT +RTLIBD = /MTd +!ELSE IF "$(RTLIBCFG)" == "legacy" +RTLIBCFG = static +RTLIB = /MT +RTLIBD = /MTd +CFLAGS = $(CFLAGS) /GS- /arch:IA32 +!ELSE +RTLIB = /MD +RTLIBD = /MDd +!ENDIF +DIRBASE = $(OUTDIR)\$(CFG)\$(ARCH) +DIROBJ = $(DIRBASE)\obj +DIRLIB = $(DIRBASE)\lib +DIRINC = $(DIRBASE)\include +DIRBIN = $(DIRBASE)\bin +LIBWEBP_PDBNAME = $(DIROBJ)\$(LIBWEBP_BASENAME).pdb +OUTPUT_DIRS = $(DIRBIN) $(DIRINC) $(DIRLIB) \ + $(DIROBJ)\dec \ + $(DIROBJ)\demux \ + $(DIROBJ)\dsp \ + $(DIROBJ)\enc \ + $(DIROBJ)\examples \ + $(DIROBJ)\extras \ + $(DIROBJ)\imageio \ + $(DIROBJ)\mux \ + $(DIROBJ)\sharpyuv \ + $(DIROBJ)\utils \ + +# Target configuration +!IF "$(CFG)" == "release-static" +CC = $(CCNODBG) +STATICLIBBUILD = TRUE +!ELSE IF "$(CFG)" == "debug-static" +CC = $(CCDEBUG) +RTLIB = $(RTLIBD) +STATICLIBBUILD = TRUE +LIBWEBPDECODER_BASENAME = $(LIBWEBPDECODER_BASENAME)_debug +LIBWEBP_BASENAME = $(LIBWEBP_BASENAME)_debug +LIBWEBPMUX_BASENAME = $(LIBWEBPMUX_BASENAME)_debug +LIBWEBPDEMUX_BASENAME = $(LIBWEBPDEMUX_BASENAME)_debug +LIBSHARPYUV_BASENAME = $(LIBSHARPYUV_BASENAME)_debug +!ELSE IF "$(CFG)" == "release-dynamic" +CC = $(CCNODBG) +RC = $(RCNODBG) +DLLBUILD = TRUE +!ELSE IF "$(CFG)" == "debug-dynamic" +CC = $(CCDEBUG) +RC = $(RCDEBUG) +RTLIB = $(RTLIBD) +DLLBUILD = TRUE +LIBWEBPDECODER_BASENAME = $(LIBWEBPDECODER_BASENAME)_debug +LIBWEBP_BASENAME = $(LIBWEBP_BASENAME)_debug +LIBWEBPMUX_BASENAME = $(LIBWEBPMUX_BASENAME)_debug +LIBWEBPDEMUX_BASENAME = $(LIBWEBPDEMUX_BASENAME)_debug +LIBSHARPYUV_BASENAME = $(LIBSHARPYUV_BASENAME)_debug +!ENDIF + +!IF "$(STATICLIBBUILD)" == "TRUE" +CC = $(CC) $(RTLIB) +CFGSET = TRUE +LIBWEBPDECODER = $(DIRLIB)\$(LIBWEBPDECODER_BASENAME).lib +LIBWEBP = $(DIRLIB)\$(LIBWEBP_BASENAME).lib +LIBWEBPMUX = $(DIRLIB)\$(LIBWEBPMUX_BASENAME).lib +LIBWEBPDEMUX = $(DIRLIB)\$(LIBWEBPDEMUX_BASENAME).lib +LIBSHARPYUV = $(DIRLIB)\$(LIBSHARPYUV_BASENAME).lib +!ELSE IF "$(DLLBUILD)" == "TRUE" +CC = $(CC) /I$(DIROBJ) $(RTLIB) /DWEBP_DLL +LIBWEBPDECODER = $(DIRLIB)\$(LIBWEBPDECODER_BASENAME)_dll.lib +LIBWEBP = $(DIRLIB)\$(LIBWEBP_BASENAME)_dll.lib +LIBWEBPMUX = $(DIRLIB)\$(LIBWEBPMUX_BASENAME)_dll.lib +LIBWEBPDEMUX = $(DIRLIB)\$(LIBWEBPDEMUX_BASENAME)_dll.lib +LIBSHARPYUV = $(DIRLIB)\$(LIBSHARPYUV_BASENAME)_dll.lib +LIBWEBP_PDBNAME = $(DIROBJ)\$(LIBWEBP_BASENAME)_dll.pdb +CFGSET = TRUE +!ENDIF + +!IF "$(UNICODE)" == "1" +CFLAGS = $(CFLAGS) /D_UNICODE /DUNICODE +!ENDIF + +####################### +# Usage +# +!IF "$(CFGSET)" == "FALSE" +!MESSAGE Usage: nmake /f Makefile.vc [CFG=] +!MESSAGE . [OBJDIR=] [RTLIBCFG=] [UNICODE=1] [] +!MESSAGE +!MESSAGE where is one of: +!MESSAGE - release-static - release static library +!MESSAGE - debug-static - debug static library +!MESSAGE - release-dynamic - release dynamic link library (DLL) +!MESSAGE - debug-dynamic - debug dynamic link library (DLL) +!MESSAGE +!MESSAGE may be: +!MESSAGE - clean - perform a clean for CFG +!MESSAGE - experimental - build CFG with experimental +!MESSAGE . features enabled. +!MESSAGE - (empty) - build libwebp-based targets for CFG +!MESSAGE - all - build (de)mux-based targets for CFG +!MESSAGE - gif2webp - requires libgif & >= VS2013 +!MESSAGE - anim_diff - requires libgif & >= VS2013 +!MESSAGE - anim_dump +!MESSAGE +!MESSAGE RTLIBCFG controls the runtime library linkage - 'static' or 'dynamic'. +!MESSAGE 'legacy' will produce a Windows 2000 compatible library. +!MESSAGE OBJDIR is the path where you like to build (obj, bins, etc.), +!MESSAGE defaults to ..\obj + +!IF "$(CFG)" != "" +!MESSAGE +!ERROR please choose a valid configuration instead of "$(CFG)" +!ENDIF +!ENDIF + +####################### +# Rules +# +!IF "$(CFGSET)" == "TRUE" +# A config was provided, so the library can be built. +# + +SHARPYUV_OBJS = \ + $(DIROBJ)\sharpyuv\sharpyuv.obj \ + $(DIROBJ)\sharpyuv\sharpyuv_cpu.obj \ + $(DIROBJ)\sharpyuv\sharpyuv_csp.obj \ + $(DIROBJ)\sharpyuv\sharpyuv_dsp.obj \ + $(DIROBJ)\sharpyuv\sharpyuv_gamma.obj \ + $(DIROBJ)\sharpyuv\sharpyuv_neon.obj \ + $(DIROBJ)\sharpyuv\sharpyuv_sse2.obj \ + +DEC_OBJS = \ + $(DIROBJ)\dec\alpha_dec.obj \ + $(DIROBJ)\dec\buffer_dec.obj \ + $(DIROBJ)\dec\frame_dec.obj \ + $(DIROBJ)\dec\idec_dec.obj \ + $(DIROBJ)\dec\io_dec.obj \ + $(DIROBJ)\dec\quant_dec.obj \ + $(DIROBJ)\dec\tree_dec.obj \ + $(DIROBJ)\dec\vp8_dec.obj \ + $(DIROBJ)\dec\vp8l_dec.obj \ + $(DIROBJ)\dec\webp_dec.obj \ + +DEMUX_OBJS = \ + $(DIROBJ)\demux\anim_decode.obj \ + $(DIROBJ)\demux\demux.obj \ + +DSP_DEC_OBJS = \ + $(DIROBJ)\dsp\alpha_processing.obj \ + $(DIROBJ)\dsp\alpha_processing_mips_dsp_r2.obj \ + $(DIROBJ)\dsp\alpha_processing_neon.obj \ + $(DIROBJ)\dsp\alpha_processing_sse2.obj \ + $(DIROBJ)\dsp\alpha_processing_sse41.obj \ + $(DIROBJ)\dsp\cpu.obj \ + $(DIROBJ)\dsp\dec.obj \ + $(DIROBJ)\dsp\dec_clip_tables.obj \ + $(DIROBJ)\dsp\dec_mips32.obj \ + $(DIROBJ)\dsp\dec_mips_dsp_r2.obj \ + $(DIROBJ)\dsp\dec_msa.obj \ + $(DIROBJ)\dsp\dec_neon.obj \ + $(DIROBJ)\dsp\dec_sse2.obj \ + $(DIROBJ)\dsp\dec_sse41.obj \ + $(DIROBJ)\dsp\filters.obj \ + $(DIROBJ)\dsp\filters_mips_dsp_r2.obj \ + $(DIROBJ)\dsp\filters_msa.obj \ + $(DIROBJ)\dsp\filters_neon.obj \ + $(DIROBJ)\dsp\filters_sse2.obj \ + $(DIROBJ)\dsp\lossless.obj \ + $(DIROBJ)\dsp\lossless_mips_dsp_r2.obj \ + $(DIROBJ)\dsp\lossless_msa.obj \ + $(DIROBJ)\dsp\lossless_neon.obj \ + $(DIROBJ)\dsp\lossless_sse2.obj \ + $(DIROBJ)\dsp\lossless_sse41.obj \ + $(DIROBJ)\dsp\rescaler.obj \ + $(DIROBJ)\dsp\rescaler_mips32.obj \ + $(DIROBJ)\dsp\rescaler_mips_dsp_r2.obj \ + $(DIROBJ)\dsp\rescaler_msa.obj \ + $(DIROBJ)\dsp\rescaler_neon.obj \ + $(DIROBJ)\dsp\rescaler_sse2.obj \ + $(DIROBJ)\dsp\upsampling.obj \ + $(DIROBJ)\dsp\upsampling_mips_dsp_r2.obj \ + $(DIROBJ)\dsp\upsampling_msa.obj \ + $(DIROBJ)\dsp\upsampling_neon.obj \ + $(DIROBJ)\dsp\upsampling_sse2.obj \ + $(DIROBJ)\dsp\upsampling_sse41.obj \ + $(DIROBJ)\dsp\yuv.obj \ + $(DIROBJ)\dsp\yuv_mips32.obj \ + $(DIROBJ)\dsp\yuv_mips_dsp_r2.obj \ + $(DIROBJ)\dsp\yuv_neon.obj \ + $(DIROBJ)\dsp\yuv_sse2.obj \ + $(DIROBJ)\dsp\yuv_sse41.obj \ + +DSP_ENC_OBJS = \ + $(DIROBJ)\dsp\cost.obj \ + $(DIROBJ)\dsp\cost_mips32.obj \ + $(DIROBJ)\dsp\cost_mips_dsp_r2.obj \ + $(DIROBJ)\dsp\cost_neon.obj \ + $(DIROBJ)\dsp\cost_sse2.obj \ + $(DIROBJ)\dsp\enc.obj \ + $(DIROBJ)\dsp\enc_mips32.obj \ + $(DIROBJ)\dsp\enc_mips_dsp_r2.obj \ + $(DIROBJ)\dsp\enc_msa.obj \ + $(DIROBJ)\dsp\enc_neon.obj \ + $(DIROBJ)\dsp\enc_sse2.obj \ + $(DIROBJ)\dsp\enc_sse41.obj \ + $(DIROBJ)\dsp\lossless_enc.obj \ + $(DIROBJ)\dsp\lossless_enc_mips32.obj \ + $(DIROBJ)\dsp\lossless_enc_mips_dsp_r2.obj \ + $(DIROBJ)\dsp\lossless_enc_msa.obj \ + $(DIROBJ)\dsp\lossless_enc_neon.obj \ + $(DIROBJ)\dsp\lossless_enc_sse2.obj \ + $(DIROBJ)\dsp\lossless_enc_sse41.obj \ + $(DIROBJ)\dsp\ssim.obj \ + $(DIROBJ)\dsp\ssim_sse2.obj \ + +EX_ANIM_UTIL_OBJS = \ + $(DIROBJ)\examples\anim_util.obj \ + +IMAGEIO_DEC_OBJS = \ + $(DIROBJ)\imageio\image_dec.obj \ + $(DIROBJ)\imageio\jpegdec.obj \ + $(DIROBJ)\imageio\metadata.obj \ + $(DIROBJ)\imageio\pngdec.obj \ + $(DIROBJ)\imageio\pnmdec.obj \ + $(DIROBJ)\imageio\tiffdec.obj \ + $(DIROBJ)\imageio\webpdec.obj \ + $(DIROBJ)\imageio\wicdec.obj \ + +IMAGEIO_ENC_OBJS = \ + $(DIROBJ)\imageio\image_enc.obj \ + +EX_GIF_DEC_OBJS = \ + $(DIROBJ)\examples\gifdec.obj \ + +EX_UTIL_OBJS = \ + $(DIROBJ)\examples\example_util.obj \ + +ENC_OBJS = \ + $(DIROBJ)\enc\alpha_enc.obj \ + $(DIROBJ)\enc\analysis_enc.obj \ + $(DIROBJ)\enc\backward_references_cost_enc.obj \ + $(DIROBJ)\enc\backward_references_enc.obj \ + $(DIROBJ)\enc\config_enc.obj \ + $(DIROBJ)\enc\cost_enc.obj \ + $(DIROBJ)\enc\filter_enc.obj \ + $(DIROBJ)\enc\frame_enc.obj \ + $(DIROBJ)\enc\histogram_enc.obj \ + $(DIROBJ)\enc\iterator_enc.obj \ + $(DIROBJ)\enc\near_lossless_enc.obj \ + $(DIROBJ)\enc\picture_enc.obj \ + $(DIROBJ)\enc\picture_csp_enc.obj \ + $(DIROBJ)\enc\picture_psnr_enc.obj \ + $(DIROBJ)\enc\picture_rescale_enc.obj \ + $(DIROBJ)\enc\picture_tools_enc.obj \ + $(DIROBJ)\enc\predictor_enc.obj \ + $(DIROBJ)\enc\quant_enc.obj \ + $(DIROBJ)\enc\syntax_enc.obj \ + $(DIROBJ)\enc\token_enc.obj \ + $(DIROBJ)\enc\tree_enc.obj \ + $(DIROBJ)\enc\vp8l_enc.obj \ + $(DIROBJ)\enc\webp_enc.obj \ + +EXTRAS_OBJS = \ + $(DIROBJ)\extras\extras.obj \ + $(DIROBJ)\extras\quality_estimate.obj \ + +IMAGEIO_UTIL_OBJS = \ + $(DIROBJ)\imageio\imageio_util.obj \ + +MUX_OBJS = \ + $(DIROBJ)\mux\anim_encode.obj \ + $(DIROBJ)\mux\muxedit.obj \ + $(DIROBJ)\mux\muxinternal.obj \ + $(DIROBJ)\mux\muxread.obj \ + +UTILS_DEC_OBJS = \ + $(DIROBJ)\utils\bit_reader_utils.obj \ + $(DIROBJ)\utils\color_cache_utils.obj \ + $(DIROBJ)\utils\filters_utils.obj \ + $(DIROBJ)\utils\huffman_utils.obj \ + $(DIROBJ)\utils\palette.obj \ + $(DIROBJ)\utils\quant_levels_dec_utils.obj \ + $(DIROBJ)\utils\rescaler_utils.obj \ + $(DIROBJ)\utils\random_utils.obj \ + $(DIROBJ)\utils\thread_utils.obj \ + $(DIROBJ)\utils\utils.obj \ + +UTILS_ENC_OBJS = \ + $(DIROBJ)\utils\bit_writer_utils.obj \ + $(DIROBJ)\utils\huffman_encode_utils.obj \ + $(DIROBJ)\utils\quant_levels_utils.obj \ + +LIBWEBPDECODER_OBJS = $(DEC_OBJS) $(DSP_DEC_OBJS) $(UTILS_DEC_OBJS) +LIBWEBP_OBJS = $(LIBWEBPDECODER_OBJS) $(ENC_OBJS) \ + $(DSP_ENC_OBJS) $(UTILS_ENC_OBJS) $(DLL_OBJS) +LIBWEBPMUX_OBJS = $(MUX_OBJS) $(LIBWEBPMUX_OBJS) +LIBWEBPDEMUX_OBJS = $(DEMUX_OBJS) $(LIBWEBPDEMUX_OBJS) +LIBSHARPYUV_OBJS = $(SHARPYUV_OBJS) + +OUT_LIBS = $(LIBWEBPDECODER) $(LIBWEBP) $(LIBSHARPYUV) +!IF "$(ARCH)" == "ARM" +ex: $(OUT_LIBS) +all: ex +!ELSE +OUT_EXAMPLES = $(DIRBIN)\cwebp.exe $(DIRBIN)\dwebp.exe +EXTRA_EXAMPLES = $(DIRBIN)\vwebp.exe $(DIRBIN)\webpmux.exe \ + $(DIRBIN)\img2webp.exe $(DIRBIN)\get_disto.exe \ + $(DIRBIN)\webp_quality.exe $(DIRBIN)\vwebp_sdl.exe \ + $(DIRBIN)\webpinfo.exe + +ex: $(OUT_LIBS) $(OUT_EXAMPLES) +all: ex $(EXTRA_EXAMPLES) +# NB: gif2webp.exe and anim_diff.exe are excluded from 'all' as libgif requires +# C99 support which is only available from VS2013 onward. +gif2webp: $(DIRBIN)\gif2webp.exe +anim_diff: $(DIRBIN)\anim_diff.exe +anim_dump: $(DIRBIN)\anim_dump.exe + +$(DIRBIN)\anim_diff.exe: $(DIROBJ)\examples\anim_diff.obj $(EX_ANIM_UTIL_OBJS) +$(DIRBIN)\anim_diff.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) +$(DIRBIN)\anim_diff.exe: $(EX_GIF_DEC_OBJS) $(LIBWEBPDEMUX) $(LIBWEBP) +$(DIRBIN)\anim_dump.exe: $(DIROBJ)\examples\anim_dump.obj $(EX_ANIM_UTIL_OBJS) +$(DIRBIN)\anim_dump.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) +$(DIRBIN)\anim_dump.exe: $(EX_GIF_DEC_OBJS) $(LIBWEBPDEMUX) $(LIBWEBP) +$(DIRBIN)\anim_dump.exe: $(IMAGEIO_ENC_OBJS) +$(DIRBIN)\cwebp.exe: $(DIROBJ)\examples\cwebp.obj $(IMAGEIO_DEC_OBJS) +$(DIRBIN)\cwebp.exe: $(IMAGEIO_UTIL_OBJS) +$(DIRBIN)\cwebp.exe: $(LIBWEBPDEMUX) $(LIBSHARPYUV) +$(DIRBIN)\dwebp.exe: $(DIROBJ)\examples\dwebp.obj $(IMAGEIO_DEC_OBJS) +$(DIRBIN)\dwebp.exe: $(IMAGEIO_ENC_OBJS) +$(DIRBIN)\dwebp.exe: $(IMAGEIO_UTIL_OBJS) +$(DIRBIN)\dwebp.exe: $(LIBWEBPDEMUX) +$(DIRBIN)\gif2webp.exe: $(DIROBJ)\examples\gif2webp.obj $(EX_GIF_DEC_OBJS) +$(DIRBIN)\gif2webp.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) $(LIBWEBPMUX) +$(DIRBIN)\gif2webp.exe: $(LIBWEBP) +$(DIRBIN)\vwebp.exe: $(DIROBJ)\examples\vwebp.obj $(EX_UTIL_OBJS) +$(DIRBIN)\vwebp.exe: $(IMAGEIO_UTIL_OBJS) $(LIBWEBPDEMUX) $(LIBWEBP) +$(DIRBIN)\vwebp_sdl.exe: $(DIROBJ)\extras\vwebp_sdl.obj +$(DIRBIN)\vwebp_sdl.exe: $(DIROBJ)\extras\webp_to_sdl.obj +$(DIRBIN)\vwebp_sdl.exe: $(IMAGEIO_UTIL_OBJS) $(LIBWEBP) +$(DIRBIN)\webpmux.exe: $(DIROBJ)\examples\webpmux.obj $(LIBWEBPMUX) +$(DIRBIN)\webpmux.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) $(LIBWEBP) +$(DIRBIN)\img2webp.exe: $(DIROBJ)\examples\img2webp.obj $(LIBWEBPMUX) +$(DIRBIN)\img2webp.exe: $(IMAGEIO_DEC_OBJS) +$(DIRBIN)\img2webp.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) +$(DIRBIN)\img2webp.exe: $(LIBWEBPDEMUX) $(LIBWEBP) $(LIBSHARPYUV) +$(DIRBIN)\get_disto.exe: $(DIROBJ)\extras\get_disto.obj +$(DIRBIN)\get_disto.exe: $(IMAGEIO_DEC_OBJS) $(IMAGEIO_UTIL_OBJS) +$(DIRBIN)\get_disto.exe: $(LIBWEBPDEMUX) $(LIBWEBP) +$(DIRBIN)\webp_quality.exe: $(DIROBJ)\extras\webp_quality.obj +$(DIRBIN)\webp_quality.exe: $(IMAGEIO_UTIL_OBJS) +$(DIRBIN)\webp_quality.exe: $(EXTRAS_OBJS) +# EXTRA_OBJS requires private symbols from dsp. Explicitly add those when +# building libwebp as a dll. +!IF "$(DLLBUILD)" == "TRUE" +$(DIRBIN)\webp_quality.exe: $(DSP_DEC_OBJS) +!ENDIF +$(DIRBIN)\webp_quality.exe: $(LIBWEBP) +$(DIRBIN)\webpinfo.exe: $(DIROBJ)\examples\webpinfo.obj +$(DIRBIN)\webpinfo.exe: $(IMAGEIO_DEC_OBJS) +$(DIRBIN)\webpinfo.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) +$(DIRBIN)\webpinfo.exe: $(LIBWEBPDEMUX) $(LIBWEBP) + +$(OUT_EXAMPLES): $(EX_UTIL_OBJS) $(LIBWEBP) +$(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS): $(OUTPUT_DIRS) +$(IMAGEIO_DEC_OBJS) $(IMAGEIO_ENC_OBJS) $(EXTRAS_OBJS): $(OUTPUT_DIRS) +!ENDIF # ARCH == ARM + +$(LIBSHARPYUV): $(LIBSHARPYUV_OBJS) +$(LIBWEBPDECODER): $(LIBWEBPDECODER_OBJS) +$(LIBWEBP): $(LIBWEBP_OBJS) $(LIBSHARPYUV) +$(LIBWEBPMUX): $(LIBWEBPMUX_OBJS) +$(LIBWEBPDEMUX): $(LIBWEBPDEMUX_OBJS) + +$(LIBWEBP_OBJS) $(LIBWEBPMUX_OBJS) $(LIBWEBPDEMUX_OBJS) $(LIBSHARPYUV_OBJS): \ + $(OUTPUT_DIRS) + +!IF "$(DLLBUILD)" == "TRUE" +{$(DIROBJ)}.c{$(DIROBJ)}.obj: + $(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$@ $< + +{src}.rc{$(DIROBJ)}.res: + $(RC) /fo$@ $< +{src\demux}.rc{$(DIROBJ)\demux}.res: + $(RC) /fo$@ $< +{src\mux}.rc{$(DIROBJ)\mux}.res: + $(RC) /fo$@ $< +{sharpyuv}.rc{$(DIROBJ)\sharpyuv}.res: + $(RC) /fo$@ $< + +$(LIBSHARPYUV): $(DIROBJ)\sharpyuv\$(LIBSHARPYUV_BASENAME:_debug=).res +$(LIBWEBP): $(LIBSHARPYUV) $(DIROBJ)\$(LIBWEBP_BASENAME:_debug=).res +$(LIBWEBPDECODER): $(DIROBJ)\$(LIBWEBPDECODER_BASENAME:_debug=).res +$(LIBWEBPMUX): $(LIBWEBP) $(DIROBJ)\mux\$(LIBWEBPMUX_BASENAME:_debug=).res +$(LIBWEBPDEMUX): $(LIBWEBP) $(DIROBJ)\demux\$(LIBWEBPDEMUX_BASENAME:_debug=).res + +$(LIBWEBPDECODER) $(LIBWEBP) $(LIBWEBPMUX) $(LIBWEBPDEMUX) $(LIBSHARPYUV): + $(LNKDLL) /out:$(DIRBIN)\$(@B:_dll=.dll) /implib:$@ $(LFLAGS) $** + -xcopy $(DIROBJ)\*.pdb $(DIRLIB) /y +!ELSE +$(LIBWEBPDECODER) $(LIBWEBP) $(LIBWEBPMUX) $(LIBWEBPDEMUX) $(LIBSHARPYUV): + $(LNKLIB) /out:$@ $** + -xcopy $(DIROBJ)\*.pdb $(DIRLIB) /y +!ENDIF + +$(OUTPUT_DIRS): + @if not exist "$(@)" mkdir "$(@)" + +.SUFFIXES: .c .obj .res .exe +# File-specific flag builds. Note batch rules take precedence over wildcards, +# so for now name each file individually. +$(DIROBJ)\examples\anim_diff.obj: examples\anim_diff.c + $(CC) $(CFLAGS) /DWEBP_HAVE_GIF /Fd$(LIBWEBP_PDBNAME) \ + /Fo$(DIROBJ)\examples\ examples\$(@B).c +$(DIROBJ)\examples\anim_dump.obj: examples\anim_dump.c + $(CC) $(CFLAGS) /DWEBP_HAVE_GIF /Fd$(LIBWEBP_PDBNAME) \ + /Fo$(DIROBJ)\examples\ examples\$(@B).c +$(DIROBJ)\examples\anim_util.obj: examples\anim_util.c + $(CC) $(CFLAGS) /DWEBP_HAVE_GIF /Fd$(LIBWEBP_PDBNAME) \ + /Fo$(DIROBJ)\examples\ examples\$(@B).c +$(DIROBJ)\examples\gif2webp.obj: examples\gif2webp.c + $(CC) $(CFLAGS) /DWEBP_HAVE_GIF /Fd$(LIBWEBP_PDBNAME) \ + /Fo$(DIROBJ)\examples\ examples\$(@B).c +$(DIROBJ)\examples\gifdec.obj: examples\gifdec.c + $(CC) $(CFLAGS) /DWEBP_HAVE_GIF /Fd$(LIBWEBP_PDBNAME) \ + /Fo$(DIROBJ)\examples\ examples\$(@B).c +# Batch rules +{examples}.c{$(DIROBJ)\examples}.obj:: + $(CC) $(CFLAGS) /Fd$(DIROBJ)\examples\ /Fo$(DIROBJ)\examples\ $< +{extras}.c{$(DIROBJ)\extras}.obj:: + $(CC) $(CFLAGS) /Fd$(DIROBJ)\extras\ /Fo$(DIROBJ)\extras\ $< +{imageio}.c{$(DIROBJ)\imageio}.obj:: + $(CC) $(CFLAGS) /Fd$(DIROBJ)\imageio\ /Fo$(DIROBJ)\imageio\ $< +{sharpyuv}.c{$(DIROBJ)\sharpyuv}.obj:: + $(CC) $(CFLAGS) /Fd$(DIROBJ)\sharpyuv\ /Fo$(DIROBJ)\sharpyuv\ $< +{src\dec}.c{$(DIROBJ)\dec}.obj:: + $(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\dec\ $< +{src\demux}.c{$(DIROBJ)\demux}.obj:: + $(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\demux\ $< +{src\dsp}.c{$(DIROBJ)\dsp}.obj:: + $(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\dsp\ $< +{src\enc}.c{$(DIROBJ)\enc}.obj:: + $(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\enc\ $< +{src\mux}.c{$(DIROBJ)\mux}.obj:: + $(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\mux\ $< +{src\utils}.c{$(DIROBJ)\utils}.obj:: + $(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\utils\ $< + +LNKLIBS = ole32.lib windowscodecs.lib shlwapi.lib +!IF "$(UNICODE)" == "1" +LNKLIBS = $(LNKLIBS) Shell32.lib +!ENDIF + +{$(DIROBJ)\examples}.obj{$(DIRBIN)}.exe: + $(LNKEXE) $(LDFLAGS) /OUT:$@ $** $(LNKLIBS) + +{$(DIROBJ)\extras}.obj{$(DIRBIN)}.exe: + $(LNKEXE) $(LDFLAGS) /OUT:$@ $** $(LNKLIBS) + +clean:: + @-erase /s $(DIROBJ)\*.dll 2> NUL + @-erase /s $(DIROBJ)\*.exp 2> NUL + @-erase /s $(DIROBJ)\*.idb 2> NUL + @-erase /s $(DIROBJ)\*.lib 2> NUL + @-erase /s $(DIROBJ)\*.obj 2> NUL + @-erase /s $(DIROBJ)\*.pch 2> NUL + @-erase /s $(DIROBJ)\*.pdb 2> NUL + @-erase /s $(DIROBJ)\*.res 2> NUL + +!ENDIF # End of case where a config was provided. diff --git a/third-party/webp/libwebp/NEWS b/third-party/webp/libwebp/NEWS new file mode 100644 index 0000000000..47f8451482 --- /dev/null +++ b/third-party/webp/libwebp/NEWS @@ -0,0 +1,315 @@ +- 9/13/2023: version 1.3.2 + This is a binary compatible release. + * security fix for lossless decoder (chromium: #1479274, CVE-2023-4863) + +- 6/23/2023: version 1.3.1 + This is a binary compatible release. + * security fixes for lossless encoder (#603, chromium: #1420107, #1455619, + CVE-2023-1999) + * improve error reporting through WebPPicture error codes + * fix upsampling for RGB565 and RGBA4444 in NEON builds + * img2webp: add -sharp_yuv & -near_lossless + * Windows builds: + - fix compatibility with clang-cl (#607) + - improve Arm64 performance with cl.exe + - add Arm64EC support + * fix webp_js with emcc >= 3.1.27 (stack size change, #614) + * CMake fixes (#592, #610, #612) + * further updates to the container and lossless bitstream docs (#581, #611) + +- 12/16/2022: version 1.3.0 + This is a binary compatible release. + * add libsharpyuv, which exposes -sharp_yuv/config.use_sharp_yuv + functionality to other libraries; libwebp now depends on this library + * major updates to the container and lossless bitstream docs (#448, #546, + #551) + * miscellaneous warning, bug & build fixes (#576, #583, #584) + +- 8/4/2022: version 1.2.4 + This is a binary compatible release. + * restore CMake libwebpmux target name for compatibility with 1.2.2 (#575) + * fix lossless crunch mode encoding with WEBP_REDUCE_SIZE + (chromium: #1345547, #1345595, #1345772, #1345804) + +- 6/30/2022: version 1.2.3 + This is a binary compatible release. + * security fix for lossless encoder (#565, chromium:1313709) + * improved progress granularity in WebPReportProgress() when using lossless + * improved precision in Sharp YUV (-sharp_yuv) conversion + * many corrections to webp-lossless-bitstream-spec.txt (#551) + * crash/leak fixes on error/OOM and other bug fixes (#558, #563, #569, #573) + +- 1/11/2022: version 1.2.2 + This is a binary compatible release. + * webpmux: add "-set bgcolor A,R,G,B" + * add ARM64 NEON support for MSVC builds (#539) + * fix duplicate include error in Xcode when using multiple XCFrameworks in a + project (#542) + * doc updates and bug fixes (#538, #544, #548, #550) + +- 7/20/2021: version 1.2.1 + This is a binary compatible release. + * minor lossless encoder improvements and x86 color conversion speed up + * add ARM64 simulator support to xcframeworkbuild.sh (#510) + * further security related hardening in libwebp & examples + (issues: #497, #508, #518) + (chromium: #1196480, #1196773, #1196775, #1196777, #1196778, #1196850) + (oss-fuzz: #28658, #28978) + * toolchain updates and bug fixes (#498, #501, #502, #504, #505, #506, #509, + #533) + * use more inclusive language within the source (#507) + +- 12/23/2020: version 1.2.0 + * API changes: + - libwebp: + encode.h: add a qmin / qmax range for quality factor (cwebp adds -qrange) + * lossless encoder improvements + * SIMD support for Wasm builds + * add xcframeworkbuild.sh, supports Mac Catalyst builds + * import fuzzers from oss-fuzz & chromium (#409) + * webpmux: add an '-set loop ' option (#494) + * toolchain updates and bug fixes (#449, #463, #470, #475, #477, #478, #479, + #488, #491) + +- 12/18/2019: version 1.1.0 + * API changes: + - libwebp: + WebPMalloc (issue #442) + - extras: + WebPUnmultiplyARGB + * alpha decode fix (issue #439) + * toolchain updates and bug fixes + (chromium: #1026858, #1027136, #1027409, #1028620, #1028716, #995200) + (oss-fuzz: #19430, #19447) + +- 7/4/2019: version 1.0.3 + This is a binary compatible release. + * resize fixes for Nx1 sizes and the addition of non-opaque alpha values for + odd sizes (issues #418, #434) + * lossless encode/decode performance improvements + * lossy compression performance improvement at low quality levels with flat + content (issue #432) + * python swig files updated to support python 3 + Tool updates: + vwebp will now preserve the aspect ratio of images that exceed monitor + resolution by scaling the image to fit (issue #433) + +- 1/14/2019: version 1.0.2 + This is a binary compatible release. + * (Windows) unicode file support in the tools (linux and mac already had + support, issue #398) + * lossless encoder speedups + * lossy encoder speedup on ARM + * lossless multi-threaded security fix (chromium:917029) + +- 11/2/2018: version 1.0.1 + This is a binary compatible release. + * lossless encoder speedups + * big-endian fix for alpha decoding (issue #393) + * gif2webp fix for loop count=65535 transcode (issue #382) + * further security related hardening in libwebp & libwebpmux + (issues #383, #385, #386, #387, #388, #391) + (oss-fuzz #9099, #9100, #9105, #9106, #9111, #9112, #9119, #9123, #9170, + #9178, #9179, #9183, #9186, #9191, #9364, #9417, #9496, #10349, + #10423, #10634, #10700, #10838, #10922, #11021, #11088, #11152) + * miscellaneous bug & build fixes (issues #381, #394, #396, #397, #400) + +- 4/2/2018: version 1.0.0 + This is a binary compatible release. + * lossy encoder improvements to avoid chroma shifts in various circumstances + (issues #308, #340) + * big-endian fixes for decode, RGBA import and WebPPictureDistortion + Tool updates: + gifwebp, anim_diff - default duration behavior (<= 10ms) changed to match + web browsers, transcoding tools (issue #379) + img2webp, webpmux - allow options to be passed in via a file (issue #355) + +- 11/24/2017: version 0.6.1 + This is a binary compatible release. + * lossless performance and compression improvements + a new 'cruncher' mode + (-m 6 -q 100) + * ARM performance improvements with clang (15-20% w/ndk r15c, issue #339) + * webp-js: emscripten/webassembly based javascript decoder + * miscellaneous bug & build fixes (issue #329, #332, #343, #353, #360, #361, + #363) + Tool updates / additions: + added webpinfo - prints file format information (issue #330) + gif2webp - loop behavior modified to match Chrome M63+ (crbug.com/649264); + '-loop_compatibility' can be used for the old behavior + +- 1/26/2017: version 0.6.0 + * lossless performance and compression improvements + * miscellaneous performance improvements (SSE2, NEON, MSA) + * webpmux gained a -duration option allowing for frame timing modification + * new img2webp utility allowing a sequence of images to be converted to + animated webp + * API changes: + - libwebp: + WebPPictureSharpARGBToYUVA + WebPPlaneDistortion + - libwebpmux / gif2webp: + WebPAnimEncoderOptions: kmax <= 0 now disables keyframes, kmax == 1 + forces all keyframes. See mux.h and the gif2webp + manpage for details. + +- 12/13/2016: version 0.5.2 + This is a binary compatible release. + This release covers CVE-2016-8888 and CVE-2016-9085. + * further security related hardening in the tools; fixes to + gif2webp/AnimEncoder (issues #310, #314, #316, #322), cwebp/libwebp (issue + #312) + * full libwebp (encoder & decoder) iOS framework; libwebpdecoder + WebP.framework renamed to WebPDecoder.framework (issue #307) + * CMake support for Android Studio (2.2) + * miscellaneous build related fixes (issue #306, #313) + * miscellaneous documentation improvements (issue #225) + * minor lossy encoder fixes and improvements + +- 6/14/2016: version 0.5.1 + This is a binary compatible release. + * miscellaneous bug fixes (issues #280, #289) + * reverted alpha plane encoding with color cache for compatibility with + libwebp 0.4.0->0.4.3 (issues #291, #298) + * lossless encoding performance improvements + * memory reduction in both lossless encoding and decoding + * force mux output to be in the extended format (VP8X) when undefined chunks + are present (issue #294) + * gradle, cmake build support + * workaround for compiler bug causing 64-bit decode failures on android + devices using clang-3.8 in the r11c NDK + * various WebPAnimEncoder improvements + +- 12/17/2015: version 0.5.0 + * miscellaneous bug & build fixes (issues #234, #258, #274, #275, #278) + * encoder & decoder speed-ups on x86/ARM/MIPS for lossy & lossless + - note! YUV->RGB conversion was sped-up, but the results will be slightly + different from previous releases + * various lossless encoder improvements + * gif2webp improvements, -min_size option added + * tools fully support input from stdin and output to stdout (issue #168) + * New WebPAnimEncoder API for creating animations + * New WebPAnimDecoder API for decoding animations + * other API changes: + - libwebp: + WebPPictureSmartARGBToYUVA() (-pre 4 in cwebp) + WebPConfig::exact (-exact in cwebp; -alpha_cleanup is now the default) + WebPConfig::near_lossless (-near_lossless in cwebp) + WebPFree() (free'ing webp allocated memory in other languages) + WebPConfigLosslessPreset() + WebPMemoryWriterClear() + - libwebpdemux: removed experimental fragment related fields and functions + - libwebpmux: WebPMuxSetCanvasSize() + * new libwebpextras library with some uncommon import functions: + WebPImportGray/WebPImportRGB565/WebPImportRGB4444 + +- 10/15/15: version 0.4.4 + This is a binary compatible release. + * rescaling out-of-bounds read fix (issue #254) + * various build fixes and improvements (issues #253, #259, #262, #267, #268) + * container documentation update + * gif2webp transparency fix (issue #245) + +- 3/3/15: version 0.4.3 + This is a binary compatible release. + * Android / gcc / iOS / MSVS build fixes and improvements + * lossless decode fix (issue #239 -- since 0.4.0) + * documentation / vwebp updates for animation + * multi-threading fix (issue #234) + +- 10/13/14: version 0.4.2 + This is a binary compatible release. + * Android / gcc build fixes + * (Windows) fix reading from stdin and writing to stdout + * gif2webp: miscellaneous fixes + * fix 'alpha-leak' with lossy compression (issue #220) + * the lossless bitstream spec has been amended to reflect the current code + +- 7/24/14: version 0.4.1 + This is a binary compatible release. + * AArch64 (arm64) & MIPS support/optimizations + * NEON assembly additions: + - ~25% faster lossy decode / encode (-m 4) + - ~10% faster lossless decode + - ~5-10% faster lossless encode (-m 3/4) + * dwebp/vwebp can read from stdin + * cwebp/gif2webp can write to stdout + * cwebp can read webp files; useful if storing sources as webp lossless + +- 12/19/13: version 0.4.0 + * improved gif2webp tool + * numerous fixes, compression improvement and speed-up + * dither option added to decoder (dwebp -dither 50 ...) + * improved multi-threaded modes (-mt option) + * improved filtering strength determination + * New function: WebPMuxGetCanvasSize + * BMP and TIFF format output added to 'dwebp' + * Significant memory reduction for decoding lossy images with alpha. + * Intertwined decoding of RGB and alpha for a shorter + time-to-first-decoded-pixel. + * WebPIterator has a new member 'has_alpha' denoting whether the frame + contains transparency. + * Container spec amended with new 'blending method' for animation. + +- 6/13/13: version 0.3.1 + This is a binary compatible release. + * Add incremental decoding support for images containing ALPH and ICCP chunks. + * Python bindings via swig for the simple encode/decode interfaces similar to + Java. + +- 3/20/13: version 0.3.0 + This is a binary compatible release. + * WebPINewRGB/WebPINewYUVA accept being passed a NULL output buffer + and will perform auto-allocation. + * default filter option is now '-strong -f 60' + * encoding speed-up for lossy methods 3 to 6 + * alpha encoding can be done in parallel to lossy using 'cwebp -mt ...' + * color profile, metadata (XMP/EXIF) and animation support finalized in the + container. + * various NEON assembly additions + Tool updates / additions: + * gif2webp added + * vwebp given color profile & animation support + * cwebp can preserve color profile / metadata with '-metadata' + +- 10/30/12: version 0.2.1 + * Various security related fixes + * cwebp.exe: fix import errors on Windows XP + * enable DLL builds for mingw targets + +- 8/3/12: version 0.2.0 + * Add support for ARGB -> YUVA conversion for lossless decoder + New functions: WebPINewYUVA, WebPIDecGetYUVA + * Add stats for lossless and alpha encoding + * Security related hardening: allocation and size checks + * Add PAM output support to dwebp + +- 7/19/12: version 0.1.99 + * This is a pre-release of 0.2.0, not an rc to allow for further + incompatible changes based on user feedback. + * Alpha channel encode/decode support. + * Lossless encoder/decoder. + * Add TIFF input support to cwebp. + Incompatible changes: + * The encode ABI has been modified to support alpha encoding. + * Deprecated function WebPINew() has been removed. + * Decode function signatures have changed to consistently use size_t over + int/uint32_t. + * decode_vp8.h is no longer installed system-wide. + * cwebp will encode the alpha channel if present. + +- 9/19/11: version 0.1.3 + * Advanced decoding APIs. + * On-the-fly cropping and rescaling of images. + * SSE2 instructions for decoding performance optimizations on x86 based + platforms. + * Support Multi-threaded decoding. + * 40% improvement in Decoding performance. + * Add support for RGB565, RGBA4444 & ARGB image colorspace. + * Better handling of large picture encoding. + +- 3/25/11: version 0.1.2 + * Incremental decoding: picture can be decoded byte-by-byte if needs be. + * lot of bug-fixes, consolidation and stabilization + +- 2/23/11: initial release of version 0.1, with the new encoder +- 9/30/10: initial release version with only the lightweight decoder diff --git a/third-party/webp/libwebp/PATENTS b/third-party/webp/libwebp/PATENTS new file mode 100644 index 0000000000..caedf607e9 --- /dev/null +++ b/third-party/webp/libwebp/PATENTS @@ -0,0 +1,23 @@ +Additional IP Rights Grant (Patents) +------------------------------------ + +"These implementations" means the copyrightable works that implement the WebM +codecs distributed by Google as part of the WebM Project. + +Google hereby grants to you a perpetual, worldwide, non-exclusive, no-charge, +royalty-free, irrevocable (except as stated in this section) patent license to +make, have made, use, offer to sell, sell, import, transfer, and otherwise +run, modify and propagate the contents of these implementations of WebM, where +such license applies only to those patent claims, both currently owned by +Google and acquired in the future, licensable by Google that are necessarily +infringed by these implementations of WebM. This grant does not include claims +that would be infringed only as a consequence of further modification of these +implementations. If you or your agent or exclusive licensee institute or order +or agree to the institution of patent litigation or any other patent +enforcement activity against any entity (including a cross-claim or +counterclaim in a lawsuit) alleging that any of these implementations of WebM +or any code incorporated within any of these implementations of WebM +constitute direct or contributory patent infringement, or inducement of +patent infringement, then any patent rights granted to you under this License +for these implementations of WebM shall terminate as of the date such +litigation is filed. diff --git a/third-party/webp/libwebp/PRESUBMIT.py b/third-party/webp/libwebp/PRESUBMIT.py new file mode 100644 index 0000000000..91ad12e151 --- /dev/null +++ b/third-party/webp/libwebp/PRESUBMIT.py @@ -0,0 +1,245 @@ +# Copyright (c) 2021, Google Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Google nor the names of its contributors may +# be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +"""Top-level presubmit script for libwebp. + +See https://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for +details on the presubmit API built into depot_tools. +""" + +import re +import subprocess2 + +USE_PYTHON3 = True +_BASH_INDENTATION = "2" +_GIT_COMMIT_SUBJECT_LENGTH = 65 +_INCLUDE_BASH_FILES_ONLY = [r".*\.sh$"] +_INCLUDE_MAN_FILES_ONLY = [r"man/.+\.1$"] +_INCLUDE_SOURCE_FILES_ONLY = [r".*\.[ch]$"] +_LIBWEBP_MAX_LINE_LENGTH = 80 + + +def _CheckCommitSubjectLength(input_api, output_api): + """Ensures commit's subject length is no longer than 65 chars.""" + name = "git-commit subject" + cmd = ["git", "log", "-1", "--pretty=%s"] + start = input_api.time.time() + proc = subprocess2.Popen( + cmd, + stderr=subprocess2.PIPE, + stdout=subprocess2.PIPE, + universal_newlines=True) + + stdout, _ = proc.communicate() + duration = input_api.time.time() - start + + if not re.match(r"^Revert", + stdout) and (len(stdout) - 1) > _GIT_COMMIT_SUBJECT_LENGTH: + failure_msg = ( + "The commit subject: %s is too long (%d chars)\n" + "Try to keep this to 50 or less (up to 65 is permitted for " + "non-reverts).\n" + "https://www.git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-" + "Project#_commit_guidelines") % (stdout, len(stdout) - 1) + return output_api.PresubmitError("%s\n (%4.2fs) failed\n%s" % + (name, duration, failure_msg)) + + return output_api.PresubmitResult("%s\n (%4.2fs) success" % (name, duration)) + + +def _CheckDuplicateFiles(input_api, output_api): + """Ensures there are not repeated filenames.""" + all_files = [] + for f in input_api.change.AllFiles(): + for include_file in _INCLUDE_SOURCE_FILES_ONLY: + if re.match(include_file, f): + all_files.append(f) + break + + basename_to_path = {} + for f in all_files: + basename_file = input_api.basename(f) + if basename_file in basename_to_path: + basename_to_path[basename_file].append(f) + else: + basename_to_path[basename_file] = [f] + + dupes = [] + for files in basename_to_path.values(): + if len(files) > 1: + dupes.extend(files) + + if dupes: + return output_api.PresubmitError( + "Duplicate source files, rebase or rename some to make them unique:\n%s" + % dupes) + return output_api.PresubmitResult("No duplicates, success\n") + + +def _GetFilesToSkip(input_api): + return list(input_api.DEFAULT_FILES_TO_SKIP) + [ + r"swig/.*\.py$", + r"\.pylintrc$", + ] + + +def _RunManCmd(input_api, output_api, man_file): + """man command wrapper.""" + cmd = ["man", "--warnings", "-EUTF-8", "-l", "-Tutf8", "-Z", man_file] + name = "Check %s file." % man_file + start = input_api.time.time() + output, _ = subprocess2.communicate( + cmd, stdout=None, stderr=subprocess2.PIPE, universal_newlines=True) + duration = input_api.time.time() - start + if output[1]: + return output_api.PresubmitError("%s\n%s (%4.2fs) failed\n%s" % + (name, " ".join(cmd), duration, output[1])) + return output_api.PresubmitResult("%s\n%s (%4.2fs)\n" % + (name, " ".join(cmd), duration)) + + +def _RunShellCheckCmd(input_api, output_api, bash_file): + """shellcheck command wrapper.""" + cmd = ["shellcheck", "-x", "-oall", "-sbash", bash_file] + name = "Check %s file." % bash_file + start = input_api.time.time() + output, rc = subprocess2.communicate( + cmd, stdout=None, stderr=subprocess2.PIPE, universal_newlines=True) + duration = input_api.time.time() - start + if rc == 0: + return output_api.PresubmitResult("%s\n%s (%4.2fs)\n" % + (name, " ".join(cmd), duration)) + return output_api.PresubmitError("%s\n%s (%4.2fs) failed\n%s" % + (name, " ".join(cmd), duration, output[1])) + + +def _RunShfmtCheckCmd(input_api, output_api, bash_file): + """shfmt command wrapper.""" + cmd = [ + "shfmt", "-i", _BASH_INDENTATION, "-bn", "-ci", "-sr", "-kp", "-d", + bash_file + ] + name = "Check %s file." % bash_file + start = input_api.time.time() + output, rc = subprocess2.communicate( + cmd, stdout=None, stderr=subprocess2.PIPE, universal_newlines=True) + duration = input_api.time.time() - start + if rc == 0: + return output_api.PresubmitResult("%s\n%s (%4.2fs)\n" % + (name, " ".join(cmd), duration)) + return output_api.PresubmitError("%s\n%s (%4.2fs) failed\n%s" % + (name, " ".join(cmd), duration, output[1])) + + +def _RunCmdOnCheckedFiles(input_api, output_api, run_cmd, files_to_check): + """Ensure that libwebp/ files are clean.""" + file_filter = lambda x: input_api.FilterSourceFile( + x, files_to_check=files_to_check, files_to_skip=None) + + affected_files = input_api.change.AffectedFiles(file_filter=file_filter) + results = [ + run_cmd(input_api, output_api, f.AbsoluteLocalPath()) + for f in affected_files + ] + return results + + +def _CommonChecks(input_api, output_api): + """Ensures this patch does not have trailing spaces, extra EOLs, + or long lines. + """ + results = [] + results.extend( + input_api.canned_checks.CheckChangeHasNoCrAndHasOnlyOneEol( + input_api, output_api)) + results.extend( + input_api.canned_checks.CheckChangeHasNoTabs(input_api, output_api)) + results.extend( + input_api.canned_checks.CheckChangeHasNoStrayWhitespace( + input_api, output_api)) + results.append(_CheckCommitSubjectLength(input_api, output_api)) + results.append(_CheckDuplicateFiles(input_api, output_api)) + + source_file_filter = lambda x: input_api.FilterSourceFile( + x, files_to_skip=_GetFilesToSkip(input_api)) + results.extend( + input_api.canned_checks.CheckLongLines( + input_api, + output_api, + maxlen=_LIBWEBP_MAX_LINE_LENGTH, + source_file_filter=source_file_filter)) + + results.extend( + input_api.canned_checks.CheckPatchFormatted( + input_api, + output_api, + check_clang_format=False, + check_python=True, + result_factory=output_api.PresubmitError)) + results.extend( + _RunCmdOnCheckedFiles(input_api, output_api, _RunManCmd, + _INCLUDE_MAN_FILES_ONLY)) + # Run pylint. + results.extend( + input_api.canned_checks.RunPylint( + input_api, + output_api, + files_to_skip=_GetFilesToSkip(input_api), + pylintrc=".pylintrc", + version="2.7")) + + # Binaries shellcheck and shfmt are not installed in depot_tools. + # Installation is needed + try: + subprocess2.communicate(["shellcheck", "--version"]) + results.extend( + _RunCmdOnCheckedFiles(input_api, output_api, _RunShellCheckCmd, + _INCLUDE_BASH_FILES_ONLY)) + print("shfmt") + subprocess2.communicate(["shfmt", "-version"]) + results.extend( + _RunCmdOnCheckedFiles(input_api, output_api, _RunShfmtCheckCmd, + _INCLUDE_BASH_FILES_ONLY)) + except OSError as os_error: + results.append( + output_api.PresubmitPromptWarning( + "%s\nPlease install missing binaries locally." % os_error.args[0])) + return results + + +def CheckChangeOnUpload(input_api, output_api): + results = [] + results.extend(_CommonChecks(input_api, output_api)) + return results + + +def CheckChangeOnCommit(input_api, output_api): + results = [] + results.extend(_CommonChecks(input_api, output_api)) + return results diff --git a/third-party/webp/libwebp/README.md b/third-party/webp/libwebp/README.md new file mode 100644 index 0000000000..a9f2c0e12b --- /dev/null +++ b/third-party/webp/libwebp/README.md @@ -0,0 +1,53 @@ +# WebP Codec + +``` + __ __ ____ ____ ____ + / \\/ \/ _ \/ _ )/ _ \ + \ / __/ _ \ __/ + \__\__/\____/\_____/__/ ____ ___ + / _/ / \ \ / _ \/ _/ + / \_/ / / \ \ __/ \__ + \____/____/\_____/_____/____/v1.3.2 +``` + +WebP codec is a library to encode and decode images in WebP format. This package +contains the library that can be used in other programs to add WebP support, as +well as the command line tools 'cwebp' and 'dwebp' to compress and decompress +images respectively. + +See https://developers.google.com/speed/webp for details on the image format. + +The latest source tree is available at +https://chromium.googlesource.com/webm/libwebp + +It is released under the same license as the WebM project. See +https://www.webmproject.org/license/software/ or the "COPYING" file for details. +An additional intellectual property rights grant can be found in the file +PATENTS. + +## Building + +See the [building documentation](doc/building.md). + +## Encoding and Decoding Tools + +The examples/ directory contains tools to encode and decode images and +animations, view information about WebP images, and more. See the +[tools documentation](doc/tools.md). + +## APIs + +See the [APIs documentation](doc/api.md), and API usage examples in the +`examples/` directory. + +## Bugs + +Please report all bugs to the issue tracker: https://bugs.chromium.org/p/webp + +Patches welcome! See [how to contribute](CONTRIBUTING.md). + +## Discuss + +Email: webp-discuss@webmproject.org + +Web: https://groups.google.com/a/webmproject.org/group/webp-discuss diff --git a/third-party/webp/libwebp/autogen.sh b/third-party/webp/libwebp/autogen.sh new file mode 100755 index 0000000000..8ef9babbae --- /dev/null +++ b/third-party/webp/libwebp/autogen.sh @@ -0,0 +1,2 @@ +#! /bin/sh -e +exec autoreconf -fi diff --git a/third-party/webp/libwebp/build.gradle b/third-party/webp/libwebp/build.gradle new file mode 100644 index 0000000000..14ceebf78c --- /dev/null +++ b/third-party/webp/libwebp/build.gradle @@ -0,0 +1,444 @@ +// Define dependencies. +buildscript { + repositories { + maven { + url "https://jcenter.bintray.com" + } + } + dependencies { + classpath "com.android.tools.build:gradle:${ANDROID_GRADLE_PLUGIN_VERSION}" + } +} + +// Define versions in the project. +project.ext { + buildToolsVersion = "${BUILD_TOOLS_VERSION}" + compileSdkVersion = COMPILE_SDK_VERSION.toInteger() +} + +// Core libraries and executables. +apply plugin: "c" +def NEON +model { + buildTypes { + debug + release + } + platforms { + arm { + architecture "arm" + } + arm64 { + architecture "arm64" + } + x86 { + architecture "x86" + } + x64 { + architecture "x86_64" + } + mips32r2 + mips32r5 + mips64r6 + } + toolChains { + gcc(Gcc) { + target("mips32r2") { + cCompiler.args "-mips32r2" + } + target("mips32r5") { + cCompiler.args "-mips32r5" + } + target("mips64r6") { + cCompiler.args "-mips64r6" + } + } + } + binaries { + all { + if (toolChain in Gcc) { + cCompiler.args "-fPIC" + cCompiler.args "-Wall" + cCompiler.define "ANDROID" + cCompiler.define "HAVE_MALLOC_H" + } + // Optimizations. + if (buildType == buildTypes.release) { + if (toolChain in Gcc) { + cCompiler.args "-finline-functions" + cCompiler.args "-ffast-math" + cCompiler.args "-ffunction-sections" + cCompiler.args "-fdata-sections" + } + if (toolChain in Clang) { + cCompiler.args "-frename-registers -s" + } + } + // mips32 fails to build with clang from r14b + // https://bugs.chromium.org/p/webp/issues/detail?id=343 + if (toolChain in Clang) { + if (getTargetPlatform() == "mips") { + cCompiler.args "-no-integrated-as" + } + } + // Check for NEON usage. + if (getTargetPlatform() == "arm") { + NEON = "c.neon" + cCompiler.define "HAVE_CPU_FEATURES_H" + } else { + NEON = "c" + } + + cCompiler.args "-I" + file(".").absolutePath + } + // Link to pthread for shared libraries. + withType(SharedLibraryBinarySpec) { + if (toolChain in Gcc) { + cCompiler.define "HAVE_PTHREAD" + cCompiler.define "WEBP_USE_THREAD" + linker.args "-pthread" + } + } + } + components { + webp(NativeLibrarySpec) { + sources { + c { + source { + srcDir "sharpyuv" + include "sharpyuv.c" + include "sharpyuv_cpu.c" + include "sharpyuv_csp.c" + include "sharpyuv_dsp.c" + include "sharpyuv_gamma.c" + include "sharpyuv_neon.c" + include "sharpyuv_sse2.c" + srcDir "src/dec" + include "alpha_dec.c" + include "buffer_dec.c" + include "frame_dec.c" + include "idec_dec.c" + include "io_dec.c" + include "quant_dec.c" + include "tree_dec.c" + include "vp8_dec.c" + include "vp8l_dec.c" + include "webp_dec.c" + srcDir "src/dsp" + include "alpha_processing.c" + include "alpha_processing_mips_dsp_r2.c" + include "alpha_processing_neon.$NEON" + include "alpha_processing_sse2.c" + include "alpha_processing_sse41.c" + include "cpu.c" + include "dec.c" + include "dec_clip_tables.c" + include "dec_mips32.c" + include "dec_mips_dsp_r2.c" + include "dec_msa.c" + include "dec_neon.$NEON" + include "dec_sse2.c" + include "dec_sse41.c" + include "filters.c" + include "filters_mips_dsp_r2.c" + include "filters_msa.c" + include "filters_neon.$NEON" + include "filters_sse2.c" + include "lossless.c" + include "lossless_mips_dsp_r2.c" + include "lossless_msa.c" + include "lossless_neon.$NEON" + include "lossless_sse2.c" + include "lossless_sse41.c" + include "rescaler.c" + include "rescaler_mips32.c" + include "rescaler_mips_dsp_r2.c" + include "rescaler_msa.c" + include "rescaler_neon.$NEON" + include "rescaler_sse2.c" + include "upsampling.c" + include "upsampling_mips_dsp_r2.c" + include "upsampling_msa.c" + include "upsampling_neon.$NEON" + include "upsampling_sse2.c" + include "upsampling_sse41.c" + include "yuv.c" + include "yuv_mips32.c" + include "yuv_mips_dsp_r2.c" + include "yuv_neon.$NEON" + include "yuv_sse2.c" + include "yuv_sse41.c" + srcDir "src/utils" + include "bit_reader_utils.c" + include "color_cache_utils.c" + include "filters_utils.c" + include "huffman_utils.c" + include "palette.c" + include "quant_levels_dec_utils.c" + include "random_utils.c" + include "rescaler_utils.c" + include "thread_utils.c" + include "utils.c" + srcDir "src/dsp" + include "cost.c" + include "cost_mips32.c" + include "cost_mips_dsp_r2.c" + include "cost_neon.$NEON" + include "cost_sse2.c" + include "enc.c" + include "enc_mips32.c" + include "enc_mips_dsp_r2.c" + include "enc_msa.c" + include "enc_neon.$NEON" + include "enc_sse2.c" + include "enc_sse41.c" + include "lossless_enc.c" + include "lossless_enc_mips32.c" + include "lossless_enc_mips_dsp_r2.c" + include "lossless_enc_msa.c" + include "lossless_enc_neon.$NEON" + include "lossless_enc_sse2.c" + include "lossless_enc_sse41.c" + include "ssim.c" + include "ssim_sse2.c" + srcDir "src/enc" + include "alpha_enc.c" + include "analysis_enc.c" + include "backward_references_cost_enc.c" + include "backward_references_enc.c" + include "config_enc.c" + include "cost_enc.c" + include "filter_enc.c" + include "frame_enc.c" + include "histogram_enc.c" + include "iterator_enc.c" + include "near_lossless_enc.c" + include "picture_enc.c" + include "picture_csp_enc.c" + include "picture_psnr_enc.c" + include "picture_rescale_enc.c" + include "picture_tools_enc.c" + include "predictor_enc.c" + include "quant_enc.c" + include "syntax_enc.c" + include "token_enc.c" + include "tree_enc.c" + include "vp8l_enc.c" + include "webp_enc.c" + srcDir "src/utils" + include "bit_writer_utils.c" + include "huffman_encode_utils.c" + include "quant_levels_utils.c" + } + exportedHeaders { + srcDir "src" + } + } + } + } + + webpdemux(NativeLibrarySpec) { + sources { + c { + source { + srcDir "src/demux" + include "anim_decode.c" + include "demux.c" + } + } + } + } + + webpmux(NativeLibrarySpec) { + sources { + c { + source { + srcDir "src/mux/" + include "anim_encode.c" + include "muxedit.c" + include "muxinternal.c" + include "muxread.c" + } + } + } + } + + // Executables from examples. + example_util(NativeLibrarySpec) { + binaries { + all { + lib library: "webp", linkage: "static" + } + } + sources { + c { + source { + srcDir "./examples" + include "example_util.c" + } + } + } + } + + imageio_util(NativeLibrarySpec) { + binaries { + all { + lib library: "webp", linkage: "static" + } + } + sources { + c { + source { + srcDir "./imageio" + include "imageio_util.c" + } + } + } + } + + imagedec(NativeLibrarySpec) { + binaries { + all { + lib library: "webpdemux", linkage: "static" + lib library: "webp", linkage: "static" + } + } + sources { + c { + source { + srcDir "./imageio" + include "image_dec.c" + include "jpegdec.c" + include "metadata.c" + include "pngdec.c" + include "pnmdec.c" + include "tiffdec.c" + include "webpdec.c" + } + } + } + } + + imageenc(NativeLibrarySpec) { + binaries { + all { + lib library: "webp", linkage: "static" + lib library: "imageio_util", linkage: "static" + } + } + sources { + c { + source { + srcDir "./imageio" + include "image_enc.c" + } + } + } + } + + cwebp(NativeExecutableSpec) { + binaries { + all { + lib library: "example_util", linkage: "static" + lib library: "imagedec", linkage: "static" + lib library: "imageio_util", linkage: "static" + lib library: "webpdemux", linkage: "static" + lib library: "webp", linkage: "static" + } + } + sources { + c { + source { + srcDir "./examples" + include "cwebp.c" + } + } + } + } + + dwebp(NativeExecutableSpec) { + binaries { + all { + lib library: "example_util", linkage: "static" + lib library: "imagedec", linkage: "static" + lib library: "imageenc", linkage: "static" + lib library: "imageio_util", linkage: "static" + lib library: "webpdemux", linkage: "static" + lib library: "webp" + } + } + sources { + c { + source { + srcDir "./examples" + include "dwebp.c" + } + } + } + } + + webpmux_example(NativeExecutableSpec) { + binaries { + all { + lib library: "example_util", linkage: "static" + lib library: "imageio_util", linkage: "static" + lib library: "webpmux", linkage: "static" + lib library: "webp" + } + } + sources { + c { + source { + srcDir "./examples" + include "webpmux.c" + } + } + } + } + + img2webp_example(NativeExecutableSpec) { + binaries { + all { + lib library: "example_util", linkage: "static" + lib library: "imagedec", linkage: "static" + lib library: "imageio_util", linkage: "static" + lib library: "webpmux", linkage: "static" + lib library: "webpdemux", linkage: "static" + lib library: "webp" + } + } + sources { + c { + source { + srcDir "./examples" + include "img2webp.c" + } + } + } + } + + webpinfo_example(NativeExecutableSpec) { + binaries { + all { + lib library: "example_util", linkage: "static" + lib library: "imageio_util", linkage: "static" + lib library: "webp" + } + } + sources { + c { + source { + srcDir "./examples" + include "webpinfo.c" + } + } + } + } + } + tasks { + // Task to test all possible configurations. + buildAllExecutables(Task) { + dependsOn $.binaries.findAll { it.buildable } + } + } +} diff --git a/third-party/webp/libwebp/cmake/WebPConfig.cmake.in b/third-party/webp/libwebp/cmake/WebPConfig.cmake.in new file mode 100644 index 0000000000..8c883fe11d --- /dev/null +++ b/third-party/webp/libwebp/cmake/WebPConfig.cmake.in @@ -0,0 +1,18 @@ +set(WebP_VERSION @PROJECT_VERSION@) +set(WEBP_VERSION ${WebP_VERSION}) + +@PACKAGE_INIT@ + +if(@WEBP_USE_THREAD@) + include(CMakeFindDependencyMacro) + find_dependency(Threads REQUIRED) +endif() + +include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") + +set_and_check(WebP_INCLUDE_DIR "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@") +set(WEBP_INCLUDE_DIRS ${WebP_INCLUDE_DIRS}) +set(WebP_LIBRARIES "@INSTALLED_LIBRARIES@") +set(WEBP_LIBRARIES "${WebP_LIBRARIES}") + +check_required_components(WebP) diff --git a/third-party/webp/libwebp/cmake/config.h.in b/third-party/webp/libwebp/cmake/config.h.in new file mode 100644 index 0000000000..fe1c53ad9a --- /dev/null +++ b/third-party/webp/libwebp/cmake/config.h.in @@ -0,0 +1,116 @@ +/* Adapted from the autotools src/webp/config.h.in. */ + +/* Define if building universal (internal helper macro) */ +/* TODO: handle properly in CMake */ +#cmakedefine AC_APPLE_UNIVERSAL_BUILD 1 + +/* Set to 1 if __builtin_bswap16 is available */ +#cmakedefine HAVE_BUILTIN_BSWAP16 1 + +/* Set to 1 if __builtin_bswap32 is available */ +#cmakedefine HAVE_BUILTIN_BSWAP32 1 + +/* Set to 1 if __builtin_bswap64 is available */ +#cmakedefine HAVE_BUILTIN_BSWAP64 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_CPU_FEATURES_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_GLUT_GLUT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_GL_GLUT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_OPENGL_GLUT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SHLWAPI_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UNISTD_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_WINCODEC_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_WINDOWS_H 1 + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +/* TODO: handle properly in CMake */ +#cmakedefine LT_OBJDIR "@LT_OBJDIR@" + +/* Name of package */ +#cmakedefine PACKAGE "@PROJECT_NAME@" + +/* Define to the address where bug reports for this package should be sent. */ +#cmakedefine PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@" + +/* Define to the full name of this package. */ +#cmakedefine PACKAGE_NAME "@PACKAGE_NAME@" + +/* Define to the full name and version of this package. */ +#cmakedefine PACKAGE_STRING "@PACKAGE_STRING@" + +/* Define to the one symbol short name of this package. */ +#cmakedefine PACKAGE_TARNAME "@PACKAGE_TARNAME@" + +/* Define to the home page for this package. */ +#cmakedefine PACKAGE_URL "@PACKAGE_URL@" + +/* Define to the version of this package. */ +#cmakedefine PACKAGE_VERSION "@PACKAGE_VERSION@" + +/* Version number of package */ +#cmakedefine VERSION "@VERSION@" + +/* Set to 1 if GIF library is installed */ +#cmakedefine WEBP_HAVE_GIF 1 + +/* Set to 1 if OpenGL is supported */ +#cmakedefine WEBP_HAVE_GL 1 + +/* Set to 1 if JPEG library is installed */ +#cmakedefine WEBP_HAVE_JPEG 1 + +/* Set to 1 if NEON is supported */ +#cmakedefine WEBP_HAVE_NEON + +/* Set to 1 if runtime detection of NEON is enabled */ +/* TODO: handle properly in CMake */ +#cmakedefine WEBP_HAVE_NEON_RTCD + +/* Set to 1 if PNG library is installed */ +#cmakedefine WEBP_HAVE_PNG 1 + +/* Set to 1 if SDL library is installed */ +#cmakedefine WEBP_HAVE_SDL 1 + +/* Set to 1 if SSE2 is supported */ +#cmakedefine WEBP_HAVE_SSE2 1 + +/* Set to 1 if SSE4.1 is supported */ +#cmakedefine WEBP_HAVE_SSE41 1 + +/* Set to 1 if TIFF library is installed */ +#cmakedefine WEBP_HAVE_TIFF 1 + +/* Enable near lossless encoding */ +#cmakedefine WEBP_NEAR_LOSSLESS 1 + +/* Undefine this to disable thread support. */ +#cmakedefine WEBP_USE_THREAD 1 + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +# undef WORDS_BIGENDIAN +# endif +#endif diff --git a/third-party/webp/libwebp/cmake/cpu.cmake b/third-party/webp/libwebp/cmake/cpu.cmake new file mode 100644 index 0000000000..7513ca8a84 --- /dev/null +++ b/third-party/webp/libwebp/cmake/cpu.cmake @@ -0,0 +1,159 @@ +# Copyright (c) 2021 Google LLC. +# +# Use of this source code is governed by a BSD-style license +# that can be found in the LICENSE file in the root of the source +# tree. An additional intellectual property rights grant can be found +# in the file PATENTS. All contributing project authors may +# be found in the AUTHORS file in the root of the source tree. + +# Check for SIMD extensions. +include(CMakePushCheckState) + +function(webp_check_compiler_flag WEBP_SIMD_FLAG ENABLE_SIMD) + if(NOT ENABLE_SIMD) + message(STATUS "Disabling ${WEBP_SIMD_FLAG} optimization.") + set(WEBP_HAVE_${WEBP_SIMD_FLAG} 0 PARENT_SCOPE) + return() + endif() + unset(WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG} CACHE) + cmake_push_check_state() + set(CMAKE_REQUIRED_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}) + check_c_source_compiles( + " + #include \"${CMAKE_CURRENT_LIST_DIR}/../src/dsp/dsp.h\" + int main(void) { + #if !defined(WEBP_USE_${WEBP_SIMD_FLAG}) + this is not valid code + #endif + return 0; + } + " + WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG}) + cmake_pop_check_state() + if(WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG}) + set(WEBP_HAVE_${WEBP_SIMD_FLAG} 1 PARENT_SCOPE) + else() + set(WEBP_HAVE_${WEBP_SIMD_FLAG} 0 PARENT_SCOPE) + endif() +endfunction() + +# those are included in the names of WEBP_USE_* in c++ code. +set(WEBP_SIMD_FLAGS "SSE41;SSE2;MIPS32;MIPS_DSP_R2;NEON;MSA") +set(WEBP_SIMD_FILE_EXTENSIONS + "_sse41.c;_sse2.c;_mips32.c;_mips_dsp_r2.c;_neon.c;_msa.c") +if(MSVC AND CMAKE_C_COMPILER_ID STREQUAL "MSVC") + # With at least Visual Studio 12 (2013)+ /arch is not necessary to build SSE2 + # or SSE4 code unless a lesser /arch is forced. MSVC does not have a SSE4 + # flag, but an AVX one. Using that with SSE4 code risks generating illegal + # instructions when used on machines with SSE4 only. The flags are left for + # older (untested) versions to avoid any potential compatibility issues. + if(MSVC_VERSION GREATER_EQUAL 1800 AND NOT CMAKE_C_FLAGS MATCHES "/arch:") + set(SIMD_ENABLE_FLAGS) + else() + set(SIMD_ENABLE_FLAGS "/arch:AVX;/arch:SSE2;;;;") + endif() + set(SIMD_DISABLE_FLAGS) +else() + set(SIMD_ENABLE_FLAGS "-msse4.1;-msse2;-mips32;-mdspr2;-mfpu=neon;-mmsa") + set(SIMD_DISABLE_FLAGS "-mno-sse4.1;-mno-sse2;;-mno-dspr2;;-mno-msa") +endif() + +set(WEBP_SIMD_FILES_TO_INCLUDE) +set(WEBP_SIMD_FLAGS_TO_INCLUDE) + +if(${ANDROID}) + if(${ANDROID_ABI} STREQUAL "armeabi-v7a") + # This is because Android studio uses the configuration "-march=armv7-a + # -mfloat-abi=softfp -mfpu=vfpv3-d16" that does not trigger neon + # optimizations but should (as this configuration does not exist anymore). + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon ") + endif() +endif() + +list(LENGTH WEBP_SIMD_FLAGS WEBP_SIMD_FLAGS_LENGTH) +math(EXPR WEBP_SIMD_FLAGS_RANGE "${WEBP_SIMD_FLAGS_LENGTH} - 1") + +foreach(I_SIMD RANGE ${WEBP_SIMD_FLAGS_RANGE}) + # With Emscripten 2.0.9 -msimd128 -mfpu=neon will enable NEON, but the source + # will fail to compile. + if(EMSCRIPTEN AND ${I_SIMD} GREATER_EQUAL 2) + break() + endif() + + list(GET WEBP_SIMD_FLAGS ${I_SIMD} WEBP_SIMD_FLAG) + + # First try with no extra flag added as the compiler might have default flags + # (especially on Android). + unset(WEBP_HAVE_${WEBP_SIMD_FLAG} CACHE) + cmake_push_check_state() + set(CMAKE_REQUIRED_FLAGS) + webp_check_compiler_flag(${WEBP_SIMD_FLAG} ${WEBP_ENABLE_SIMD}) + if(NOT WEBP_HAVE_${WEBP_SIMD_FLAG}) + list(GET SIMD_ENABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG) + if(EMSCRIPTEN) + set(SIMD_COMPILE_FLAG "-msimd128 ${SIMD_COMPILE_FLAG}") + endif() + set(CMAKE_REQUIRED_FLAGS ${SIMD_COMPILE_FLAG}) + webp_check_compiler_flag(${WEBP_SIMD_FLAG} ${WEBP_ENABLE_SIMD}) + else() + if(MSVC AND SIMD_ENABLE_FLAGS) + # The detection for SSE2/SSE4 support under MSVC is based on the compiler + # version so e.g., clang-cl will require flags to enable the assembly. + list(GET SIMD_ENABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG) + else() + set(SIMD_COMPILE_FLAG " ") + endif() + endif() + # Check which files we should include or not. + list(GET WEBP_SIMD_FILE_EXTENSIONS ${I_SIMD} WEBP_SIMD_FILE_EXTENSION) + file(GLOB SIMD_FILES "${CMAKE_CURRENT_LIST_DIR}/../" + "src/dsp/*${WEBP_SIMD_FILE_EXTENSION}") + if(WEBP_HAVE_${WEBP_SIMD_FLAG}) + # Memorize the file and flags. + foreach(FILE ${SIMD_FILES}) + list(APPEND WEBP_SIMD_FILES_TO_INCLUDE ${FILE}) + list(APPEND WEBP_SIMD_FLAGS_TO_INCLUDE ${SIMD_COMPILE_FLAG}) + endforeach() + else() + # Remove the file from the list. + foreach(FILE ${SIMD_FILES}) + list(APPEND WEBP_SIMD_FILES_NOT_TO_INCLUDE ${FILE}) + endforeach() + # Explicitly disable SIMD. + if(SIMD_DISABLE_FLAGS) + list(GET SIMD_DISABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG) + include(CheckCCompilerFlag) + if(SIMD_COMPILE_FLAG) + # Between 3.17.0 and 3.18.2 check_cxx_compiler_flag() sets a normal + # variable at parent scope while check_cxx_source_compiles() continues + # to set an internal cache variable, so we unset both to avoid the + # failure / success state persisting between checks. See + # https://gitlab.kitware.com/cmake/cmake/-/issues/21207. + unset(HAS_COMPILE_FLAG) + unset(HAS_COMPILE_FLAG CACHE) + check_c_compiler_flag(${SIMD_COMPILE_FLAG} HAS_COMPILE_FLAG) + if(HAS_COMPILE_FLAG) + # Do one more check for Clang to circumvent CMake issue 13194. + if(COMMAND check_compiler_flag_common_patterns) + # Only in CMake 3.0 and above. + check_compiler_flag_common_patterns(COMMON_PATTERNS) + else() + set(COMMON_PATTERNS) + endif() + set(CMAKE_REQUIRED_DEFINITIONS ${SIMD_COMPILE_FLAG}) + check_c_source_compiles( + "int main(void) {return 0;}" FLAG_${SIMD_COMPILE_FLAG} FAIL_REGEX + "warning: argument unused during compilation:" ${COMMON_PATTERNS}) + if(NOT FLAG_${SIMD_COMPILE_FLAG}) + unset(HAS_COMPILE_FLAG) + unset(HAS_COMPILE_FLAG CACHE) + endif() + endif() + if(HAS_COMPILE_FLAG) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SIMD_COMPILE_FLAG}") + endif() + endif() + endif() + endif() + cmake_pop_check_state() +endforeach() diff --git a/third-party/webp/libwebp/cmake/deps.cmake b/third-party/webp/libwebp/cmake/deps.cmake new file mode 100644 index 0000000000..0760ba927b --- /dev/null +++ b/third-party/webp/libwebp/cmake/deps.cmake @@ -0,0 +1,172 @@ +# Copyright (c) 2021 Google LLC. +# +# Use of this source code is governed by a BSD-style license +# that can be found in the LICENSE file in the root of the source +# tree. An additional intellectual property rights grant can be found +# in the file PATENTS. All contributing project authors may +# be found in the AUTHORS file in the root of the source tree. + +# Generate the config.h to compile with specific intrinsics / libs. + +# Check for compiler options. +include(CheckCSourceCompiles) +check_c_source_compiles( + " + int main(void) { + (void)__builtin_bswap16(0); + return 0; + } + " + HAVE_BUILTIN_BSWAP16) +check_c_source_compiles( + " + int main(void) { + (void)__builtin_bswap32(0); + return 0; + } + " + HAVE_BUILTIN_BSWAP32) +check_c_source_compiles( + " + int main(void) { + (void)__builtin_bswap64(0); + return 0; + } + " + HAVE_BUILTIN_BSWAP64) + +# Check for libraries. +if(WEBP_USE_THREAD) + find_package(Threads) + if(Threads_FOUND) + # work around cmake bug on QNX (https://cmake.org/Bug/view.php?id=11333) + if(CMAKE_USE_PTHREADS_INIT AND NOT CMAKE_SYSTEM_NAME STREQUAL "QNX") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread") + endif() + list(APPEND WEBP_DEP_LIBRARIES Threads::Threads) + endif() + set(WEBP_USE_THREAD ${Threads_FOUND}) +endif() + +# TODO: this seems unused, check with autotools. +set(LT_OBJDIR ".libs/") + +# Only useful for vwebp, so useless for now. +find_package(OpenGL) +set(WEBP_HAVE_GL ${OPENGL_FOUND}) + +# Check if we need to link to the C math library. We do not look for it as it is +# not found when cross-compiling, while it is here. +check_c_source_compiles( + " + #include + int main(int argc, char** argv) { + return (int)pow(argc, 2.5); + } + " + HAVE_MATH_LIBRARY) +if(NOT HAVE_MATH_LIBRARY) + message(STATUS "Adding -lm flag.") + list(APPEND SHARPYUV_DEP_LIBRARIES m) + list(APPEND WEBP_DEP_LIBRARIES m) +endif() + +# Find the standard image libraries. +set(WEBP_DEP_IMG_LIBRARIES) +set(WEBP_DEP_IMG_INCLUDE_DIRS) +if(WEBP_FIND_IMG_LIBS) + foreach(I_LIB PNG JPEG TIFF) + # Disable tiff when compiling in static mode as it is failing on Ubuntu. + if(WEBP_LINK_STATIC AND ${I_LIB} STREQUAL "TIFF") + message(STATUS "TIFF is disabled when statically linking.") + continue() + endif() + find_package(${I_LIB}) + set(WEBP_HAVE_${I_LIB} ${${I_LIB}_FOUND}) + if(${I_LIB}_FOUND) + list(APPEND WEBP_DEP_IMG_LIBRARIES ${${I_LIB}_LIBRARIES}) + list(APPEND WEBP_DEP_IMG_INCLUDE_DIRS ${${I_LIB}_INCLUDE_DIR} + ${${I_LIB}_INCLUDE_DIRS}) + endif() + endforeach() + if(WEBP_DEP_IMG_INCLUDE_DIRS) + list(REMOVE_DUPLICATES WEBP_DEP_IMG_INCLUDE_DIRS) + endif() + + # GIF detection, gifdec isn't part of the imageio lib. + include(CMakePushCheckState) + set(WEBP_DEP_GIF_LIBRARIES) + set(WEBP_DEP_GIF_INCLUDE_DIRS) + find_package(GIF) + set(WEBP_HAVE_GIF ${GIF_FOUND}) + if(GIF_FOUND) + # GIF find_package only locates the header and library, it doesn't fail + # compile tests when detecting the version, but falls back to 3 (as of at + # least cmake 3.7.2). Make sure the library links to avoid incorrect + # detection when cross compiling. + cmake_push_check_state() + set(CMAKE_REQUIRED_LIBRARIES ${GIF_LIBRARIES}) + set(CMAKE_REQUIRED_INCLUDES ${GIF_INCLUDE_DIR}) + check_c_source_compiles( + " + #include + int main(void) { + (void)DGifOpenFileHandle; + return 0; + } + " + GIF_COMPILES) + cmake_pop_check_state() + if(GIF_COMPILES) + list(APPEND WEBP_DEP_GIF_LIBRARIES ${GIF_LIBRARIES}) + list(APPEND WEBP_DEP_GIF_INCLUDE_DIRS ${GIF_INCLUDE_DIR}) + else() + unset(GIF_FOUND) + endif() + endif() +endif() + +# Check for specific headers. +include(CheckIncludeFiles) +check_include_files(GLUT/glut.h HAVE_GLUT_GLUT_H) +check_include_files(GL/glut.h HAVE_GL_GLUT_H) +check_include_files(OpenGL/glut.h HAVE_OPENGL_GLUT_H) +check_include_files(shlwapi.h HAVE_SHLWAPI_H) +check_include_files(unistd.h HAVE_UNISTD_H) +check_include_files(wincodec.h HAVE_WINCODEC_H) +check_include_files(windows.h HAVE_WINDOWS_H) + +# Windows specifics +if(HAVE_WINCODEC_H) + list(APPEND WEBP_DEP_LIBRARIES shlwapi ole32 windowscodecs) +endif() + +# Check for SIMD extensions. +include(${CMAKE_CURRENT_LIST_DIR}/cpu.cmake) + +# Define extra info. +set(PACKAGE ${PROJECT_NAME}) +set(PACKAGE_NAME ${PROJECT_NAME}) + +# Read from configure.ac. +file(READ ${CMAKE_CURRENT_SOURCE_DIR}/configure.ac CONFIGURE_AC) +string(REGEX MATCHALL "\\[([0-9a-z\\.:/]*)\\]" CONFIGURE_AC_PACKAGE_INFO + ${CONFIGURE_AC}) +function(strip_bracket VAR) + string(LENGTH ${${VAR}} TMP_LEN) + math(EXPR TMP_LEN ${TMP_LEN}-2) + string(SUBSTRING ${${VAR}} 1 ${TMP_LEN} TMP_SUB) + set(${VAR} ${TMP_SUB} PARENT_SCOPE) +endfunction() + +list(GET CONFIGURE_AC_PACKAGE_INFO 1 PACKAGE_VERSION) +strip_bracket(PACKAGE_VERSION) +list(GET CONFIGURE_AC_PACKAGE_INFO 2 PACKAGE_BUGREPORT) +strip_bracket(PACKAGE_BUGREPORT) +list(GET CONFIGURE_AC_PACKAGE_INFO 3 PACKAGE_URL) +strip_bracket(PACKAGE_URL) + +# Build more info. +set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") +set(PACKAGE_TARNAME ${PACKAGE_NAME}) +set(VERSION ${PACKAGE_VERSION}) diff --git a/third-party/webp/libwebp/codereview.settings b/third-party/webp/libwebp/codereview.settings new file mode 100644 index 0000000000..ccba2eeed2 --- /dev/null +++ b/third-party/webp/libwebp/codereview.settings @@ -0,0 +1,4 @@ +# This file is used by git cl to get repository specific information. +GERRIT_HOST: True +CODE_REVIEW_SERVER: chromium-review.googlesource.com +GERRIT_SQUASH_UPLOADS: False diff --git a/third-party/webp/libwebp/configure.ac b/third-party/webp/libwebp/configure.ac new file mode 100644 index 0000000000..2216e4a86f --- /dev/null +++ b/third-party/webp/libwebp/configure.ac @@ -0,0 +1,803 @@ +AC_INIT([libwebp], [1.3.2], + [https://bugs.chromium.org/p/webp],, + [https://developers.google.com/speed/webp]) +AC_CANONICAL_HOST +AC_PREREQ([2.60]) +AM_INIT_AUTOMAKE([-Wall foreign subdir-objects]) + +dnl === automake >= 1.12 requires this for 'unusual archivers' support. +dnl === it must occur before LT_INIT (AC_PROG_LIBTOOL). +m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) + +dnl === AC_PROG_LIBTOOL is deprecated. +m4_ifdef([LT_INIT], [LT_INIT], [AC_PROG_LIBTOOL]) +AC_PROG_SED +AM_PROG_CC_C_O + +dnl === Enable less verbose output when building. +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +dnl == test endianness +AC_C_BIGENDIAN + +dnl === SET_IF_UNSET(shell_var, value) +dnl === Set the shell variable 'shell_var' to 'value' if it is unset. +AC_DEFUN([SET_IF_UNSET], [test "${$1+set}" = "set" || $1=$2]) + +AC_ARG_ENABLE([everything], + AS_HELP_STRING([--enable-everything], + [Enable all optional targets. These can still be + disabled with --disable-target]), + [SET_IF_UNSET([enable_libsharpyuv], [$enableval]) + SET_IF_UNSET([enable_libwebpdecoder], [$enableval]) + SET_IF_UNSET([enable_libwebpdemux], [$enableval]) + SET_IF_UNSET([enable_libwebpextras], [$enableval]) + SET_IF_UNSET([enable_libwebpmux], [$enableval])]) + +dnl === Check whether libwebpmux should be built +AC_MSG_CHECKING(whether libwebpmux is to be built) +AC_ARG_ENABLE([libwebpmux], + AS_HELP_STRING([--disable-libwebpmux], + [Disable libwebpmux @<:@default=no@:>@]), + [], [enable_libwebpmux=yes]) +AC_MSG_RESULT(${enable_libwebpmux-no}) +AM_CONDITIONAL([BUILD_MUX], [test "$enable_libwebpmux" = "yes"]) + +dnl === Check whether libwebpdemux should be built +AC_MSG_CHECKING(whether libwebpdemux is to be built) +AC_ARG_ENABLE([libwebpdemux], + AS_HELP_STRING([--disable-libwebpdemux], + [Disable libwebpdemux @<:@default=no@:>@]), + [], [enable_libwebpdemux=yes]) +AC_MSG_RESULT(${enable_libwebpdemux-no}) +AM_CONDITIONAL([BUILD_DEMUX], [test "$enable_libwebpdemux" = "yes"]) + +dnl === Check whether decoder library should be built. +AC_MSG_CHECKING(whether decoder library is to be built) +AC_ARG_ENABLE([libwebpdecoder], + AS_HELP_STRING([--enable-libwebpdecoder], + [Build libwebpdecoder @<:@default=no@:>@])) +AC_MSG_RESULT(${enable_libwebpdecoder-no}) +AM_CONDITIONAL([BUILD_LIBWEBPDECODER], [test "$enable_libwebpdecoder" = "yes"]) + +dnl === Check whether libwebpextras should be built +AC_MSG_CHECKING(whether libwebpextras is to be built) +AC_ARG_ENABLE([libwebpextras], + AS_HELP_STRING([--enable-libwebpextras], + [Build libwebpextras @<:@default=no@:>@])) +AC_MSG_RESULT(${enable_libwebpextras-no}) +AM_CONDITIONAL([BUILD_EXTRAS], [test "$enable_libwebpextras" = "yes"]) + +dnl === If --enable-asserts is not defined, define NDEBUG + +AC_MSG_CHECKING(whether asserts are enabled) +AC_ARG_ENABLE([asserts], + AS_HELP_STRING([--enable-asserts], + [Enable assert checks])) +if test "x${enable_asserts-no}" = "xno"; then + AM_CPPFLAGS="${AM_CPPFLAGS} -DNDEBUG" +fi +AC_MSG_RESULT(${enable_asserts-no}) +AC_SUBST([AM_CPPFLAGS]) + +AC_ARG_WITH([pkgconfigdir], AS_HELP_STRING([--with-pkgconfigdir=DIR], + [Path to the pkgconfig directory @<:@LIBDIR/pkgconfig@:>@]), + [pkgconfigdir="$withval"], [pkgconfigdir='${libdir}/pkgconfig']) +AC_SUBST([pkgconfigdir]) + +dnl === TEST_AND_ADD_CFLAGS(var, flag) +dnl === Checks whether $CC supports 'flag' and adds it to 'var' +dnl === on success. +AC_DEFUN([TEST_AND_ADD_CFLAGS], + [SAVED_CFLAGS="$CFLAGS" + CFLAGS="-Werror $2" + AC_MSG_CHECKING([whether $CC supports $2]) + dnl Note AC_LANG_PROGRAM([]) uses an old-style main definition. + AC_COMPILE_IFELSE([AC_LANG_SOURCE([int main(void) { return 0; }])], + [AC_MSG_RESULT([yes])] + dnl Simply append the variable avoiding a + dnl compatibility ifdef for AS_VAR_APPEND as this + dnl variable shouldn't grow all that large. + [$1="${$1} $2"], + [AC_MSG_RESULT([no])]) + CFLAGS="$SAVED_CFLAGS"]) +TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-fvisibility=hidden]) +TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wall]) +TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wconstant-conversion]) +TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wdeclaration-after-statement]) +TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wextra]) +TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wfloat-conversion]) +TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wformat -Wformat-nonliteral]) +TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wformat -Wformat-security]) +TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wmissing-declarations]) +TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wmissing-prototypes]) +TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wold-style-definition]) +TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wparentheses-equality]) +TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wshadow]) +TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wshorten-64-to-32]) +TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wundef]) +TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunreachable-code-aggressive]) +TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunreachable-code]) +TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunused-but-set-variable]) +TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunused]) +TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wvla]) +# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62040 +# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61622 +AS_IF([test "$GCC" = "yes" ], [ + gcc_version=`$CC -dumpversion` + gcc_wht_bug="" + case "$host_cpu" in + aarch64|arm64) + case "$gcc_version" in + 4.9|4.9.0|4.9.1) gcc_wht_bug=yes ;; + esac + esac + AS_IF([test "$gcc_wht_bug" = "yes"], [ + TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-frename-registers])])]) +# Use -flax-vector-conversions, if available, when building intrinsics with +# older versions of gcc. The flag appeared in 4.3.x, but if backported, and +# -fno-lax-vector-conversions is set, errors may occur with the intrinsics +# files along with the older system includes, e.g., emmintrin.h. +# Originally observed with cc (GCC) 4.2.1 20070831 patched [FreeBSD] (9.3). +# https://bugs.chromium.org/p/webp/issues/detail?id=274 +AS_IF([test "$GCC" = "yes" ], [ + case "$host_cpu" in + amd64|i?86|x86_64) + AC_COMPILE_IFELSE( + dnl only check for -flax-vector-conversions with older gcc, skip + dnl clang as it reports itself as 4.2.1, but the flag isn't needed. + [AC_LANG_SOURCE([#if !defined(__clang__) && defined(__GNUC__) && \ + ((__GNUC__ << 8) | __GNUC_MINOR__) < 0x403 + #error old gcc + #endif + int main(void) { return 0; } + ])],, + [TEST_AND_ADD_CFLAGS([INTRINSICS_CFLAGS], + [-flax-vector-conversions])]) + ;; + esac]) +AC_SUBST([AM_CFLAGS]) + +dnl === Check for machine specific flags +AC_ARG_ENABLE([sse4.1], + AS_HELP_STRING([--disable-sse4.1], + [Disable detection of SSE4.1 support + @<:@default=auto@:>@])) + +AS_IF([test "x$enable_sse4_1" != "xno" -a "x$enable_sse2" != "xno"], [ + SSE41_FLAGS="$INTRINSICS_CFLAGS $SSE41_FLAGS" + TEST_AND_ADD_CFLAGS([SSE41_FLAGS], [-msse4.1]) + AS_IF([test -n "$SSE41_FLAGS"], [ + SAVED_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS $SSE41_FLAGS" + AC_CHECK_HEADER([smmintrin.h], + [AC_DEFINE(WEBP_HAVE_SSE41, [1], + [Set to 1 if SSE4.1 is supported])], + [SSE41_FLAGS=""]) + CFLAGS=$SAVED_CFLAGS]) + AC_SUBST([SSE41_FLAGS])]) + +AC_ARG_ENABLE([sse2], + AS_HELP_STRING([--disable-sse2], + [Disable detection of SSE2 support + @<:@default=auto@:>@])) + +AS_IF([test "x$enable_sse2" != "xno"], [ + SSE2_FLAGS="$INTRINSICS_CFLAGS $SSE2_FLAGS" + TEST_AND_ADD_CFLAGS([SSE2_FLAGS], [-msse2]) + AS_IF([test -n "$SSE2_FLAGS"], [ + SAVED_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS $SSE2_FLAGS" + AC_CHECK_HEADER([emmintrin.h], + [AC_DEFINE(WEBP_HAVE_SSE2, [1], + [Set to 1 if SSE2 is supported])], + [SSE2_FLAGS=""]) + CFLAGS=$SAVED_CFLAGS]) + AC_SUBST([SSE2_FLAGS])]) + +AC_ARG_ENABLE([neon], + AS_HELP_STRING([--disable-neon], + [Disable detection of NEON support + @<:@default=auto@:>@])) + +AC_ARG_ENABLE([neon_rtcd], + AS_HELP_STRING([--disable-neon-rtcd], + [Disable runtime detection of NEON support via + /proc/cpuinfo on Linux hosts + @<:@default=auto@:>@])) +# For ARM(7) hosts: +# Both NEON flags unset and NEON support detected = build all modules with NEON +# NEON detected with the use of -mfpu=neon = build only NEON modules with NEON +AS_IF([test "x$enable_neon" != "xno"], [ + case "$host_cpu" in + arm|armv7*) + # Test for NEON support without flags before falling back to -mfpu=neon + for flag in '' '-mfpu=neon'; do + LOCAL_NEON_FLAGS="$INTRINSICS_CFLAGS $NEON_FLAGS" + TEST_AND_ADD_CFLAGS([LOCAL_NEON_FLAGS], [$flag]) + SAVED_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS $LOCAL_NEON_FLAGS" + + dnl Note AC_LANG_PROGRAM([]) uses an old-style main definition. + AC_COMPILE_IFELSE([AC_LANG_SOURCE([ + #include + int main(void) { + int8x8_t v = vdup_n_s8(0); + (void)v; + return 0; + }])], + [NEON_FLAGS="$(echo $LOCAL_NEON_FLAGS | $SED 's/^ *//')" + AS_IF([test -n "$NEON_FLAGS"], [ + AS_IF([test "${host_os%%-*}" = "linux" -o \ + "x$enable_neon_rtcd" = "xno"], [ + CFLAGS=$SAVED_CFLAGS + AC_DEFINE(WEBP_HAVE_NEON, [1], [Set to 1 if NEON is supported]) + break + ],[ + AC_MSG_WARN(m4_normalize([NEON runtime cpu-detection is + unavailable for ${host_os%%-*}. Force + with CFLAGS=-mfpu=neon or + --disable-neon-rtcd.])) + enable_neon_rtcd=no + NEON_FLAGS="" + ]) + ],[ + CFLAGS=$SAVED_CFLAGS + AC_DEFINE(WEBP_HAVE_NEON, [1], [Set to 1 if NEON is supported]) + break + ])]) + CFLAGS=$SAVED_CFLAGS + done + + AS_IF([test -n "$NEON_FLAGS"], [ + # If NEON is available and rtcd is disabled apply NEON_FLAGS globally. + AS_IF([test "x$enable_neon_rtcd" = "xno"], [ + AM_CFLAGS="$AM_CFLAGS $NEON_FLAGS" + NEON_FLAGS=""], + [AC_DEFINE(WEBP_HAVE_NEON_RTCD, [1], + [Set to 1 if runtime detection of NEON is enabled])])]) + + case "$host_os" in + *android*) AC_CHECK_HEADERS([cpu-features.h]) ;; + esac + ;; + aarch64*|arm64*) + AC_DEFINE(WEBP_HAVE_NEON, [1], [Set to 1 if NEON is supported]) + ;; + esac + AC_SUBST([NEON_FLAGS])]) + +dnl === CLEAR_LIBVARS([var_pfx]) +dnl === Clears _{INCLUDES,LIBS}. +AC_DEFUN([CLEAR_LIBVARS], [$1_INCLUDES=""; $1_LIBS=""]) + +dnl === WITHLIB_OPTION([opt_pfx], [outvar_pfx]) +dnl === Defines --with-{include,lib}dir options which set +dnl === the variables _{INCLUDES,LIBS}. +AC_DEFUN([WITHLIB_OPTION], + [AC_ARG_WITH([$1includedir], + AS_HELP_STRING([--with-$1includedir=DIR], + [use $2 includes from DIR]), + $2_INCLUDES="-I$withval") + AC_ARG_WITH([$1libdir], + AS_HELP_STRING([--with-$1libdir=DIR], + [use $2 libraries from DIR]), + [$2_LIBS="-L$withval"])]) + +dnl === LIBCHECK_PROLOGUE([var_pfx]) +dnl === Caches the current values of CPPFLAGS/LIBS in SAVED_* then +dnl === prepends the current values with _{INCLUDES,LIBS}. +AC_DEFUN([LIBCHECK_PROLOGUE], + [SAVED_CPPFLAGS=$CPPFLAGS + SAVED_LIBS=$LIBS + CPPFLAGS="$$1_INCLUDES $CPPFLAGS" + LIBS="$$1_LIBS $LIBS"]) + +dnl === LIBCHECK_EPILOGUE([var_pfx]) +dnl === Restores the values of CPPFLAGS/LIBS from SAVED_* and exports +dnl === _{INCLUDES,LIBS} with AC_SUBST. +AC_DEFUN([LIBCHECK_EPILOGUE], + [AC_SUBST($1_LIBS) + AC_SUBST($1_INCLUDES) + CPPFLAGS=$SAVED_CPPFLAGS + LIBS=$SAVED_LIBS]) + +dnl === Check for gcc builtins + +dnl === CHECK_FOR_BUILTIN([builtin], [param], [define]) +dnl === links a C AC_LANG_PROGRAM, with () +dnl === AC_DEFINE'ing if successful. +AC_DEFUN([CHECK_FOR_BUILTIN], + [AC_LANG_PUSH([C]) + AC_MSG_CHECKING([for $1]) + AC_LINK_IFELSE([AC_LANG_PROGRAM([], [(void)$1($2)])], + [AC_MSG_RESULT([yes]) + AC_DEFINE([$3], [1], + [Set to 1 if $1 is available])], + [AC_MSG_RESULT([no])]), + AC_LANG_POP]) + +dnl AC_CHECK_FUNC doesn't work with builtin's. +CHECK_FOR_BUILTIN([__builtin_bswap16], [1u << 15], [HAVE_BUILTIN_BSWAP16]) +CHECK_FOR_BUILTIN([__builtin_bswap32], [1u << 31], [HAVE_BUILTIN_BSWAP32]) +CHECK_FOR_BUILTIN([__builtin_bswap64], [1ull << 63], [HAVE_BUILTIN_BSWAP64]) + +dnl === Check for pthread support +AC_ARG_ENABLE([threading], + AS_HELP_STRING([--disable-threading], + [Disable detection of thread support]),, + [enable_threading=yes]) +if test "$enable_threading" = "yes"; then + AC_MSG_NOTICE([checking for threading support...]) + AX_PTHREAD([AC_DEFINE([WEBP_USE_THREAD], [1], + [Undefine this to disable thread support.]) + LIBS="$PTHREAD_LIBS $LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + CC="$PTHREAD_CC" + ], + [AC_CHECK_FUNC([_beginthreadex], + [AC_DEFINE([WEBP_USE_THREAD], [1], + [Undefine this to disable thread + support.])], + [enable_threading=no])]) +fi +AC_MSG_NOTICE([checking if threading is enabled... ${enable_threading-no}]) + +dnl === check for OpenGL/GLUT support === + +AC_ARG_ENABLE([gl], AS_HELP_STRING([--disable-gl], + [Disable detection of OpenGL support + @<:@default=auto@:>@])) +AS_IF([test "x$enable_gl" != "xno"], [ + CLEAR_LIBVARS([GL]) + WITHLIB_OPTION([gl], [GL]) + + LIBCHECK_PROLOGUE([GL]) + + glut_cflags="none" + glut_ldflags="none" + case $host_os in + darwin*) + # Special case for OSX builds. Append these to give the user a chance to + # override with --with-gl* + glut_cflags="$glut_cflags|-framework GLUT -framework OpenGL" + glut_ldflags="$glut_ldflags|-framework GLUT -framework OpenGL" + # quiet deprecation warnings for glut + TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wno-deprecated-declarations]) + ;; + esac + + GLUT_SAVED_CPPFLAGS="$CPPFLAGS" + SAVED_IFS="$IFS" + IFS="|" + for flag in $glut_cflags; do + # restore IFS immediately as the autoconf macros may need the default. + IFS="$SAVED_IFS" + unset ac_cv_header_GL_glut_h + unset ac_cv_header_OpenGL_glut_h + + case $flag in + none) ;; + *) CPPFLAGS="$flag $CPPFLAGS";; + esac + AC_CHECK_HEADERS([GL/glut.h GLUT/glut.h OpenGL/glut.h], + [glut_headers=yes; + test "$flag" = "none" || GL_INCLUDES="$CPPFLAGS"; + break]) + CPPFLAGS="$GLUT_SAVED_CPPFLAGS" + test "$glut_headers" = "yes" && break + done + IFS="$SAVED_IFS" + + if test "$glut_headers" = "yes"; then + AC_LANG_PUSH([C]) + GLUT_SAVED_LDFLAGS="$LDFLAGS" + SAVED_IFS="$IFS" + IFS="|" + for flag in $glut_ldflags; do + # restore IFS immediately as the autoconf macros may need the default. + IFS="$SAVED_IFS" + unset ac_cv_search_glBegin + + case $flag in + none) ;; + *) LDFLAGS="$flag $LDFLAGS";; + esac + + # find libGL + GL_SAVED_LIBS="$LIBS" + AC_SEARCH_LIBS([glBegin], [GL OpenGL opengl32]) + LIBS="$GL_SAVED_LIBS" + + # A direct link to libGL may not be necessary on e.g., linux. + GLUT_SAVED_LIBS="$LIBS" + for lib in "" "-lglut" "-lglut $ac_cv_search_glBegin"; do + LIBS="$lib" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([ + #ifdef __cplusplus + # define EXTERN_C extern "C" + #else + # define EXTERN_C + #endif + EXTERN_C char glOrtho(); + EXTERN_C char glutMainLoop(); + ],[ + glOrtho(); + glutMainLoop(); + ]) + ], + AC_DEFINE(WEBP_HAVE_GL, [1], + [Set to 1 if OpenGL is supported]) + [glut_support=yes], [] + ) + if test "$glut_support" = "yes"; then + GL_LIBS="$LDFLAGS $lib" + break + fi + done + LIBS="$GLUT_SAVED_LIBS" + LDFLAGS="$GLUT_SAVED_LDFLAGS" + test "$glut_support" = "yes" && break + done + IFS="$SAVED_IFS" + AC_LANG_POP + fi + + LIBCHECK_EPILOGUE([GL]) + + if test "$glut_support" = "yes" -a "$enable_libwebpdemux" = "yes"; then + build_vwebp=yes + else + AC_MSG_NOTICE( + m4_normalize([Not building vwebp. + OpenGL libraries and --enable-libwebpdemux are required.])) + fi +]) +AM_CONDITIONAL([BUILD_VWEBP], [test "$build_vwebp" = "yes"]) + +dnl === check for SDL support === + +AC_ARG_ENABLE([sdl], + AS_HELP_STRING([--disable-sdl], + [Disable detection of SDL support + @<:@default=auto@:>@])) +AS_IF([test "x$enable_sdl" != "xno"], [ + CLEAR_LIBVARS([SDL]) + AC_PATH_PROGS([LIBSDL_CONFIG], [sdl-config]) + if test -n "$LIBSDL_CONFIG"; then + SDL_INCLUDES=`$LIBSDL_CONFIG --cflags` + SDL_LIBS="`$LIBSDL_CONFIG --libs`" + fi + + WITHLIB_OPTION([sdl], [SDL]) + + sdl_header="no" + LIBCHECK_PROLOGUE([SDL]) + AC_CHECK_HEADER([SDL/SDL.h], [sdl_header="SDL/SDL.h"], + [AC_CHECK_HEADER([SDL.h], [sdl_header="SDL.h"], + [AC_MSG_WARN(SDL library not available - no sdl.h)])]) + if test x"$sdl_header" != "xno"; then + AC_LANG_PUSH(C) + SDL_SAVED_LIBS="$LIBS" + for lib in "" "-lSDL" "-lSDLmain -lSDL"; do + LIBS="$SDL_SAVED_LIBS $lib" + # Perform a full link to ensure SDL_main is resolved if needed. + AC_LINK_IFELSE( + [AC_LANG_SOURCE([ + #include <$sdl_header> + int main(int argc, char** argv) { + SDL_Init(0); + return 0; + }])], + [SDL_LIBS="$LDFLAGS $LIBS" + SDL_INCLUDES="$SDL_INCLUDES -DWEBP_HAVE_SDL" + AC_DEFINE(WEBP_HAVE_SDL, [1], + [Set to 1 if SDL library is installed]) + sdl_support=yes] + ) + if test x"$sdl_support" = "xyes"; then + break + fi + done + # LIBS is restored by LIBCHECK_EPILOGUE + AC_LANG_POP + if test x"$sdl_header" = "xSDL.h"; then + SDL_INCLUDES="$SDL_INCLUDES -DWEBP_HAVE_JUST_SDL_H" + fi + fi + LIBCHECK_EPILOGUE([SDL]) + + if test x"$sdl_support" = "xyes"; then + build_vwebp_sdl=yes + else + AC_MSG_NOTICE([Not building vwebp-sdl. SDL library is required.]) + fi +]) + +AM_CONDITIONAL([BUILD_VWEBP_SDL], [test "$build_vwebp_sdl" = "yes"]) + +dnl === check for PNG support === + +AC_ARG_ENABLE([png], AS_HELP_STRING([--disable-png], + [Disable detection of PNG format support + @<:@default=auto@:>@])) +AS_IF([test "x$enable_png" != "xno"], [ + CLEAR_LIBVARS([PNG]) + AC_PATH_PROGS([LIBPNG_CONFIG], + [libpng-config libpng16-config libpng15-config libpng14-config \ + libpng12-config]) + if test -n "$LIBPNG_CONFIG"; then + PNG_INCLUDES=`$LIBPNG_CONFIG --cflags` + PNG_LIBS="`$LIBPNG_CONFIG --ldflags`" + fi + + WITHLIB_OPTION([png], [PNG]) + + LIBCHECK_PROLOGUE([PNG]) + AC_CHECK_HEADER(png.h, + AC_SEARCH_LIBS(png_get_libpng_ver, [png], + [test "$ac_cv_search_png_get_libpng_ver" = "none required" \ + || PNG_LIBS="$PNG_LIBS $ac_cv_search_png_get_libpng_ver" + PNG_INCLUDES="$PNG_INCLUDES -DWEBP_HAVE_PNG" + AC_DEFINE(WEBP_HAVE_PNG, [1], + [Set to 1 if PNG library is installed]) + png_support=yes + ], + [AC_MSG_WARN(Optional png library not found) + PNG_LIBS="" + PNG_INCLUDES="" + ], + [$MATH_LIBS]), + [AC_MSG_WARN(png library not available - no png.h) + PNG_LIBS="" + PNG_INCLUDES="" + ], + ) + LIBCHECK_EPILOGUE([PNG]) +]) + +dnl === check for JPEG support === + +AC_ARG_ENABLE([jpeg], + AS_HELP_STRING([--disable-jpeg], + [Disable detection of JPEG format support + @<:@default=auto@:>@])) +AS_IF([test "x$enable_jpeg" != "xno"], [ + CLEAR_LIBVARS([JPEG]) + WITHLIB_OPTION([jpeg], [JPEG]) + + LIBCHECK_PROLOGUE([JPEG]) + AC_CHECK_HEADER(jpeglib.h, + AC_CHECK_LIB(jpeg, jpeg_set_defaults, + [JPEG_LIBS="$JPEG_LIBS -ljpeg" + JPEG_INCLUDES="$JPEG_INCLUDES -DWEBP_HAVE_JPEG" + AC_DEFINE(WEBP_HAVE_JPEG, [1], + [Set to 1 if JPEG library is installed]) + jpeg_support=yes + ], + AC_MSG_WARN(Optional jpeg library not found), + [$MATH_LIBS]), + AC_MSG_WARN(jpeg library not available - no jpeglib.h) + ) + LIBCHECK_EPILOGUE([JPEG]) +]) + +dnl === check for TIFF support === + +AC_ARG_ENABLE([tiff], + AS_HELP_STRING([--disable-tiff], + [Disable detection of TIFF format support + @<:@default=auto@:>@])) +AS_IF([test "x$enable_tiff" != "xno"], [ + CLEAR_LIBVARS([TIFF]) + WITHLIB_OPTION([tiff], [TIFF]) + + LIBCHECK_PROLOGUE([TIFF]) + AC_CHECK_HEADER(tiffio.h, + AC_CHECK_LIB(tiff, TIFFGetVersion, + [TIFF_LIBS="$TIFF_LIBS -ltiff" + TIFF_INCLUDES="$TIFF_INCLUDES -DWEBP_HAVE_TIFF" + AC_DEFINE(WEBP_HAVE_TIFF, [1], + [Set to 1 if TIFF library is installed]) + tiff_support=yes + ], + AC_MSG_WARN(Optional tiff library not found), + [$MATH_LIBS]), + AC_MSG_WARN(tiff library not available - no tiffio.h) + ) + LIBCHECK_EPILOGUE([TIFF]) +]) + +dnl === check for GIF support === + +AC_ARG_ENABLE([gif], AS_HELP_STRING([--disable-gif], + [Disable detection of GIF format support + @<:@default=auto@:>@])) +AS_IF([test "x$enable_gif" != "xno"], [ + CLEAR_LIBVARS([GIF]) + WITHLIB_OPTION([gif], [GIF]) + + LIBCHECK_PROLOGUE([GIF]) + AC_CHECK_HEADER(gif_lib.h, + AC_CHECK_LIB([gif], [DGifOpenFileHandle], + [GIF_LIBS="$GIF_LIBS -lgif" + AC_DEFINE(WEBP_HAVE_GIF, [1], + [Set to 1 if GIF library is installed]) + gif_support=yes + ], + AC_MSG_WARN(Optional gif library not found), + [$MATH_LIBS]), + AC_MSG_WARN(gif library not available - no gif_lib.h) + ) + LIBCHECK_EPILOGUE([GIF]) + + if test "$gif_support" = "yes" -a \ + "$enable_libwebpdemux" = "yes"; then + build_anim_diff=yes + else + AC_MSG_NOTICE( + [Not building anim_diff. libgif and --enable-libwebpdemux are required.]) + fi + + if test "$gif_support" = "yes" -a \ + "$enable_libwebpmux" = "yes"; then + build_gif2webp=yes + else + AC_MSG_NOTICE( + [Not building gif2webp. libgif and --enable-libwebpmux are required.]) + fi +]) +AM_CONDITIONAL([BUILD_ANIMDIFF], [test "${build_anim_diff}" = "yes"]) +AM_CONDITIONAL([BUILD_GIF2WEBP], [test "${build_gif2webp}" = "yes"]) + +if test "$enable_libwebpdemux" = "yes" -a "$enable_libwebpmux" = "yes"; then + build_img2webp=yes +else + AC_MSG_NOTICE( + m4_normalize([Not building img2webp. + --enable-libwebpdemux & --enable-libwebpmux are required.])) +fi +AM_CONDITIONAL([BUILD_IMG2WEBP], [test "${build_img2webp}" = "yes"]) + +if test "$enable_libwebpmux" = "yes"; then + build_webpinfo=yes +else + AC_MSG_NOTICE([Not building webpinfo. --enable-libwebpdemux is required.]) +fi +AM_CONDITIONAL([BUILD_WEBPINFO], [test "${build_webpinfo}" = "yes"]) + +dnl === check for WIC support === + +AC_ARG_ENABLE([wic], + AS_HELP_STRING([--disable-wic], + [Disable Windows Imaging Component (WIC) detection. + @<:@default=auto@:>@]),, + [enable_wic=yes]) + +case $host_os in +mingw*) +if test "$enable_wic" = "yes"; then + AC_CHECK_HEADERS([wincodec.h shlwapi.h windows.h]) + if test "$ac_cv_header_wincodec_h" = "yes"; then + AC_MSG_CHECKING(for Windows Imaging Component support) + SAVED_LIBS=$LIBS + LIBS="-lshlwapi -lole32 $LIBS" + # match include structure from [cd]webp.c + wic_headers=" + #define INITGUID + #define CINTERFACE + #define COBJMACROS + #define _WIN32_IE 0x500 + + #include + #include + #include + " + # test for functions from each lib and the GUID is created properly + wic_main=" + int main(void) { + CLSID_WICImagingFactory; + CoInitialize(NULL); + SHCreateStreamOnFile(NULL, 0, NULL); + return 0; + } + " + AC_LANG_PUSH(C) + AC_LINK_IFELSE( + [AC_LANG_SOURCE([ + $wic_headers + $wic_main])], + [wic_support=yes], + [wic_support=no] + ) + AC_LANG_POP + + test "$wic_support" = "yes" || LIBS=$SAVED_LIBS + AC_MSG_RESULT(${wic_support-no}) + fi +fi +esac + +dnl === If --enable-swap-16bit-csp is defined, add -DWEBP_SWAP_16BIT_CSP=1 + +USE_SWAP_16BIT_CSP="" +AC_MSG_CHECKING(if --enable-swap-16bit-csp option is specified) +AC_ARG_ENABLE([swap-16bit-csp], + AS_HELP_STRING([--enable-swap-16bit-csp], + [Enable byte swap for 16 bit colorspaces])) +if test "$enable_swap_16bit_csp" = "yes"; then + USE_SWAP_16BIT_CSP="-DWEBP_SWAP_16BIT_CSP=1" +fi +AC_MSG_RESULT(${enable_swap_16bit_csp-no}) +AC_SUBST(USE_SWAP_16BIT_CSP) + +dnl === If --disable-near-lossless is defined, add -DWEBP_NEAR_LOSSLESS=0 + +AC_DEFINE(WEBP_NEAR_LOSSLESS, [1], [Enable near lossless encoding]) +AC_MSG_CHECKING(if --disable-near-lossless option is specified) +AC_ARG_ENABLE([near_lossless], + AS_HELP_STRING([--disable-near-lossless], + [Disable near lossless encoding]), + [], [enable_near_lossless=yes]) +if test "$enable_near_lossless" = "no"; then + AC_DEFINE(WEBP_NEAR_LOSSLESS, [0], [Enable near lossless encoding]) + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +fi + +dnl ========================= + +dnl Add an empty webp_libname_prefix variable for use in *.pc.in. +AC_SUBST([webp_libname_prefix]) +AC_CONFIG_MACRO_DIR([m4]) +AC_CONFIG_HEADERS([src/webp/config.h]) +AC_CONFIG_FILES([Makefile src/Makefile man/Makefile \ + examples/Makefile extras/Makefile imageio/Makefile \ + sharpyuv/Makefile sharpyuv/libsharpyuv.pc \ + src/dec/Makefile src/enc/Makefile src/dsp/Makefile \ + src/demux/Makefile src/mux/Makefile \ + src/utils/Makefile \ + src/libwebp.pc src/libwebpdecoder.pc \ + src/demux/libwebpdemux.pc src/mux/libwebpmux.pc]) + + +AC_OUTPUT + +AC_MSG_NOTICE([ +WebP Configuration Summary +-------------------------- + +Shared libraries: ${enable_shared} +Static libraries: ${enable_static} +Threading support: ${enable_threading-no} +libwebp: yes +libwebpdecoder: ${enable_libwebpdecoder-no} +libwebpdemux: ${enable_libwebpdemux-no} +libwebpmux: ${enable_libwebpmux-no} +libwebpextras: ${enable_libwebpextras-no} + +Tools: +cwebp : ${enable_libwebpdemux-no} + Input format support + ==================== + JPEG : ${jpeg_support-no} + PNG : ${png_support-no} + TIFF : ${tiff_support-no} + WIC : ${wic_support-no} +dwebp : ${enable_libwebpdemux-no} + Output format support + ===================== + PNG : ${png_support-no} + WIC : ${wic_support-no} +GIF support : ${gif_support-no} +anim_diff : ${build_anim_diff-no} +gif2webp : ${build_gif2webp-no} +img2webp : ${build_img2webp-no} +webpmux : ${enable_libwebpmux-no} +vwebp : ${build_vwebp-no} +webpinfo : ${build_webpinfo-no} +SDL support : ${sdl_support-no} +vwebp_sdl : ${build_vwebp_sdl-no} +]) diff --git a/third-party/webp/libwebp/doc/TODO b/third-party/webp/libwebp/doc/TODO new file mode 100644 index 0000000000..b0a9382d85 --- /dev/null +++ b/third-party/webp/libwebp/doc/TODO @@ -0,0 +1,13 @@ +, 20111004 + +* Determine that normative RFC 2119 terms (MUST, SHOULD, MAY, etc.) are + truly intended in all cases where capitalized. + +* Several passages could be made clearer. + + * Overall edit for scope. Portions are phrased as an introduction to + the 0.1.3 RIFF container additions, rather than a holistic guide to + WebP. + + * To wit, suggest s/[spec|specification]/guide/g . "Spec" can imply a + standards track; in any case it's too formal for a work in progress. diff --git a/third-party/webp/libwebp/doc/api.md b/third-party/webp/libwebp/doc/api.md new file mode 100644 index 0000000000..c613ed3421 --- /dev/null +++ b/third-party/webp/libwebp/doc/api.md @@ -0,0 +1,385 @@ +# WebP APIs + +## Encoding API + +The main encoding functions are available in the header src/webp/encode.h + +The ready-to-use ones are: + +```c +size_t WebPEncodeRGB(const uint8_t* rgb, int width, int height, int stride, + float quality_factor, uint8_t** output); +size_t WebPEncodeBGR(const uint8_t* bgr, int width, int height, int stride, + float quality_factor, uint8_t** output); +size_t WebPEncodeRGBA(const uint8_t* rgba, int width, int height, int stride, + float quality_factor, uint8_t** output); +size_t WebPEncodeBGRA(const uint8_t* bgra, int width, int height, int stride, + float quality_factor, uint8_t** output); +``` + +They will convert raw RGB samples to a WebP data. The only control supplied is +the quality factor. + +There are some variants for using the lossless format: + +```c +size_t WebPEncodeLosslessRGB(const uint8_t* rgb, int width, int height, + int stride, uint8_t** output); +size_t WebPEncodeLosslessBGR(const uint8_t* bgr, int width, int height, + int stride, uint8_t** output); +size_t WebPEncodeLosslessRGBA(const uint8_t* rgba, int width, int height, + int stride, uint8_t** output); +size_t WebPEncodeLosslessBGRA(const uint8_t* bgra, int width, int height, + int stride, uint8_t** output); +``` + +Of course in this case, no quality factor is needed since the compression occurs +without loss of the input values, at the expense of larger output sizes. + +### Advanced encoding API + +A more advanced API is based on the WebPConfig and WebPPicture structures. + +WebPConfig contains the encoding settings and is not tied to a particular +picture. WebPPicture contains input data, on which some WebPConfig will be used +for compression. The encoding flow looks like: + +```c +#include + +// Setup a config, starting form a preset and tuning some additional +// parameters +WebPConfig config; +if (!WebPConfigPreset(&config, WEBP_PRESET_PHOTO, quality_factor)) { + return 0; // version error +} +// ... additional tuning +config.sns_strength = 90; +config.filter_sharpness = 6; +config_error = WebPValidateConfig(&config); // not mandatory, but useful + +// Setup the input data +WebPPicture pic; +if (!WebPPictureInit(&pic)) { + return 0; // version error +} +pic.width = width; +pic.height = height; +// allocated picture of dimension width x height +if (!WebPPictureAlloc(&pic)) { + return 0; // memory error +} +// at this point, 'pic' has been initialized as a container, +// and can receive the Y/U/V samples. +// Alternatively, one could use ready-made import functions like +// WebPPictureImportRGB(), which will take care of memory allocation. +// In any case, past this point, one will have to call +// WebPPictureFree(&pic) to reclaim memory. + +// Set up a byte-output write method. WebPMemoryWriter, for instance. +WebPMemoryWriter wrt; +WebPMemoryWriterInit(&wrt); // initialize 'wrt' + +pic.writer = MyFileWriter; +pic.custom_ptr = my_opaque_structure_to_make_MyFileWriter_work; + +// Compress! +int ok = WebPEncode(&config, &pic); // ok = 0 => error occurred! +WebPPictureFree(&pic); // must be called independently of the 'ok' result. + +// output data should have been handled by the writer at that point. +// -> compressed data is the memory buffer described by wrt.mem / wrt.size + +// deallocate the memory used by compressed data +WebPMemoryWriterClear(&wrt); +``` + +## Decoding API + +This is mainly just one function to call: + +```c +#include "webp/decode.h" +uint8_t* WebPDecodeRGB(const uint8_t* data, size_t data_size, + int* width, int* height); +``` + +Please have a look at the file src/webp/decode.h for the details. There are +variants for decoding in BGR/RGBA/ARGB/BGRA order, along with decoding to raw +Y'CbCr samples. One can also decode the image directly into a pre-allocated +buffer. + +To detect a WebP file and gather the picture's dimensions, the function: + +```c +int WebPGetInfo(const uint8_t* data, size_t data_size, + int* width, int* height); +``` + +is supplied. No decoding is involved when using it. + +### Incremental decoding API + +In the case when data is being progressively transmitted, pictures can still be +incrementally decoded using a slightly more complicated API. Decoder state is +stored into an instance of the WebPIDecoder object. This object can be created +with the purpose of decoding either RGB or Y'CbCr samples. For instance: + +```c +WebPDecBuffer buffer; +WebPInitDecBuffer(&buffer); +buffer.colorspace = MODE_BGR; +... +WebPIDecoder* idec = WebPINewDecoder(&buffer); +``` + +As data is made progressively available, this incremental-decoder object can be +used to decode the picture further. There are two (mutually exclusive) ways to +pass freshly arrived data: + +either by appending the fresh bytes: + +```c +WebPIAppend(idec, fresh_data, size_of_fresh_data); +``` + +or by just mentioning the new size of the transmitted data: + +```c +WebPIUpdate(idec, buffer, size_of_transmitted_buffer); +``` + +Note that 'buffer' can be modified between each call to WebPIUpdate, in +particular when the buffer is resized to accommodate larger data. + +These functions will return the decoding status: either VP8_STATUS_SUSPENDED if +decoding is not finished yet or VP8_STATUS_OK when decoding is done. Any other +status is an error condition. + +The 'idec' object must always be released (even upon an error condition) by +calling: WebPDelete(idec). + +To retrieve partially decoded picture samples, one must use the corresponding +method: WebPIDecGetRGB or WebPIDecGetYUVA. It will return the last displayable +pixel row. + +Lastly, note that decoding can also be performed into a pre-allocated pixel +buffer. This buffer must be passed when creating a WebPIDecoder, calling +WebPINewRGB() or WebPINewYUVA(). + +Please have a look at the src/webp/decode.h header for further details. + +### Advanced Decoding API + +WebP decoding supports an advanced API which provides on-the-fly cropping and +rescaling, something of great usefulness on memory-constrained environments like +mobile phones. Basically, the memory usage will scale with the output's size, +not the input's, when one only needs a quick preview or a zoomed in portion of +an otherwise too-large picture. Some CPU can be saved too, incidentally. + +```c +// A) Init a configuration object +WebPDecoderConfig config; +CHECK(WebPInitDecoderConfig(&config)); + +// B) optional: retrieve the bitstream's features. +CHECK(WebPGetFeatures(data, data_size, &config.input) == VP8_STATUS_OK); + +// C) Adjust 'config' options, if needed +config.options.no_fancy_upsampling = 1; +config.options.use_scaling = 1; +config.options.scaled_width = scaledWidth(); +config.options.scaled_height = scaledHeight(); +// etc. + +// D) Specify 'config' output options for specifying output colorspace. +// Optionally the external image decode buffer can also be specified. +config.output.colorspace = MODE_BGRA; +// Optionally, the config.output can be pointed to an external buffer as +// well for decoding the image. This externally supplied memory buffer +// should be big enough to store the decoded picture. +config.output.u.RGBA.rgba = (uint8_t*) memory_buffer; +config.output.u.RGBA.stride = scanline_stride; +config.output.u.RGBA.size = total_size_of_the_memory_buffer; +config.output.is_external_memory = 1; + +// E) Decode the WebP image. There are two variants w.r.t decoding image. +// The first one (E.1) decodes the full image and the second one (E.2) is +// used to incrementally decode the image using small input buffers. +// Any one of these steps can be used to decode the WebP image. + +// E.1) Decode full image. +CHECK(WebPDecode(data, data_size, &config) == VP8_STATUS_OK); + +// E.2) Decode image incrementally. +WebPIDecoder* const idec = WebPIDecode(NULL, NULL, &config); +CHECK(idec != NULL); +while (bytes_remaining > 0) { + VP8StatusCode status = WebPIAppend(idec, input, bytes_read); + if (status == VP8_STATUS_OK || status == VP8_STATUS_SUSPENDED) { + bytes_remaining -= bytes_read; + } else { + break; + } +} +WebPIDelete(idec); + +// F) Decoded image is now in config.output (and config.output.u.RGBA). +// It can be saved, displayed or otherwise processed. + +// G) Reclaim memory allocated in config's object. It's safe to call +// this function even if the memory is external and wasn't allocated +// by WebPDecode(). +WebPFreeDecBuffer(&config.output); +``` + +## WebP Mux + +WebPMux is a set of two libraries 'Mux' and 'Demux' for creation, extraction and +manipulation of an extended format WebP file, which can have features like color +profile, metadata and animation. Reference command-line tools `webpmux` and +`vwebp` as well as the WebP container specification +'doc/webp-container-spec.txt' are also provided in this package, see the +[tools documentation](tools.md). + +### Mux API + +The Mux API contains methods for adding data to and reading data from WebP +files. This API currently supports XMP/EXIF metadata, ICC profile and animation. +Other features may be added in subsequent releases. + +Example#1 (pseudo code): Creating a WebPMux object with image data, color +profile and XMP metadata. + +```c +int copy_data = 0; +WebPMux* mux = WebPMuxNew(); +// ... (Prepare image data). +WebPMuxSetImage(mux, &image, copy_data); +// ... (Prepare ICC profile data). +WebPMuxSetChunk(mux, "ICCP", &icc_profile, copy_data); +// ... (Prepare XMP metadata). +WebPMuxSetChunk(mux, "XMP ", &xmp, copy_data); +// Get data from mux in WebP RIFF format. +WebPMuxAssemble(mux, &output_data); +WebPMuxDelete(mux); +// ... (Consume output_data; e.g. write output_data.bytes to file). +WebPDataClear(&output_data); +``` + +Example#2 (pseudo code): Get image and color profile data from a WebP file. + +```c +int copy_data = 0; +// ... (Read data from file). +WebPMux* mux = WebPMuxCreate(&data, copy_data); +WebPMuxGetFrame(mux, 1, &image); +// ... (Consume image; e.g. call WebPDecode() to decode the data). +WebPMuxGetChunk(mux, "ICCP", &icc_profile); +// ... (Consume icc_profile). +WebPMuxDelete(mux); +free(data); +``` + +For a detailed Mux API reference, please refer to the header file +(src/webp/mux.h). + +### Demux API + +The Demux API enables extraction of images and extended format data from WebP +files. This API currently supports reading of XMP/EXIF metadata, ICC profile and +animated images. Other features may be added in subsequent releases. + +Code example: Demuxing WebP data to extract all the frames, ICC profile and +EXIF/XMP metadata. + +```c +WebPDemuxer* demux = WebPDemux(&webp_data); +uint32_t width = WebPDemuxGetI(demux, WEBP_FF_CANVAS_WIDTH); +uint32_t height = WebPDemuxGetI(demux, WEBP_FF_CANVAS_HEIGHT); +// ... (Get information about the features present in the WebP file). +uint32_t flags = WebPDemuxGetI(demux, WEBP_FF_FORMAT_FLAGS); + +// ... (Iterate over all frames). +WebPIterator iter; +if (WebPDemuxGetFrame(demux, 1, &iter)) { + do { + // ... (Consume 'iter'; e.g. Decode 'iter.fragment' with WebPDecode(), + // ... and get other frame properties like width, height, offsets etc. + // ... see 'struct WebPIterator' below for more info). + } while (WebPDemuxNextFrame(&iter)); + WebPDemuxReleaseIterator(&iter); +} + +// ... (Extract metadata). +WebPChunkIterator chunk_iter; +if (flags & ICCP_FLAG) WebPDemuxGetChunk(demux, "ICCP", 1, &chunk_iter); +// ... (Consume the ICC profile in 'chunk_iter.chunk'). +WebPDemuxReleaseChunkIterator(&chunk_iter); +if (flags & EXIF_FLAG) WebPDemuxGetChunk(demux, "EXIF", 1, &chunk_iter); +// ... (Consume the EXIF metadata in 'chunk_iter.chunk'). +WebPDemuxReleaseChunkIterator(&chunk_iter); +if (flags & XMP_FLAG) WebPDemuxGetChunk(demux, "XMP ", 1, &chunk_iter); +// ... (Consume the XMP metadata in 'chunk_iter.chunk'). +WebPDemuxReleaseChunkIterator(&chunk_iter); +WebPDemuxDelete(demux); +``` + +For a detailed Demux API reference, please refer to the header file +(src/webp/demux.h). + +## AnimEncoder API + +The AnimEncoder API can be used to create animated WebP images. + +Code example: + +```c +WebPAnimEncoderOptions enc_options; +WebPAnimEncoderOptionsInit(&enc_options); +// ... (Tune 'enc_options' as needed). +WebPAnimEncoder* enc = WebPAnimEncoderNew(width, height, &enc_options); +while() { + WebPConfig config; + WebPConfigInit(&config); + // ... (Tune 'config' as needed). + WebPAnimEncoderAdd(enc, frame, duration, &config); +} +WebPAnimEncoderAssemble(enc, webp_data); +WebPAnimEncoderDelete(enc); +// ... (Write the 'webp_data' to a file, or re-mux it further). +``` + +For a detailed AnimEncoder API reference, please refer to the header file +(src/webp/mux.h). + +## AnimDecoder API + +This AnimDecoder API allows decoding (possibly) animated WebP images. + +Code Example: + +```c +WebPAnimDecoderOptions dec_options; +WebPAnimDecoderOptionsInit(&dec_options); +// Tune 'dec_options' as needed. +WebPAnimDecoder* dec = WebPAnimDecoderNew(webp_data, &dec_options); +WebPAnimInfo anim_info; +WebPAnimDecoderGetInfo(dec, &anim_info); +for (uint32_t i = 0; i < anim_info.loop_count; ++i) { + while (WebPAnimDecoderHasMoreFrames(dec)) { + uint8_t* buf; + int timestamp; + WebPAnimDecoderGetNext(dec, &buf, ×tamp); + // ... (Render 'buf' based on 'timestamp'). + // ... (Do NOT free 'buf', as it is owned by 'dec'). + } + WebPAnimDecoderReset(dec); +} +const WebPDemuxer* demuxer = WebPAnimDecoderGetDemuxer(dec); +// ... (Do something using 'demuxer'; e.g. get EXIF/XMP/ICC data). +WebPAnimDecoderDelete(dec); +``` + +For a detailed AnimDecoder API reference, please refer to the header file +(src/webp/demux.h). diff --git a/third-party/webp/libwebp/doc/building.md b/third-party/webp/libwebp/doc/building.md new file mode 100644 index 0000000000..5efeab9acc --- /dev/null +++ b/third-party/webp/libwebp/doc/building.md @@ -0,0 +1,213 @@ +# Building + +## Windows build + +By running: + +```batch +nmake /f Makefile.vc CFG=release-static RTLIBCFG=static OBJDIR=output +``` + +the directory `output\release-static\(x64|x86)\bin` will contain the tools +cwebp.exe and dwebp.exe. The directory `output\release-static\(x64|x86)\lib` +will contain the libwebp static library. The target architecture (x86/x64) is +detected by Makefile.vc from the Visual Studio compiler (cl.exe) available in +the system path. + +## Unix build using makefile.unix + +On platforms with GNU tools installed (gcc and make), running + +```shell +make -f makefile.unix +``` + +will build the binaries examples/cwebp and examples/dwebp, along with the static +library src/libwebp.a. No system-wide installation is supplied, as this is a +simple alternative to the full installation system based on the autoconf tools +(see below). Please refer to makefile.unix for additional details and +customizations. + +## Using autoconf tools + +Prerequisites: a compiler (e.g., gcc), make, autoconf, automake, libtool. + +On a Debian-like system the following should install everything you need for a +minimal build: + +```shell +$ sudo apt-get install gcc make autoconf automake libtool +``` + +When building from git sources, you will need to run autogen.sh to generate the +configure script. + +```shell +./configure +make +make install +``` + +should be all you need to have the following files + +``` +/usr/local/include/webp/decode.h +/usr/local/include/webp/encode.h +/usr/local/include/webp/types.h +/usr/local/lib/libwebp.* +/usr/local/bin/cwebp +/usr/local/bin/dwebp +``` + +installed. + +Note: A decode-only library, libwebpdecoder, is available using the +`--enable-libwebpdecoder` flag. The encode library is built separately and can +be installed independently using a minor modification in the corresponding +Makefile.am configure files (see comments there). See `./configure --help` for +more options. + +## Building for MIPS Linux + +MIPS Linux toolchain stable available releases can be found at: +https://community.imgtec.com/developers/mips/tools/codescape-mips-sdk/available-releases/ + +```shell +# Add toolchain to PATH +export PATH=$PATH:/path/to/toolchain/bin + +# 32-bit build for mips32r5 (p5600) +HOST=mips-mti-linux-gnu +MIPS_CFLAGS="-O3 -mips32r5 -mabi=32 -mtune=p5600 -mmsa -mfp64 \ + -msched-weight -mload-store-pairs -fPIE" +MIPS_LDFLAGS="-mips32r5 -mabi=32 -mmsa -mfp64 -pie" + +# 64-bit build for mips64r6 (i6400) +HOST=mips-img-linux-gnu +MIPS_CFLAGS="-O3 -mips64r6 -mabi=64 -mtune=i6400 -mmsa -mfp64 \ + -msched-weight -mload-store-pairs -fPIE" +MIPS_LDFLAGS="-mips64r6 -mabi=64 -mmsa -mfp64 -pie" + +./configure --host=${HOST} --build=`config.guess` \ + CC="${HOST}-gcc -EL" \ + CFLAGS="$MIPS_CFLAGS" \ + LDFLAGS="$MIPS_LDFLAGS" +make +make install +``` + +## CMake + +With CMake, you can compile libwebp, cwebp, dwebp, gif2webp, img2webp, webpinfo +and the JS bindings. + +Prerequisites: a compiler (e.g., gcc with autotools) and CMake. + +On a Debian-like system the following should install everything you need for a +minimal build: + +```shell +$ sudo apt-get install build-essential cmake +``` + +When building from git sources, you will need to run cmake to generate the +makefiles. + +```shell +mkdir build && cd build && cmake ../ +make +make install +``` + +If you also want any of the executables, you will need to enable them through +CMake, e.g.: + +```shell +cmake -DWEBP_BUILD_CWEBP=ON -DWEBP_BUILD_DWEBP=ON ../ +``` + +or through your favorite interface (like ccmake or cmake-qt-gui). + +Use option `-DWEBP_UNICODE=ON` for Unicode support on Windows (with chcp 65001). + +Finally, once installed, you can also use WebP in your CMake project by doing: + +```cmake +find_package(WebP) +``` + +which will define the CMake variables WebP_INCLUDE_DIRS and WebP_LIBRARIES. + +## Gradle + +The support for Gradle is minimal: it only helps you compile libwebp, cwebp and +dwebp and webpmux_example. + +Prerequisites: a compiler (e.g., gcc with autotools) and gradle. + +On a Debian-like system the following should install everything you need for a +minimal build: + +```shell +$ sudo apt-get install build-essential gradle +``` + +When building from git sources, you will need to run the Gradle wrapper with the +appropriate target, e.g. : + +```shell +./gradlew buildAllExecutables +``` + +## SWIG bindings + +To generate language bindings from swig/libwebp.swig at least swig-1.3 +(http://www.swig.org) is required. + +Currently the following functions are mapped: + +Decode: + +``` +WebPGetDecoderVersion +WebPGetInfo +WebPDecodeRGBA +WebPDecodeARGB +WebPDecodeBGRA +WebPDecodeBGR +WebPDecodeRGB +``` + +Encode: + +``` +WebPGetEncoderVersion +WebPEncodeRGBA +WebPEncodeBGRA +WebPEncodeRGB +WebPEncodeBGR +WebPEncodeLosslessRGBA +WebPEncodeLosslessBGRA +WebPEncodeLosslessRGB +WebPEncodeLosslessBGR +``` + +See also the [swig documentation](../swig/README.md) for more detailed build +instructions and usage examples. + +### Java bindings + +To build the swig-generated JNI wrapper code at least JDK-1.5 (or equivalent) is +necessary for enum support. The output is intended to be a shared object / DLL +that can be loaded via `System.loadLibrary("webp_jni")`. + +### Python bindings + +To build the swig-generated Python extension code at least Python 2.6 is +required. Python < 2.6 may build with some minor changes to libwebp.swig or the +generated code, but is untested. + +## Javascript decoder + +Libwebp can be compiled into a JavaScript decoder using Emscripten and CMake. +See the [corresponding documentation](../README.md) diff --git a/third-party/webp/libwebp/doc/specs_generation.md b/third-party/webp/libwebp/doc/specs_generation.md new file mode 100644 index 0000000000..0380d6646e --- /dev/null +++ b/third-party/webp/libwebp/doc/specs_generation.md @@ -0,0 +1,26 @@ +# Generate libwebp Container Spec Docs from Text Source + +HTML generation requires [kramdown](https://kramdown.gettalong.org/), easily +installed as a [rubygem](https://rubygems.org/). Rubygems installation should +satisfy dependencies automatically. + +HTML generation can then be done from the project root: + +```shell +$ kramdown doc/webp-container-spec.txt --template doc/template.html > \ + doc/output/webp-container-spec.html +``` + +kramdown can optionally syntax highlight code blocks, using +[CodeRay](https://github.com/rubychan/coderay), a dependency of kramdown that +rubygems will install automatically. The following will apply inline CSS +styling; an external stylesheet is not needed. + +```shell +$ kramdown doc/webp-lossless-bitstream-spec.txt --template \ + doc/template.html --coderay-css style --coderay-line-numbers ' ' \ + --coderay-default-lang c > \ + doc/output/webp-lossless-bitstream-spec.html +``` + +Optimally, use kramdown 0.13.7 or newer if syntax highlighting desired. diff --git a/third-party/webp/libwebp/doc/template.html b/third-party/webp/libwebp/doc/template.html new file mode 100644 index 0000000000..5dbc2894ab --- /dev/null +++ b/third-party/webp/libwebp/doc/template.html @@ -0,0 +1,94 @@ + + + + + WebP Container Specification + + + + +<%= @body %> + + diff --git a/third-party/webp/libwebp/doc/tools.md b/third-party/webp/libwebp/doc/tools.md new file mode 100644 index 0000000000..bf492746fe --- /dev/null +++ b/third-party/webp/libwebp/doc/tools.md @@ -0,0 +1,516 @@ +# WebP tools + +## Encoding tool + +The examples/ directory contains tools for encoding (cwebp) and decoding (dwebp) +images. + +The easiest use should look like: + +```shell +cwebp input.png -q 80 -o output.webp +``` + +which will convert the input file to a WebP file using a quality factor of 80 on +a 0->100 scale (0 being the lowest quality, 100 being the best. Default value is +75). + +You might want to try the `-lossless` flag too, which will compress the source +(in RGBA format) without any loss. The `-q` quality parameter will in this case +control the amount of processing time spent trying to make the output file as +small as possible. + +A longer list of options is available using the `-longhelp` command line flag: + +```shell +> cwebp -longhelp +Usage: + cwebp [-preset <...>] [options] in_file [-o out_file] +``` + +If input size (-s) for an image is not specified, it is assumed to be a PNG, +JPEG, TIFF or WebP file. Note: Animated PNG and WebP files are not supported. + +Options: + +``` +-h / -help ............. short help +-H / -longhelp ......... long help +-q ............. quality factor (0:small..100:big), default=75 +-alpha_q ......... transparency-compression quality (0..100), + default=100 +-preset ....... preset setting, one of: + default, photo, picture, + drawing, icon, text + -preset must come first, as it overwrites other parameters +-z ............... activates lossless preset with given + level in [0:fast, ..., 9:slowest] + +-m ............... compression method (0=fast, 6=slowest), default=4 +-segments ........ number of segments to use (1..4), default=4 +-size ............ target size (in bytes) +-psnr .......... target PSNR (in dB. typically: 42) + +-s ......... input size (width x height) for YUV +-sns ............. spatial noise shaping (0:off, 100:max), default=50 +-f ............... filter strength (0=off..100), default=60 +-sharpness ....... filter sharpness (0:most .. 7:least sharp), default=0 +-strong ................ use strong filter instead of simple (default) +-nostrong .............. use simple filter instead of strong +-sharp_yuv ............. use sharper (and slower) RGB->YUV conversion +-partition_limit . limit quality to fit the 512k limit on + the first partition (0=no degradation ... 100=full) +-pass ............ analysis pass number (1..10) +-qrange .... specifies the permissible quality range + (default: 0 100) +-crop .. crop picture with the given rectangle +-resize ........ resize picture (*after* any cropping) +-mt .................... use multi-threading if available +-low_memory ............ reduce memory usage (slower encoding) +-map ............. print map of extra info +-print_psnr ............ prints averaged PSNR distortion +-print_ssim ............ prints averaged SSIM distortion +-print_lsim ............ prints local-similarity distortion +-d .......... dump the compressed output (PGM file) +-alpha_method .... transparency-compression method (0..1), default=1 +-alpha_filter . predictive filtering for alpha plane, + one of: none, fast (default) or best +-exact ................. preserve RGB values in transparent area, default=off +-blend_alpha ..... blend colors against background color + expressed as RGB values written in + hexadecimal, e.g. 0xc0e0d0 for red=0xc0 + green=0xe0 and blue=0xd0 +-noalpha ............... discard any transparency information +-lossless .............. encode image losslessly, default=off +-near_lossless ... use near-lossless image preprocessing + (0..100=off), default=100 +-hint ......... specify image characteristics hint, + one of: photo, picture or graph + +-metadata ..... comma separated list of metadata to + copy from the input to the output if present. + Valid values: all, none (default), exif, icc, xmp + +-short ................. condense printed message +-quiet ................. don't print anything +-version ............... print version number and exit +-noasm ................. disable all assembly optimizations +-v ..................... verbose, e.g. print encoding/decoding times +-progress .............. report encoding progress +``` + +Experimental Options: + +``` +-jpeg_like ............. roughly match expected JPEG size +-af .................... auto-adjust filter strength +-pre ............. pre-processing filter +``` + +The main options you might want to try in order to further tune the visual +quality are: + +-preset -sns -f -m + +Namely: + +* `preset` will set up a default encoding configuration targeting a particular + type of input. It should appear first in the list of options, so that + subsequent options can take effect on top of this preset. Default value is + 'default'. +* `sns` will progressively turn on (when going from 0 to 100) some additional + visual optimizations (like: segmentation map re-enforcement). This option + will balance the bit allocation differently. It tries to take bits from the + "easy" parts of the picture and use them in the "difficult" ones instead. + Usually, raising the sns value (at fixed -q value) leads to larger files, + but with better quality. Typical value is around '75'. +* `f` option directly links to the filtering strength used by the codec's + in-loop processing. The higher the value, the smoother the highly-compressed + area will look. This is particularly useful when aiming at very small files. + Typical values are around 20-30. Note that using the option + -strong/-nostrong will change the type of filtering. Use "-f 0" to turn + filtering off. +* `m` controls the trade-off between encoding speed and quality. Default is 4. + You can try -m 5 or -m 6 to explore more (time-consuming) encoding + possibilities. A lower value will result in faster encoding at the expense + of quality. + +## Decoding tool + +There is a decoding sample in examples/dwebp.c which will take a .webp file and +decode it to a PNG image file (amongst other formats). This is simply to +demonstrate the use of the API. You can verify the file test.webp decodes to +exactly the same as test_ref.ppm by using: + +```shell +cd examples +./dwebp test.webp -ppm -o test.ppm +diff test.ppm test_ref.ppm +``` + +The full list of options is available using -h: + +```shell +> dwebp -h +Usage: dwebp in_file [options] [-o out_file] +``` + +Decodes the WebP image file to PNG format [Default]. Note: Animated WebP files +are not supported. + +Use following options to convert into alternate image formats: + +``` +-pam ......... save the raw RGBA samples as a color PAM +-ppm ......... save the raw RGB samples as a color PPM +-bmp ......... save as uncompressed BMP format +-tiff ........ save as uncompressed TIFF format +-pgm ......... save the raw YUV samples as a grayscale PGM + file with IMC4 layout +-yuv ......... save the raw YUV samples in flat layout +``` + +Other options are: + +``` +-version ..... print version number and exit +-nofancy ..... don't use the fancy YUV420 upscaler +-nofilter .... disable in-loop filtering +-nodither .... disable dithering +-dither .. dithering strength (in 0..100) +-alpha_dither use alpha-plane dithering if needed +-mt .......... use multi-threading +-crop ... crop output with the given rectangle +-resize ......... resize output (*after* any cropping) +-flip ........ flip the output vertically +-alpha ....... only save the alpha plane +-incremental . use incremental decoding (useful for tests) +-h ........... this help message +-v ........... verbose (e.g. print encoding/decoding times) +-quiet ....... quiet mode, don't print anything +-noasm ....... disable all assembly optimizations +``` + +## WebP file analysis tool + +`webpinfo` can be used to print out the chunk level structure and bitstream +header information of WebP files. It can also check if the files are of valid +WebP format. + +Usage: + +```shell +webpinfo [options] in_files +``` + +Note: there could be multiple input files; options must come before input files. + +Options: + +``` +-version ........... Print version number and exit. +-quiet ............. Do not show chunk parsing information. +-diag .............. Show parsing error diagnosis. +-summary ........... Show chunk stats summary. +-bitstream_info .... Parse bitstream header. +``` + +## Visualization tool + +There's a little self-serve visualization tool called 'vwebp' under the +examples/ directory. It uses OpenGL to open a simple drawing window and show a +decoded WebP file. It's not yet integrated in the automake build system, but you +can try to manually compile it using the recommendations below. + +Usage: + +```shell +vwebp in_file [options] +``` + +Decodes the WebP image file and visualize it using OpenGL + +Options are: + +``` +-version ..... print version number and exit +-noicc ....... don't use the icc profile if present +-nofancy ..... don't use the fancy YUV420 upscaler +-nofilter .... disable in-loop filtering +-dither dithering strength (0..100), default=50 +-noalphadither disable alpha plane dithering +-usebgcolor .. display background color +-mt .......... use multi-threading +-info ........ print info +-h ........... this help message +``` + +Keyboard shortcuts: + +``` +'c' ................ toggle use of color profile +'b' ................ toggle background color display +'i' ................ overlay file information +'d' ................ disable blending & disposal (debug) +'q' / 'Q' / ESC .... quit +``` + +### Building + +Prerequisites: + +1. OpenGL & OpenGL Utility Toolkit (GLUT) + + Linux: `sudo apt-get install freeglut3-dev mesa-common-dev` + + Mac + Xcode: These libraries should be available in the OpenGL / GLUT + frameworks. + + Windows: http://freeglut.sourceforge.net/index.php#download + +2. (Optional) qcms (Quick Color Management System) + + 1. Download qcms from Mozilla / Chromium: + https://hg.mozilla.org/mozilla-central/file/0e7639e3bdfb/gfx/qcms + https://source.chromium.org/chromium/chromium/src/+/main:third_party/qcms/;drc=d4a2f8e1ed461d8fc05ed88d1ae2dc94c9773825 + 2. Build and archive the source files as libqcms.a / qcms.lib + 3. Update makefile.unix / Makefile.vc + 1. Define WEBP_HAVE_QCMS + 2. Update include / library paths to reference the qcms directory. + +Build using makefile.unix / Makefile.vc: + +```shell +$ make -f makefile.unix examples/vwebp +> nmake /f Makefile.vc CFG=release-static \ + ../obj/x64/release-static/bin/vwebp.exe +``` + +## Animation creation tool + +The utility `img2webp` can turn a sequence of input images (PNG, JPEG, ...) into +an animated WebP file. It offers fine control over duration, encoding modes, +etc. + +Usage: + +```shell +img2webp [file_options] [[frame_options] frame_file]... [-o webp_file] +``` + +File-level options (only used at the start of compression): + +``` +-min_size ............ minimize size +-kmax .......... maximum number of frame between key-frames + (0=only keyframes) +-kmin .......... minimum number of frame between key-frames + (0=disable key-frames altogether) +-mixed ............... use mixed lossy/lossless automatic mode +-near_lossless . use near-lossless image preprocessing + (0..100=off), default=100 +-sharp_yuv ........... use sharper (and slower) RGB->YUV conversion + (lossy only) +-loop .......... loop count (default: 0, = infinite loop) +-v ................... verbose mode +-h ................... this help +-version ............. print version number and exit +``` + +Per-frame options (only used for subsequent images input): + +``` +-d ............. frame duration in ms (default: 100) +-lossless ........... use lossless mode (default) +-lossy ... ........... use lossy mode +-q ........... quality +-m ............. method to use +``` + +example: `img2webp -loop 2 in0.png -lossy in1.jpg -d 80 in2.tiff -o out.webp` + +Note: if a single file name is passed as the argument, the arguments will be +tokenized from this file. The file name must not start with the character '-'. + +## Animated GIF conversion + +Animated GIF files can be converted to WebP files with animation using the +gif2webp utility available under examples/. The files can then be viewed using +vwebp. + +Usage: + +```shell +gif2webp [options] gif_file -o webp_file +``` + +Options: + +``` +-h / -help ............. this help +-lossy ................. encode image using lossy compression +-mixed ................. for each frame in the image, pick lossy + or lossless compression heuristically +-q ............. quality factor (0:small..100:big) +-m ............... compression method (0=fast, 6=slowest) +-min_size .............. minimize output size (default:off) + lossless compression by default; can be + combined with -q, -m, -lossy or -mixed + options +-kmin ............ min distance between key frames +-kmax ............ max distance between key frames +-f ............... filter strength (0=off..100) +-metadata ..... comma separated list of metadata to + copy from the input to the output if present + Valid values: all, none, icc, xmp (default) +-loop_compatibility .... use compatibility mode for Chrome + version prior to M62 (inclusive) +-mt .................... use multi-threading if available + +-version ............... print version number and exit +-v ..................... verbose +-quiet ................. don't print anything +``` + +### Building + +With the libgif development files installed, gif2webp can be built using +makefile.unix: + +```shell +$ make -f makefile.unix examples/gif2webp +``` + +or using autoconf: + +```shell +$ ./configure --enable-everything +$ make +``` + +## Comparison of animated images + +Test utility anim_diff under examples/ can be used to compare two animated +images (each can be GIF or WebP). + +Usage: + +```shell +anim_diff [options] +``` + +Options: + +``` +-dump_frames dump decoded frames in PAM format +-min_psnr ... minimum per-frame PSNR +-raw_comparison ..... if this flag is not used, RGB is + premultiplied before comparison +-max_diff ..... maximum allowed difference per channel + between corresponding pixels in subsequent + frames +-h .................. this help +-version ............ print version number and exit +``` + +### Building + +With the libgif development files installed, anim_diff can be built using +makefile.unix: + +```shell +$ make -f makefile.unix examples/anim_diff +``` + +or using autoconf: + +```shell +$ ./configure --enable-everything +$ make +``` + +## WebP Mux tool + +The examples/ directory contains a tool (webpmux) for manipulating WebP files. +The webpmux tool can be used to create an extended format WebP file and also to +extract or strip relevant data from such a file. + +A list of options is available using the -help command line flag: + +```shell +> webpmux -help +Usage: webpmux -get GET_OPTIONS INPUT -o OUTPUT + webpmux -set SET_OPTIONS INPUT -o OUTPUT + webpmux -duration DURATION_OPTIONS [-duration ...] + INPUT -o OUTPUT + webpmux -strip STRIP_OPTIONS INPUT -o OUTPUT + webpmux -frame FRAME_OPTIONS [-frame...] [-loop LOOP_COUNT] + [-bgcolor BACKGROUND_COLOR] -o OUTPUT + webpmux -info INPUT + webpmux [-h|-help] + webpmux -version + webpmux argument_file_name + +GET_OPTIONS: + Extract relevant data: + icc get ICC profile + exif get EXIF metadata + xmp get XMP metadata + frame n get nth frame + +SET_OPTIONS: + Set color profile/metadata/parameters: + loop LOOP_COUNT set the loop count + bgcolor BACKGROUND_COLOR set the animation background color + icc file.icc set ICC profile + exif file.exif set EXIF metadata + xmp file.xmp set XMP metadata + where: 'file.icc' contains the ICC profile to be set, + 'file.exif' contains the EXIF metadata to be set + 'file.xmp' contains the XMP metadata to be set + +DURATION_OPTIONS: + Set duration of selected frames: + duration set duration for all frames + duration,frame set duration of a particular frame + duration,start,end set duration of frames in the + interval [start,end]) + where: 'duration' is the duration in milliseconds + 'start' is the start frame index + 'end' is the inclusive end frame index + The special 'end' value '0' means: last frame. + +STRIP_OPTIONS: + Strip color profile/metadata: + icc strip ICC profile + exif strip EXIF metadata + xmp strip XMP metadata + +FRAME_OPTIONS(i): + Create animation: + file_i +di[+xi+yi[+mi[bi]]] + where: 'file_i' is the i'th animation frame (WebP format), + 'di' is the pause duration before next frame, + 'xi','yi' specify the image offset for this frame, + 'mi' is the dispose method for this frame (0 or 1), + 'bi' is the blending method for this frame (+b or -b) + +LOOP_COUNT: + Number of times to repeat the animation. + Valid range is 0 to 65535 [Default: 0 (infinite)]. + +BACKGROUND_COLOR: + Background color of the canvas. + A,R,G,B + where: 'A', 'R', 'G' and 'B' are integers in the range 0 to 255 specifying + the Alpha, Red, Green and Blue component values respectively + [Default: 255,255,255,255] + +INPUT & OUTPUT are in WebP format. + +Note: The nature of EXIF, XMP and ICC data is not checked and is assumed to be +valid. + +Note: if a single file name is passed as the argument, the arguments will be +tokenized from this file. The file name must not start with the character '-'. +``` diff --git a/third-party/webp/libwebp/doc/webp-container-spec.txt b/third-party/webp/libwebp/doc/webp-container-spec.txt new file mode 100644 index 0000000000..f61555d65d --- /dev/null +++ b/third-party/webp/libwebp/doc/webp-container-spec.txt @@ -0,0 +1,870 @@ + + + +WebP Container Specification +============================ + +* TOC placeholder +{:toc} + + +Introduction +------------ + +WebP is an image format that uses either (i) the VP8 key frame encoding to +compress image data in a lossy way or (ii) the WebP lossless encoding. These +encoding schemes should make it more efficient than older formats, such as JPEG, +GIF, and PNG. It is optimized for fast image transfer over the network (for +example, for websites). The WebP format has feature parity (color profile, +metadata, animation, etc.) with other formats as well. This document describes +the structure of a WebP file. + +The WebP container (that is, the RIFF container for WebP) allows feature support +over and above the basic use case of WebP (that is, a file containing a single +image encoded as a VP8 key frame). The WebP container provides additional +support for the following: + + * Lossless Compression: An image can be losslessly compressed, using the + WebP Lossless Format. + + * Metadata: An image may have metadata stored in Exchangeable Image File + Format (Exif) or Extensible Metadata Platform (XMP) format. + + * Transparency: An image may have transparency, that is, an alpha channel. + + * Color Profile: An image may have an embedded ICC profile as described + by the [International Color Consortium][iccspec]. + + * Animation: An image may have multiple frames with pauses between them, + making it an animation. + +Terminology & Basics +-------------------- + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", +"SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this +document are to be interpreted as described in BCP 14 [RFC 2119][] [RFC 8174][] +when, and only when, they appear in all capitals, as shown here. + +A WebP file contains either a still image (that is, an encoded matrix of pixels) +or an [animation](#animation). Optionally, it can also contain transparency +information, a color profile and metadata. We refer to the matrix of pixels as +the _canvas_ of the image. + +Bit numbering in chunk diagrams starts at `0` for the most significant bit +('MSB 0'), as described in [RFC 1166][]. + +Below are additional terms used throughout this document: + +_Reader/Writer_ + +: Code that reads WebP files is referred to as a _reader_, while code that + writes them is referred to as a _writer_. + +_uint16_ + +: A 16-bit, little-endian, unsigned integer. + +_uint24_ + +: A 24-bit, little-endian, unsigned integer. + +_uint32_ + +: A 32-bit, little-endian, unsigned integer. + +_FourCC_ + +: A four-character code (FourCC) is a _uint32_ created by concatenating four + ASCII characters in little-endian order. This means 'aaaa' (0x61616161) and + 'AAAA' (0x41414141) are treated as different _FourCCs_. + +_1-based_ + +: An unsigned integer field storing values offset by `-1`, for example, such a + field would store value _25_ as _24_. + +_ChunkHeader('ABCD')_ + +: Used to describe the _FourCC_ and _Chunk Size_ header of individual chunks, + where 'ABCD' is the FourCC for the chunk. This element's size is 8 bytes. + + +RIFF File Format +---------------- + +The WebP file format is based on the RIFF (Resource Interchange File Format) +document format. + +The basic element of a RIFF file is a _chunk_. It consists of: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Chunk FourCC | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Chunk Size | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + : Chunk Payload : + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +Chunk FourCC: 32 bits + +: ASCII four-character code used for chunk identification. + +Chunk Size: 32 bits (_uint32_) + +: The size of the chunk in bytes, not including this field, the chunk + identifier, or padding. + +Chunk Payload: _Chunk Size_ bytes + +: The data payload. If _Chunk Size_ is odd, a single padding byte -- which MUST + be `0` to conform with RIFF -- is added. + +**Note:** RIFF has a convention that all-uppercase chunk FourCCs are standard +chunks that apply to any RIFF file format, while FourCCs specific to a file +format are all lowercase. WebP does not follow this convention. + + +WebP File Header +---------------- + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | 'R' | 'I' | 'F' | 'F' | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | File Size | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | 'W' | 'E' | 'B' | 'P' | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +'RIFF': 32 bits + +: The ASCII characters 'R', 'I', 'F', 'F'. + +File Size: 32 bits (_uint32_) + +: The size of the file in bytes, starting at offset 8. The maximum value of + this field is 2^32 minus 10 bytes and thus the size of the whole file is at + most 4 GiB minus 2 bytes. + +'WEBP': 32 bits + +: The ASCII characters 'W', 'E', 'B', 'P'. + +A WebP file MUST begin with a RIFF header with the FourCC 'WEBP'. The file size +in the header is the total size of the chunks that follow plus `4` bytes for +the 'WEBP' FourCC. The file SHOULD NOT contain any data after the data +specified by _File Size_. Readers MAY parse such files, ignoring the trailing +data. As the size of any chunk is even, the size given by the RIFF header is +also even. The contents of individual chunks are described in the following +sections. + + +Simple File Format (Lossy) +-------------------------- + +This layout SHOULD be used if the image requires _lossy_ encoding and does not +require transparency or other advanced features provided by the extended format. +Files with this layout are smaller and supported by older software. + +Simple WebP (lossy) file format: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + | WebP file header (12 bytes) | + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + : 'VP8 ' Chunk : + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +'VP8 ' Chunk: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | ChunkHeader('VP8 ') | + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + : VP8 data : + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +VP8 data: _Chunk Size_ bytes + +: VP8 bitstream data. + +Note that the fourth character in the 'VP8 ' FourCC is an ASCII space (0x20). + +The VP8 bitstream format specification is described in [VP8 Data Format and +Decoding Guide][rfc 6386]. Note that the VP8 frame header contains the VP8 frame +width and height. That is assumed to be the width and height of the canvas. + +The VP8 specification describes how to decode the image into Y'CbCr format. To +convert to RGB, [Recommendation BT.601][rec601] SHOULD be used. Applications MAY +use another conversion method, but visual results may differ among decoders. + + +Simple File Format (Lossless) +----------------------------- + +**Note:** Older readers may not support files using the lossless format. + +This layout SHOULD be used if the image requires _lossless_ encoding (with an +optional transparency channel) and does not require advanced features provided +by the extended format. + +Simple WebP (lossless) file format: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + | WebP file header (12 bytes) | + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + : 'VP8L' Chunk : + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +'VP8L' Chunk: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | ChunkHeader('VP8L') | + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + : VP8L data : + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +VP8L data: _Chunk Size_ bytes + +: VP8L bitstream data. + +The current specification of the VP8L bitstream can be found at +[WebP Lossless Bitstream Format][webpllspec]. Note that the VP8L header +contains the VP8L image width and height. That is assumed to be the width +and height of the canvas. + + +Extended File Format +-------------------- + +**Note:** Older readers may not support files using the extended format. + +An extended format file consists of: + + * A 'VP8X' Chunk with information about features used in the file. + + * An optional 'ICCP' Chunk with a color profile. + + * An optional 'ANIM' Chunk with animation control data. + + * Image data. + + * An optional 'EXIF' Chunk with Exif metadata. + + * An optional 'XMP ' Chunk with XMP metadata. + + * An optional list of [unknown chunks](#unknown-chunks). + +For a _still image_, the _image data_ consists of a single frame, which is made +up of: + + * An optional [alpha subchunk](#alpha). + + * A [bitstream subchunk](#bitstream-vp8vp8l). + +For an _animated image_, the _image data_ consists of multiple frames. More +details about frames can be found in the [Animation](#animation) section. + +All chunks SHOULD be placed in the same order as listed above. If a chunk +appears in the wrong place, the file is invalid, but readers MAY parse the +file, ignoring the chunks that are out of order. + +**Rationale:** Setting the order of chunks should allow quicker file +parsing. For example, if an 'ALPH' Chunk does not appear in its required +position, a decoder can choose to stop searching for it. The rule of +ignoring late chunks should make programs that need to do a full search +give the same results as the ones stopping early. + +Extended WebP file header: +{:#extended_header} + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + | WebP file header (12 bytes) | + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | ChunkHeader('VP8X') | + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |Rsv|I|L|E|X|A|R| Reserved | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Canvas Width Minus One | ... + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ... Canvas Height Minus One | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +Reserved (Rsv): 2 bits + +: MUST be `0`. Readers MUST ignore this field. + +ICC profile (I): 1 bit + +: Set if the file contains an 'ICCP' Chunk. + +Alpha (L): 1 bit + +: Set if any of the frames of the image contain transparency information + ("alpha"). + +Exif metadata (E): 1 bit + +: Set if the file contains Exif metadata. + +XMP metadata (X): 1 bit + +: Set if the file contains XMP metadata. + +Animation (A): 1 bit + +: Set if this is an animated image. Data in 'ANIM' and 'ANMF' Chunks should be + used to control the animation. + +Reserved (R): 1 bit + +: MUST be `0`. Readers MUST ignore this field. + +Reserved: 24 bits + +: MUST be `0`. Readers MUST ignore this field. + +Canvas Width Minus One: 24 bits + +: _1-based_ width of the canvas in pixels. + The actual canvas width is `1 + Canvas Width Minus One`. + +Canvas Height Minus One: 24 bits + +: _1-based_ height of the canvas in pixels. + The actual canvas height is `1 + Canvas Height Minus One`. + +The product of _Canvas Width_ and _Canvas Height_ MUST be at most `2^32 - 1`. + +Future specifications may add more fields. Unknown fields MUST be ignored. + +### Chunks + +#### Animation + +An animation is controlled by 'ANIM' and 'ANMF' Chunks. + +'ANIM' Chunk: +{:#anim_chunk} + +For an animated image, this chunk contains the _global parameters_ of the +animation. + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | ChunkHeader('ANIM') | + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Background Color | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Loop Count | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +Background Color: 32 bits (_uint32_) + +: The default background color of the canvas in \[Blue, Green, Red, Alpha\] + byte order. This color MAY be used to fill the unused space on the canvas + around the frames, as well as the transparent pixels of the first frame. + The background color is also used when the Disposal method is `1`. + +**Note**: + + * The background color MAY contain a non-opaque alpha value, even if the + _Alpha_ flag in the ['VP8X' Chunk](#extended_header) is unset. + + * Viewer applications SHOULD treat the background color value as a hint and + are not required to use it. + + * The canvas is cleared at the start of each loop. The background color MAY be + used to achieve this. + +Loop Count: 16 bits (_uint16_) + +: The number of times to loop the animation. If it is `0`, this means + infinitely. + +This chunk MUST appear if the _Animation_ flag in the 'VP8X' Chunk is set. +If the _Animation_ flag is not set and this chunk is present, it MUST be +ignored. + +'ANMF' Chunk: + +For animated images, this chunk contains information about a _single_ frame. +If the _Animation flag_ is not set, then this chunk SHOULD NOT be present. + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | ChunkHeader('ANMF') | + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Frame X | ... + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ... Frame Y | Frame Width Minus One ... + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ... | Frame Height Minus One | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Frame Duration | Reserved |B|D| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + : Frame Data : + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +Frame X: 24 bits (_uint24_) + +: The X coordinate of the upper left corner of the frame is `Frame X * 2`. + +Frame Y: 24 bits (_uint24_) + +: The Y coordinate of the upper left corner of the frame is `Frame Y * 2`. + +Frame Width Minus One: 24 bits (_uint24_) + +: The _1-based_ width of the frame. + The frame width is `1 + Frame Width Minus One`. + +Frame Height Minus One: 24 bits (_uint24_) + +: The _1-based_ height of the frame. + The frame height is `1 + Frame Height Minus One`. + +Frame Duration: 24 bits (_uint24_) + +: The time to wait before displaying the next frame, in 1-millisecond units. + Note that the interpretation of the Frame Duration of 0 (and often <= 10) is + defined by the implementation. Many tools and browsers assign a minimum + duration similar to GIF. + +Reserved: 6 bits + +: MUST be `0`. Readers MUST ignore this field. + +Blending method (B): 1 bit + +: Indicates how transparent pixels of _the current frame_ are to be blended + with corresponding pixels of the previous canvas: + + * `0`: Use alpha-blending. After disposing of the previous frame, render the + current frame on the canvas using [alpha-blending](#alpha-blending). If + the current frame does not have an alpha channel, assume the alpha value + is 255, effectively replacing the rectangle. + + * `1`: Do not blend. After disposing of the previous frame, render the + current frame on the canvas by overwriting the rectangle covered by the + current frame. + +Disposal method (D): 1 bit + +: Indicates how _the current frame_ is to be treated after it has been + displayed (before rendering the next frame) on the canvas: + + * `0`: Do not dispose. Leave the canvas as is. + + * `1`: Dispose to the background color. Fill the _rectangle_ on the canvas + covered by the _current frame_ with the background color specified in the + ['ANIM' Chunk](#anim_chunk). + +**Notes**: + + * The frame disposal only applies to the _frame rectangle_, that is, the + rectangle defined by _Frame X_, _Frame Y_, _frame width_, and _frame + height_. It may or may not cover the whole canvas. + +{:#alpha-blending} + * Alpha-blending: + + Given that each of the R, G, B, and A channels is 8 bits, and the RGB + channels are _not premultiplied_ by alpha, the formula for blending + 'dst' onto 'src' is: + +~~~~~ + blend.A = src.A + dst.A * (1 - src.A / 255) + if blend.A = 0 then + blend.RGB = 0 + else + blend.RGB = + (src.RGB * src.A + + dst.RGB * dst.A * (1 - src.A / 255)) / blend.A +~~~~~ + + * Alpha-blending SHOULD be done in linear color space, by taking into account + the [color profile](#color-profile) of the image. If the color profile is + not present, standard RGB (sRGB) is to be assumed. (Note that sRGB also + needs to be linearized due to a gamma of ~2.2.) + +Frame Data: _Chunk Size_ - `16` bytes + +: Consists of: + + * An optional [alpha subchunk](#alpha) for the frame. + + * A [bitstream subchunk](#bitstream-vp8vp8l) for the frame. + + * An optional list of [unknown chunks](#unknown-chunks). + +**Note**: The 'ANMF' payload, _Frame Data_ above, consists of individual +_padded_ chunks, as described by the [RIFF file format](#riff-file-format). + +#### Alpha + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | ChunkHeader('ALPH') | + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |Rsv| P | F | C | Alpha Bitstream... | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +Reserved (Rsv): 2 bits + +: MUST be `0`. Readers MUST ignore this field. + +Preprocessing (P): 2 bits + +: These _informative_ bits are used to signal the preprocessing that has + been performed during compression. The decoder can use this information to + for example, dither the values or smooth the gradients prior to display. + + * `0`: No preprocessing. + * `1`: Level reduction. + +Decoders are not required to use this information in any specified way. + +Filtering method (F): 2 bits + +: The filtering methods used are described as follows: + + * `0`: None. + * `1`: Horizontal filter. + * `2`: Vertical filter. + * `3`: Gradient filter. + +For each pixel, filtering is performed using the following calculations. +Assume the alpha values surrounding the current `X` position are labeled as: + + C | B | + ---+---+ + A | X | + +We seek to compute the alpha value at position `X`. First, a prediction is +made depending on the filtering method: + + * Method `0`: predictor = 0 + * Method `1`: predictor = A + * Method `2`: predictor = B + * Method `3`: predictor = clip(A + B - C) + +where `clip(v)` is equal to: + + * 0 if v < 0, + * 255 if v > 255, or + * v otherwise + +The final value is derived by adding the decompressed value `X` to the +predictor and using modulo-256 arithmetic to wrap the \[256..511\] range +into the \[0..255\] one: + +`alpha = (predictor + X) % 256` + +There are special cases for the left-most and top-most pixel positions. For +example, the top-left value at location (0, 0) uses 0 as the predictor value. +Otherwise: + + * For horizontal or gradient filtering methods, the left-most pixels at + location (0, y) are predicted using the location (0, y-1) just above. + * For vertical or gradient filtering methods, the top-most pixels at + location (x, 0) are predicted using the location (x-1, 0) on the left. + +Compression method (C): 2 bits + +: The compression method used: + + * `0`: No compression. + * `1`: Compressed using the WebP lossless format. + +Alpha bitstream: _Chunk Size_ - `1` bytes + +: Encoded alpha bitstream. + +This optional chunk contains encoded alpha data for this frame. A frame +containing a 'VP8L' Chunk SHOULD NOT contain this chunk. + +**Rationale**: The transparency information is already part of the 'VP8L' +Chunk. + +The alpha channel data is stored as uncompressed raw data (when the +compression method is '0') or compressed using the lossless format +(when the compression method is '1'). + + * Raw data: This consists of a byte sequence of length = width * height, + containing all the 8-bit transparency values in scan order. + + * Lossless format compression: The byte sequence is a compressed + image-stream (as described in ["WebP Lossless Bitstream Format"] + [webpllspec]) of implicit dimensions width x height. That is, this + image-stream does NOT contain any headers describing the image dimensions. + + **Rationale**: The dimensions are already known from other sources, + so storing them again would be redundant and prone to error. + + Once the image-stream is decoded into Alpha, Red, Green, Blue (ARGB) color + values, following the process described in the lossless format + specification, the transparency information must be extracted from the + *green* channel of the ARGB quadruplet. + + **Rationale**: The green channel is allowed extra transformation + steps in the specification -- unlike the other channels -- that can + improve compression. + +#### Bitstream (VP8/VP8L) + +This chunk contains compressed bitstream data for a single frame. + +A bitstream chunk may be either (i) a 'VP8 ' Chunk, using 'VP8 ' (note the +significant fourth-character space) as its FourCC, _or_ (ii) a 'VP8L' Chunk, +using 'VP8L' as its FourCC. + +The formats of 'VP8 ' and 'VP8L' Chunks are as described in sections +[Simple File Format (Lossy)](#simple-file-format-lossy) +and [Simple File Format (Lossless)](#simple-file-format-lossless), respectively. + +#### Color Profile + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | ChunkHeader('ICCP') | + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + : Color Profile : + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +Color Profile: _Chunk Size_ bytes + +: ICC profile. + +This chunk MUST appear before the image data. + +There SHOULD be at most one such chunk. If there are more such chunks, readers +MAY ignore all except the first one. +See the [ICC Specification][iccspec] for details. + +If this chunk is not present, sRGB SHOULD be assumed. + +#### Metadata + +Metadata can be stored in 'EXIF' or 'XMP ' Chunks. + +There SHOULD be at most one chunk of each type ('EXIF' and 'XMP '). If there +are more such chunks, readers MAY ignore all except the first one. + +The chunks are defined as follows: + +'EXIF' Chunk: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | ChunkHeader('EXIF') | + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + : Exif Metadata : + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +Exif Metadata: _Chunk Size_ bytes + +: Image metadata in Exif format. + +'XMP ' Chunk: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | ChunkHeader('XMP ') | + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + : XMP Metadata : + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +XMP Metadata: _Chunk Size_ bytes + +: Image metadata in XMP format. + +Note that the fourth character in the 'XMP ' FourCC is an ASCII space (0x20). + +Additional guidance about handling metadata can be found in the +Metadata Working Group's ["Guidelines for Handling Metadata"][metadata]. + +#### Unknown Chunks + +A RIFF chunk (described in the [RIFF File Format](#riff-file-format) section) +whose FourCC is different from any of the chunks described in this document, is +considered an _unknown chunk_. + +**Rationale**: Allowing unknown chunks gives a provision for future extension +of the format and also allows storage of any application-specific data. + +A file MAY contain unknown chunks: + + * at the end of the file, as described in [Extended WebP file + header](#extended_header) section, or + * at the end of 'ANMF' Chunks, as described in the + [Animation](#animation) section. + +Readers SHOULD ignore these chunks. Writers SHOULD preserve them in their +original order (unless they specifically intend to modify these chunks). + +### Canvas Assembly from Frames + +Here we provide an overview of how a reader MUST assemble a canvas in the case +of an animated image. + +The process begins with creating a canvas using the dimensions given in the +'VP8X' Chunk, `Canvas Width Minus One + 1` pixels wide by `Canvas Height Minus +One + 1` pixels high. The `Loop Count` field from the 'ANIM' Chunk controls how +many times the animation process is repeated. This is `Loop Count - 1` for +nonzero `Loop Count` values or infinite if the `Loop Count` is zero. + +At the beginning of each loop iteration, the canvas is filled using the +background color from the 'ANIM' Chunk or an application-defined color. + +'ANMF' Chunks contain individual frames given in display order. Before rendering +each frame, the previous frame's `Disposal method` is applied. + +The rendering of the decoded frame begins at the Cartesian coordinates (`2 * +Frame X`, `2 * Frame Y`), using the top-left corner of the canvas as the origin. +`Frame Width Minus One + 1` pixels wide by `Frame Height Minus One + 1` pixels +high are rendered onto the canvas using the `Blending method`. + +The canvas is displayed for `Frame Duration` milliseconds. This continues until +all frames given by 'ANMF' Chunks have been displayed. A new loop iteration is +then begun, or the canvas is left in its final state if all iterations have been +completed. + +The following pseudocode illustrates the rendering process. The notation +_VP8X.field_ means the field in the 'VP8X' Chunk with the same description. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +assert VP8X.flags.hasAnimation +canvas ↠new image of size VP8X.canvasWidth x VP8X.canvasHeight with + background color ANIM.background_color. +loop_count ↠ANIM.loopCount +dispose_method ↠Dispose to background color +if loop_count == 0: + loop_count = ∞ +frame_params ↠nil +assert next chunk in image_data is ANMF +for loop = 0..loop_count - 1 + clear canvas to ANIM.background_color or application-defined color + until eof or non-ANMF chunk + frame_params.frameX = Frame X + frame_params.frameY = Frame Y + frame_params.frameWidth = Frame Width Minus One + 1 + frame_params.frameHeight = Frame Height Minus One + 1 + frame_params.frameDuration = Frame Duration + frame_right = frame_params.frameX + frame_params.frameWidth + frame_bottom = frame_params.frameY + frame_params.frameHeight + assert VP8X.canvasWidth >= frame_right + assert VP8X.canvasHeight >= frame_bottom + for subchunk in 'Frame Data': + if subchunk.tag == "ALPH": + assert alpha subchunks not found in 'Frame Data' earlier + frame_params.alpha = alpha_data + else if subchunk.tag == "VP8 " OR subchunk.tag == "VP8L": + assert bitstream subchunks not found in 'Frame Data' earlier + frame_params.bitstream = bitstream_data + render frame with frame_params.alpha and frame_params.bitstream + on canvas with top-left corner at (frame_params.frameX, + frame_params.frameY), using Blending method + frame_params.blendingMethod. + canvas contains the decoded image. + Show the contents of the canvas for + frame_params.frameDuration * 1 ms. + dispose_method = frame_params.disposeMethod +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +Example File Layouts +-------------------- + +A lossy-encoded image with alpha may look as follows: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +RIFF/WEBP ++- VP8X (descriptions of features used) ++- ALPH (alpha bitstream) ++- VP8 (bitstream) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A lossless-encoded image may look as follows: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +RIFF/WEBP ++- VP8X (descriptions of features used) ++- VP8L (lossless bitstream) ++- XYZW (unknown chunk) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A lossless image with an ICC profile and XMP metadata may +look as follows: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +RIFF/WEBP ++- VP8X (descriptions of features used) ++- ICCP (color profile) ++- VP8L (lossless bitstream) ++- XMP (metadata) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +An animated image with Exif metadata may look as follows: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +RIFF/WEBP ++- VP8X (descriptions of features used) ++- ANIM (global animation parameters) ++- ANMF (frame1 parameters + data) ++- ANMF (frame2 parameters + data) ++- ANMF (frame3 parameters + data) ++- ANMF (frame4 parameters + data) ++- EXIF (metadata) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +[webpllspec]: https://chromium.googlesource.com/webm/libwebp/+/HEAD/doc/webp-lossless-bitstream-spec.txt +[iccspec]: https://www.color.org/icc_specs2.xalter +[metadata]: https://web.archive.org/web/20180919181934/http://www.metadataworkinggroup.org/pdf/mwg_guidance.pdf +[rec601]: https://www.itu.int/rec/R-REC-BT.601 +[rfc 1166]: https://datatracker.ietf.org/doc/html/rfc1166 +[rfc 2119]: https://datatracker.ietf.org/doc/html/rfc2119 +[rfc 6386]: https://datatracker.ietf.org/doc/html/rfc6386 +[rfc 8174]: https://datatracker.ietf.org/doc/html/rfc8174 diff --git a/third-party/webp/libwebp/doc/webp-lossless-bitstream-spec.txt b/third-party/webp/libwebp/doc/webp-lossless-bitstream-spec.txt new file mode 100644 index 0000000000..e732887d98 --- /dev/null +++ b/third-party/webp/libwebp/doc/webp-lossless-bitstream-spec.txt @@ -0,0 +1,1156 @@ + + +Specification for WebP Lossless Bitstream +========================================= + +_Jyrki Alakuijala, Ph.D., Google, Inc., 2023-03-09_ + +Abstract +-------- + +WebP lossless is an image format for lossless compression of ARGB images. The +lossless format stores and restores the pixel values exactly, including the +color values for pixels whose alpha value is 0. The format uses subresolution +images, recursively embedded into the format itself, for storing statistical +data about the images, such as the used entropy codes, spatial predictors, color +space conversion, and color table. A universal algorithm for sequential data +compression (LZ77), prefix coding, and a color cache are used for compression of +the bulk data. Decoding speeds faster than PNG have been demonstrated, as well +as 25% denser compression than can be achieved using today's PNG format. + + +* TOC placeholder +{:toc} + +1 Introduction +-------------- + +This document describes the compressed data representation of a WebP lossless +image. It is intended as a detailed reference for the WebP lossless encoder and +decoder implementation. + +In this document, we extensively use C programming language syntax to describe +the bitstream and assume the existence of a function for reading bits, +`ReadBits(n)`. The bytes are read in the natural order of the stream containing +them, and bits of each byte are read in least-significant-bit-first order. When +multiple bits are read at the same time, the integer is constructed from the +original data in the original order. The most significant bits of the returned +integer are also the most significant bits of the original data. Thus, the +statement + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +b = ReadBits(2); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +is equivalent with the two statements below: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +b = ReadBits(1); +b |= ReadBits(1) << 1; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +We assume that each color component, that is, alpha, red, blue, and green, is +represented using an 8-bit byte. We define the corresponding type as uint8. A +whole ARGB pixel is represented by a type called uint32, which is an unsigned +integer consisting of 32 bits. In the code showing the behavior of the +transforms, these values are codified in the following bits: alpha in bits +31..24, red in bits 23..16, green in bits 15..8, and blue in bits 7..0; however, +implementations of the format are free to use another representation internally. + +Broadly, a WebP lossless image contains header data, transform information, and +actual image data. Headers contain the width and height of the image. A WebP +lossless image can go through four different types of transforms before being +entropy encoded. The transform information in the bitstream contains the data +required to apply the respective inverse transforms. + +2 Nomenclature +-------------- + +ARGB +: A pixel value consisting of alpha, red, green, and blue values. + +ARGB image +: A two-dimensional array containing ARGB pixels. + +color cache +: A small hash-addressed array to store recently used colors to be able to + recall them with shorter codes. + +color indexing image +: A one-dimensional image of colors that can be indexed using a small integer + (up to 256 within WebP lossless). + +color transform image +: A two-dimensional subresolution image containing data about correlations of + color components. + +distance mapping +: Changes LZ77 distances to have the smallest values for pixels in + two-dimensional proximity. + +entropy image +: A two-dimensional subresolution image indicating which entropy coding should + be used in a respective square in the image, that is, each pixel is a meta + prefix code. + +LZ77 +: A dictionary-based sliding window compression algorithm that either emits + symbols or describes them as sequences of past symbols. + +meta prefix code +: A small integer (up to 16 bits) that indexes an element in the meta prefix + table. + +predictor image +: A two-dimensional subresolution image indicating which spatial predictor is + used for a particular square in the image. + +prefix code +: A classic way to do entropy coding where a smaller number of bits are used + for more frequent codes. + +prefix coding +: A way to entropy code larger integers, which codes a few bits of the integer + using an entropy code and codifies the remaining bits raw. This allows for + the descriptions of the entropy codes to remain relatively small even when + the range of symbols is large. + +scan-line order +: A processing order of pixels (left to right and top to bottom), starting + from the left-hand-top pixel. Once a row is completed, continue from the + left-hand column of the next row. + +3 RIFF Header +------------- + +The beginning of the header has the RIFF container. This consists of the +following 21 bytes: + + 1. String 'RIFF'. + 2. A little-endian, 32-bit value of the chunk length, which is the whole size + of the chunk controlled by the RIFF header. Normally, this equals + the payload size (file size minus 8 bytes: 4 bytes for the 'RIFF' + identifier and 4 bytes for storing the value itself). + 3. String 'WEBP' (RIFF container name). + 4. String 'VP8L' (FourCC for lossless-encoded image data). + 5. A little-endian, 32-bit value of the number of bytes in the + lossless stream. + 6. 1-byte signature 0x2f. + +The first 28 bits of the bitstream specify the width and height of the image. +Width and height are decoded as 14-bit integers as follows: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +int image_width = ReadBits(14) + 1; +int image_height = ReadBits(14) + 1; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The 14-bit precision for image width and height limits the maximum size of a +WebP lossless image to 16384✕16384 pixels. + +The alpha_is_used bit is a hint only, and should not impact decoding. It should +be set to 0 when all alpha values are 255 in the picture, and 1 otherwise. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +int alpha_is_used = ReadBits(1); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The version_number is a 3 bit code that must be set to 0. Any other value should +be treated as an error. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +int version_number = ReadBits(3); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +4 Transforms +------------ + +The transforms are reversible manipulations of the image data that can reduce +the remaining symbolic entropy by modeling spatial and color correlations. They +can make the final compression more dense. + +An image can go through four types of transforms. A 1 bit indicates the +presence of a transform. Each transform is allowed to be used only once. The +transforms are used only for the main-level ARGB image; the subresolution images +(color transform image, entropy image, and predictor image) have no transforms, +not even the 0 bit indicating the end of transforms. + +Typically, an encoder would use these transforms to reduce the Shannon entropy +in the residual image. Also, the transform data can be decided based on entropy +minimization. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +while (ReadBits(1)) { // Transform present. + // Decode transform type. + enum TransformType transform_type = ReadBits(2); + // Decode transform data. + ... +} + +// Decode actual image data (Section 5). +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If a transform is present, then the next two bits specify the transform type. +There are four types of transforms. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +enum TransformType { + PREDICTOR_TRANSFORM = 0, + COLOR_TRANSFORM = 1, + SUBTRACT_GREEN_TRANSFORM = 2, + COLOR_INDEXING_TRANSFORM = 3, +}; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The transform type is followed by the transform data. Transform data contains +the information required to apply the inverse transform and depends on the +transform type. The inverse transforms are applied in the reverse order that +they are read from the bitstream, that is, last one first. + +Next, we describe the transform data for different types. + +### 4.1 Predictor Transform + +The predictor transform can be used to reduce entropy by exploiting the fact +that neighboring pixels are often correlated. In the predictor transform, the +current pixel value is predicted from the pixels already decoded (in scan-line +order) and only the residual value (actual - predicted) is encoded. The green +component of a pixel defines which of the 14 predictors is used within a +particular block of the ARGB image. The _prediction mode_ determines the type of +prediction to use. We divide the image into squares, and all the pixels in a +square use the same prediction mode. + +The first 3 bits of prediction data define the block width and height in number +of bits. The number of block columns, `block_xsize`, is used in two-dimension +indexing. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +int size_bits = ReadBits(3) + 2; +int block_width = (1 << size_bits); +int block_height = (1 << size_bits); +#define DIV_ROUND_UP(num, den) (((num) + (den) - 1) / (den)) +int block_xsize = DIV_ROUND_UP(image_width, 1 << size_bits); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The transform data contains the prediction mode for each block of the image. It +is a subresolution image where the green component of a pixel defines which of +the 14 predictors is used for all the `block_width * block_height` pixels within +a particular block of the ARGB image. This subresolution image is encoded using +the same techniques described in [Chapter 5](#image-data). + +For a pixel (x, y), one can compute the respective filter block address by: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +int block_index = (y >> size_bits) * block_xsize + + (x >> size_bits); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +There are 14 different prediction modes. In each prediction mode, the current +pixel value is predicted from one or more neighboring pixels whose values are +already known. + +We chose the neighboring pixels (TL, T, TR, and L) of the current pixel (P) as +follows: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +O O O O O O O O O O O +O O O O O O O O O O O +O O O O TL T TR O O O O +O O O O L P X X X X X +X X X X X X X X X X X +X X X X X X X X X X X +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +where TL means top-left, T means top, TR means top-right, and L means left. At +the time of predicting a value for P, all O, TL, T, TR and L pixels have already +been processed, and the P pixel and all X pixels are unknown. + +Given the preceding neighboring pixels, the different prediction modes are +defined as follows. + +| Mode | Predicted value of each channel of the current pixel | +| ------ | ------------------------------------------------------- | +| 0 | 0xff000000 (represents solid black color in ARGB) | +| 1 | L | +| 2 | T | +| 3 | TR | +| 4 | TL | +| 5 | Average2(Average2(L, TR), T) | +| 6 | Average2(L, TL) | +| 7 | Average2(L, T) | +| 8 | Average2(TL, T) | +| 9 | Average2(T, TR) | +| 10 | Average2(Average2(L, TL), Average2(T, TR)) | +| 11 | Select(L, T, TL) | +| 12 | ClampAddSubtractFull(L, T, TL) | +| 13 | ClampAddSubtractHalf(Average2(L, T), TL) | + + +`Average2` is defined as follows for each ARGB component: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +uint8 Average2(uint8 a, uint8 b) { + return (a + b) / 2; +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The Select predictor is defined as follows: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +uint32 Select(uint32 L, uint32 T, uint32 TL) { + // L = left pixel, T = top pixel, TL = top-left pixel. + + // ARGB component estimates for prediction. + int pAlpha = ALPHA(L) + ALPHA(T) - ALPHA(TL); + int pRed = RED(L) + RED(T) - RED(TL); + int pGreen = GREEN(L) + GREEN(T) - GREEN(TL); + int pBlue = BLUE(L) + BLUE(T) - BLUE(TL); + + // Manhattan distances to estimates for left and top pixels. + int pL = abs(pAlpha - ALPHA(L)) + abs(pRed - RED(L)) + + abs(pGreen - GREEN(L)) + abs(pBlue - BLUE(L)); + int pT = abs(pAlpha - ALPHA(T)) + abs(pRed - RED(T)) + + abs(pGreen - GREEN(T)) + abs(pBlue - BLUE(T)); + + // Return either left or top, the one closer to the prediction. + if (pL < pT) { + return L; + } else { + return T; + } +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The functions `ClampAddSubtractFull` and `ClampAddSubtractHalf` are performed +for each ARGB component as follows: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Clamp the input value between 0 and 255. +int Clamp(int a) { + return (a < 0) ? 0 : (a > 255) ? 255 : a; +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +int ClampAddSubtractFull(int a, int b, int c) { + return Clamp(a + b - c); +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +int ClampAddSubtractHalf(int a, int b) { + return Clamp(a + (a - b) / 2); +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +There are special handling rules for some border pixels. If there is a +prediction transform, regardless of the mode \[0..13\] for these pixels, the +predicted value for the left-topmost pixel of the image is 0xff000000, all +pixels on the top row are L-pixel, and all pixels on the leftmost column are +T-pixel. + +Addressing the TR-pixel for pixels on the rightmost column is +exceptional. The pixels on the rightmost column are predicted by using the modes +\[0..13\], just like pixels not on the border, but the leftmost pixel on the +same row as the current pixel is instead used as the TR-pixel. + +The final pixel value is obtained by adding each channel of the predicted value +to the encoded residual value. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void PredictorTransformOutput(uint32 residual, uint32 pred, + uint8* alpha, uint8* red, + uint8* green, uint8* blue) { + *alpha = ALPHA(residual) + ALPHA(pred); + *red = RED(residual) + RED(pred); + *green = GREEN(residual) + GREEN(pred); + *blue = BLUE(residual) + BLUE(pred); +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +### 4.2 Color Transform + +The goal of the color transform is to decorrelate the R, G, and B values of each +pixel. The color transform keeps the green (G) value as it is, transforms the +red (R) value based on the green value, and transforms the blue (B) value based +on the green value and then on the red value. + +As is the case for the predictor transform, first the image is divided into +blocks, and the same transform mode is used for all the pixels in a block. For +each block, there are three types of color transform elements. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +typedef struct { + uint8 green_to_red; + uint8 green_to_blue; + uint8 red_to_blue; +} ColorTransformElement; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The actual color transform is done by defining a color transform delta. The +color transform delta depends on the `ColorTransformElement`, which is the same +for all the pixels in a particular block. The delta is subtracted during the +color transform. The inverse color transform then is just adding those deltas. + +The color transform function is defined as follows: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void ColorTransform(uint8 red, uint8 blue, uint8 green, + ColorTransformElement *trans, + uint8 *new_red, uint8 *new_blue) { + // Transformed values of red and blue components + int tmp_red = red; + int tmp_blue = blue; + + // Applying the transform is just subtracting the transform deltas + tmp_red -= ColorTransformDelta(trans->green_to_red, green); + tmp_blue -= ColorTransformDelta(trans->green_to_blue, green); + tmp_blue -= ColorTransformDelta(trans->red_to_blue, red); + + *new_red = tmp_red & 0xff; + *new_blue = tmp_blue & 0xff; +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +`ColorTransformDelta` is computed using a signed 8-bit integer representing a +3.5-fixed-point number and a signed 8-bit RGB color channel (c) \[-128..127\] +and is defined as follows: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +int8 ColorTransformDelta(int8 t, int8 c) { + return (t * c) >> 5; +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A conversion from the 8-bit unsigned representation (uint8) to the 8-bit signed +one (int8) is required before calling `ColorTransformDelta()`. The signed value +should be interpreted as an 8-bit two's complement number (that is: uint8 range +\[128..255\] is mapped to the \[-128..-1\] range of its converted int8 value). + +The multiplication is to be done using more precision (with at least 16-bit +precision). The sign extension property of the shift operation does not matter +here; only the lowest 8 bits are used from the result, and there the sign +extension shifting and unsigned shifting are consistent with each other. + +Now, we describe the contents of color transform data so that decoding can apply +the inverse color transform and recover the original red and blue values. The +first 3 bits of the color transform data contain the width and height of the +image block in number of bits, just like the predictor transform: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +int size_bits = ReadBits(3) + 2; +int block_width = 1 << size_bits; +int block_height = 1 << size_bits; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The remaining part of the color transform data contains `ColorTransformElement` +instances, corresponding to each block of the image. Each +`ColorTransformElement` `'cte'` is treated as a pixel in a subresolution image +whose alpha component is `255`, red component is `cte.red_to_blue`, green +component is `cte.green_to_blue`, and blue component is `cte.green_to_red`. + +During decoding, `ColorTransformElement` instances of the blocks are decoded and +the inverse color transform is applied on the ARGB values of the pixels. As +mentioned earlier, that inverse color transform is just adding +`ColorTransformElement` values to the red and blue channels. The alpha and green +channels are left as is. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void InverseTransform(uint8 red, uint8 green, uint8 blue, + ColorTransformElement *trans, + uint8 *new_red, uint8 *new_blue) { + // Transformed values of red and blue components + int tmp_red = red; + int tmp_blue = blue; + + // Applying the inverse transform is just adding the + // color transform deltas + tmp_red += ColorTransformDelta(trans->green_to_red, green); + tmp_blue += ColorTransformDelta(trans->green_to_blue, green); + tmp_blue += + ColorTransformDelta(trans->red_to_blue, tmp_red & 0xff); + + *new_red = tmp_red & 0xff; + *new_blue = tmp_blue & 0xff; +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +### 4.3 Subtract Green Transform + +The subtract green transform subtracts green values from red and blue values of +each pixel. When this transform is present, the decoder needs to add the green +value to both the red and blue values. There is no data associated with this +transform. The decoder applies the inverse transform as follows: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void AddGreenToBlueAndRed(uint8 green, uint8 *red, uint8 *blue) { + *red = (*red + green) & 0xff; + *blue = (*blue + green) & 0xff; +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This transform is redundant, as it can be modeled using the color transform, but +since there is no additional data here, the subtract green transform can be +coded using fewer bits than a full-blown color transform. + +### 4.4 Color Indexing Transform + +If there are not many unique pixel values, it may be more efficient to create a +color index array and replace the pixel values by the array's indices. The color +indexing transform achieves this. (In the context of WebP lossless, we +specifically do not call this a palette transform because a similar but more +dynamic concept exists in WebP lossless encoding: color cache.) + +The color indexing transform checks for the number of unique ARGB values in the +image. If that number is below a threshold (256), it creates an array of those +ARGB values, which is then used to replace the pixel values with the +corresponding index: the green channel of the pixels are replaced with the +index, all alpha values are set to 255, and all red and blue values to 0. + +The transform data contains the color table size and the entries in the color +table. The decoder reads the color indexing transform data as follows: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// 8-bit value for the color table size +int color_table_size = ReadBits(8) + 1; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The color table is stored using the image storage format itself. The color table +can be obtained by reading an image, without the RIFF header, image size, and +transforms, assuming the height of 1 pixel and the width of `color_table_size`. +The color table is always subtraction-coded to reduce image entropy. The deltas +of palette colors contain typically much less entropy than the colors +themselves, leading to significant savings for smaller images. In decoding, +every final color in the color table can be obtained by adding the previous +color component values by each ARGB component separately and storing the least +significant 8 bits of the result. + +The inverse transform for the image is simply replacing the pixel values (which +are indices to the color table) with the actual color table values. The indexing +is done based on the green component of the ARGB color. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Inverse transform +argb = color_table[GREEN(argb)]; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If the index is equal to or larger than `color_table_size`, the argb color value +should be set to 0x00000000 (transparent black). + +When the color table is small (equal to or less than 16 colors), several pixels +are bundled into a single pixel. The pixel bundling packs several (2, 4, or 8) +pixels into a single pixel, reducing the image width respectively. Pixel +bundling allows for a more efficient joint distribution entropy coding of +neighboring pixels and gives some arithmetic coding-like benefits to the +entropy code, but it can only be used when there are 16 or fewer unique values. + +`color_table_size` specifies how many pixels are combined: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +int width_bits; +if (color_table_size <= 2) { + width_bits = 3; +} else if (color_table_size <= 4) { + width_bits = 2; +} else if (color_table_size <= 16) { + width_bits = 1; +} else { + width_bits = 0; +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +`width_bits` has a value of 0, 1, 2, or 3. A value of 0 indicates no pixel +bundling is to be done for the image. A value of 1 indicates that two pixels are +combined, and each pixel has a range of \[0..15\]. A value of 2 indicates that +four pixels are combined, and each pixel has a range of \[0..3\]. A value of 3 +indicates that eight pixels are combined and each pixel has a range of \[0..1\], +that is, a binary value. + +The values are packed into the green component as follows: + + * `width_bits` = 1: For every x value, where x ≡ 0 (mod 2), a green + value at x is positioned into the 4 least significant bits of the + green value at x / 2, and a green value at x + 1 is positioned into the + 4 most significant bits of the green value at x / 2. + * `width_bits` = 2: For every x value, where x ≡ 0 (mod 4), a green + value at x is positioned into the 2 least-significant bits of the + green value at x / 4, and green values at x + 1 to x + 3 are positioned in + order to the more significant bits of the green value at x / 4. + * `width_bits` = 3: For every x value, where x ≡ 0 (mod 8), a green + value at x is positioned into the least significant bit of the green + value at x / 8, and green values at x + 1 to x + 7 are positioned in order + to the more significant bits of the green value at x / 8. + +After reading this transform, `image_width` is subsampled by `width_bits`. This +affects the size of subsequent transforms. The new size can be calculated using +`DIV_ROUND_UP`, as defined [earlier](#predictor-transform). + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +image_width = DIV_ROUND_UP(image_width, 1 << width_bits); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +5 Image Data +------------ + +Image data is an array of pixel values in scan-line order. + +### 5.1 Roles of Image Data + +We use image data in five different roles: + + 1. ARGB image: Stores the actual pixels of the image. + 1. Entropy image: Stores the meta prefix codes (see + ["Decoding of Meta Prefix Codes"](#decoding-of-meta-prefix-codes)). + 1. Predictor image: Stores the metadata for the predictor transform (see + ["Predictor Transform"](#predictor-transform)). + 1. Color transform image: Created by `ColorTransformElement` values + (defined in ["Color Transform"](#color-transform)) for different blocks of + the image. + 1. Color indexing image: An array of size `color_table_size` (up to 256 ARGB + values) storing the metadata for the color indexing transform (see + ["Color Indexing Transform"](#color-indexing-transform)). + +### 5.2 Encoding of Image Data + +The encoding of image data is independent of its role. + +The image is first divided into a set of fixed-size blocks (typically 16x16 +blocks). Each of these blocks are modeled using their own entropy codes. Also, +several blocks may share the same entropy codes. + +**Rationale:** Storing an entropy code incurs a cost. This cost can be minimized +if statistically similar blocks share an entropy code, thereby storing that code +only once. For example, an encoder can find similar blocks by clustering them +using their statistical properties or by repeatedly joining a pair of randomly +selected clusters when it reduces the overall amount of bits needed to encode +the image. + +Each pixel is encoded using one of the three possible methods: + + 1. Prefix-coded literals: Each channel (green, red, blue, and alpha) is + entropy-coded independently. + 2. LZ77 backward reference: A sequence of pixels are copied from elsewhere in + the image. + 3. Color cache code: Using a short multiplicative hash code (color cache + index) of a recently seen color. + +The following subsections describe each of these in detail. + +#### 5.2.1 Prefix-Coded Literals + +The pixel is stored as prefix-coded values of green, red, blue, and alpha (in +that order). See [Section 6.2.3](#decoding-entropy-coded-image-data) for +details. + +#### 5.2.2 LZ77 Backward Reference + +Backward references are tuples of _length_ and _distance code_: + + * Length indicates how many pixels in scan-line order are to be copied. + * Distance code is a number indicating the position of a previously seen + pixel, from which the pixels are to be copied. The exact mapping is + described [below](#distance-mapping). + +The length and distance values are stored using **LZ77 prefix coding**. + +LZ77 prefix coding divides large integer values into two parts: the _prefix +code_ and the _extra bits_. The prefix code is stored using an entropy code, +while the extra bits are stored as they are (without an entropy code). + +**Rationale**: This approach reduces the storage requirement for the entropy +code. Also, large values are usually rare, so extra bits would be used for very +few values in the image. Thus, this approach results in better compression +overall. + +The following table denotes the prefix codes and extra bits used for storing +different ranges of values. + +Note: The maximum backward reference length is limited to 4096. Hence, only the +first 24 prefix codes (with the respective extra bits) are meaningful for length +values. For distance values, however, all the 40 prefix codes are valid. + +| Value range | Prefix code | Extra bits | +| --------------- | ----------- | ---------- | +| 1 | 0 | 0 | +| 2 | 1 | 0 | +| 3 | 2 | 0 | +| 4 | 3 | 0 | +| 5..6 | 4 | 1 | +| 7..8 | 5 | 1 | +| 9..12 | 6 | 2 | +| 13..16 | 7 | 2 | +| ... | ... | ... | +| 3072..4096 | 23 | 10 | +| ... | ... | ... | +| 524289..786432 | 38 | 18 | +| 786433..1048576 | 39 | 18 | + +The pseudocode to obtain a (length or distance) value from the prefix code is as +follows: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +if (prefix_code < 4) { + return prefix_code + 1; +} +int extra_bits = (prefix_code - 2) >> 1; +int offset = (2 + (prefix_code & 1)) << extra_bits; +return offset + ReadBits(extra_bits) + 1; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +##### Distance Mapping + +As noted previously, a distance code is a number indicating the position of a +previously seen pixel, from which the pixels are to be copied. This subsection +defines the mapping between a distance code and the position of a previous +pixel. + +Distance codes larger than 120 denote the pixel distance in scan-line order, +offset by 120. + +The smallest distance codes \[1..120\] are special and are reserved for a close +neighborhood of the current pixel. This neighborhood consists of 120 pixels: + + * Pixels that are 1 to 7 rows above the current pixel and are up to 8 columns + to the left or up to 7 columns to the right of the current pixel. \[Total + such pixels = `7 * (8 + 1 + 7) = 112`\]. + * Pixels that are in the same row as the current pixel and are up to 8 + columns to the left of the current pixel. \[`8` such pixels\]. + +The mapping between distance code `i` and the neighboring pixel offset +`(xi, yi)` is as follows: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +(0, 1), (1, 0), (1, 1), (-1, 1), (0, 2), (2, 0), (1, 2), +(-1, 2), (2, 1), (-2, 1), (2, 2), (-2, 2), (0, 3), (3, 0), +(1, 3), (-1, 3), (3, 1), (-3, 1), (2, 3), (-2, 3), (3, 2), +(-3, 2), (0, 4), (4, 0), (1, 4), (-1, 4), (4, 1), (-4, 1), +(3, 3), (-3, 3), (2, 4), (-2, 4), (4, 2), (-4, 2), (0, 5), +(3, 4), (-3, 4), (4, 3), (-4, 3), (5, 0), (1, 5), (-1, 5), +(5, 1), (-5, 1), (2, 5), (-2, 5), (5, 2), (-5, 2), (4, 4), +(-4, 4), (3, 5), (-3, 5), (5, 3), (-5, 3), (0, 6), (6, 0), +(1, 6), (-1, 6), (6, 1), (-6, 1), (2, 6), (-2, 6), (6, 2), +(-6, 2), (4, 5), (-4, 5), (5, 4), (-5, 4), (3, 6), (-3, 6), +(6, 3), (-6, 3), (0, 7), (7, 0), (1, 7), (-1, 7), (5, 5), +(-5, 5), (7, 1), (-7, 1), (4, 6), (-4, 6), (6, 4), (-6, 4), +(2, 7), (-2, 7), (7, 2), (-7, 2), (3, 7), (-3, 7), (7, 3), +(-7, 3), (5, 6), (-5, 6), (6, 5), (-6, 5), (8, 0), (4, 7), +(-4, 7), (7, 4), (-7, 4), (8, 1), (8, 2), (6, 6), (-6, 6), +(8, 3), (5, 7), (-5, 7), (7, 5), (-7, 5), (8, 4), (6, 7), +(-6, 7), (7, 6), (-7, 6), (8, 5), (7, 7), (-7, 7), (8, 6), +(8, 7) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For example, the distance code `1` indicates an offset of `(0, 1)` for the +neighboring pixel, that is, the pixel above the current pixel (0 pixel +difference in the X direction and 1 pixel difference in the Y direction). +Similarly, the distance code `3` indicates the top-left pixel. + +The decoder can convert a distance code `i` to a scan-line order distance `dist` +as follows: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +(xi, yi) = distance_map[i - 1] +dist = xi + yi * xsize +if (dist < 1) { + dist = 1 +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +where `distance_map` is the mapping noted above, and `xsize` is the width of the +image in pixels. + +#### 5.2.3 Color Cache Coding +{:#color-cache-code} + +Color cache stores a set of colors that have been recently used in the image. + +**Rationale:** This way, the recently used colors can sometimes be referred to +more efficiently than emitting them using the other two methods (described in +Sections [5.2.1](#prefix-coded-literals) and [5.2.2](#lz77-backward-reference)). + +Color cache codes are stored as follows. First, there is a 1-bit value that +indicates if the color cache is used. If this bit is 0, no color cache codes +exist, and they are not transmitted in the prefix code that decodes the green +symbols and the length prefix codes. However, if this bit is 1, the color cache +size is read next: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +int color_cache_code_bits = ReadBits(4); +int color_cache_size = 1 << color_cache_code_bits; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +`color_cache_code_bits` defines the size of the color cache (`1 << +color_cache_code_bits`). The range of allowed values for +`color_cache_code_bits` is \[1..11\]. Compliant decoders must indicate a +corrupted bitstream for other values. + +A color cache is an array of size `color_cache_size`. Each entry stores one ARGB +color. Colors are looked up by indexing them by `(0x1e35a7bd * color) >> (32 - +color_cache_code_bits)`. Only one lookup is done in a color cache; there is no +conflict resolution. + +In the beginning of decoding or encoding of an image, all entries in all color +cache values are set to zero. The color cache code is converted to this color at +decoding time. The state of the color cache is maintained by inserting every +pixel, be it produced by backward referencing or as literals, into the cache in +the order they appear in the stream. + +6 Entropy Code +-------------- + +### 6.1 Overview + +Most of the data is coded using a [canonical prefix code][canonical_huff]. +Hence, the codes are transmitted by sending the _prefix code lengths_, as +opposed to the actual _prefix codes_. + +In particular, the format uses **spatially variant prefix coding**. In other +words, different blocks of the image can potentially use different entropy +codes. + +**Rationale**: Different areas of the image may have different characteristics. +So, allowing them to use different entropy codes provides more flexibility and +potentially better compression. + +### 6.2 Details + +The encoded image data consists of several parts: + + 1. Decoding and building the prefix codes. + 1. Meta prefix codes. + 1. Entropy-coded image data. + +For any given pixel (x, y), there is a set of five prefix codes associated with +it. These codes are (in bitstream order): + + * **Prefix code #1**: Used for green channel, backward-reference length, and + color cache. + * **Prefix code #2, #3, and #4**: Used for red, blue, and alpha channels, + respectively. + * **Prefix code #5**: Used for backward-reference distance. + +From here on, we refer to this set as a **prefix code group**. + +#### 6.2.1 Decoding and Building the Prefix Codes + +This section describes how to read the prefix code lengths from the bitstream. + +The prefix code lengths can be coded in two ways. The method used is specified +by a 1-bit value. + + * If this bit is 1, it is a _simple code length code_. + * If this bit is 0, it is a _normal code length code_. + +In both cases, there can be unused code lengths that are still part of the +stream. This may be inefficient, but it is allowed by the format. +The described tree must be a complete binary tree. A single leaf node is +considered a complete binary tree and can be encoded using either the simple +code length code or the normal code length code. When coding a single leaf +node using the _normal code length code_, all but one code length are zeros, +and the single leaf node value is marked with the length of 1 -- even when no +bits are consumed when that single leaf node tree is used. + +##### Simple Code Length Code + +This variant is used in the special case when only 1 or 2 prefix symbols are in +the range \[0..255\] with code length `1`. All other prefix code lengths are +implicitly zeros. + +The first bit indicates the number of symbols: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +int num_symbols = ReadBits(1) + 1; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following are the symbol values. + +This first symbol is coded using 1 or 8 bits, depending on the value of +`is_first_8bits`. The range is \[0..1\] or \[0..255\], respectively. The second +symbol, if present, is always assumed to be in the range \[0..255\] and coded +using 8 bits. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +int is_first_8bits = ReadBits(1); +symbol0 = ReadBits(1 + 7 * is_first_8bits); +code_lengths[symbol0] = 1; +if (num_symbols == 2) { + symbol1 = ReadBits(8); + code_lengths[symbol1] = 1; +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The two symbols should be different. Duplicate symbols are allowed, but +inefficient. + +**Note:** Another special case is when _all_ prefix code lengths are _zeros_ (an +empty prefix code). For example, a prefix code for distance can be empty if +there are no backward references. Similarly, prefix codes for alpha, red, and +blue can be empty if all pixels within the same meta prefix code are produced +using the color cache. However, this case doesn't need special handling, as +empty prefix codes can be coded as those containing a single symbol `0`. + +##### Normal Code Length Code + +The code lengths of the prefix code fit in 8 bits and are read as follows. +First, `num_code_lengths` specifies the number of code lengths. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +int num_code_lengths = 4 + ReadBits(4); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The code lengths are themselves encoded using prefix codes; lower-level code +lengths, `code_length_code_lengths`, first have to be read. The rest of those +`code_length_code_lengths` (according to the order in `kCodeLengthCodeOrder`) +are zeros. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +int kCodeLengthCodes = 19; +int kCodeLengthCodeOrder[kCodeLengthCodes] = { + 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +}; +int code_length_code_lengths[kCodeLengthCodes] = { 0 }; // All zeros +for (i = 0; i < num_code_lengths; ++i) { + code_length_code_lengths[kCodeLengthCodeOrder[i]] = ReadBits(3); +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Next, if `ReadBits(1) == 0`, the maximum number of different read symbols +(`max_symbol`) for each symbol type (A, R, G, B, and distance) is set to its +alphabet size: + + * G channel: 256 + 24 + `color_cache_size` + * Other literals (A, R, and B): 256 + * Distance code: 40 + +Otherwise, it is defined as: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +int length_nbits = 2 + 2 * ReadBits(3); +int max_symbol = 2 + ReadBits(length_nbits); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If `max_symbol` is larger than the size of the alphabet for the symbol type, the +bitstream is invalid. + +A prefix table is then built from `code_length_code_lengths` and used to read up +to `max_symbol` code lengths. + + * Code \[0..15\] indicates literal code lengths. + * Value 0 means no symbols have been coded. + * Values \[1..15\] indicate the bit length of the respective code. + * Code 16 repeats the previous nonzero value \[3..6\] times, that is, + `3 + ReadBits(2)` times. If code 16 is used before a nonzero + value has been emitted, a value of 8 is repeated. + * Code 17 emits a streak of zeros of length \[3..10\], that is, `3 + + ReadBits(3)` times. + * Code 18 emits a streak of zeros of length \[11..138\], that is, + `11 + ReadBits(7)` times. + +Once code lengths are read, a prefix code for each symbol type (A, R, G, B, and +distance) is formed using their respective alphabet sizes. + +The Normal Code Length Code must code a full decision tree, that is, the sum of +`2 ^ (-length)` for all non-zero codes must be exactly one. There is however +one exception to this rule, the single leaf node tree, where the leaf node +value is marked with value 1 and other values are 0s. + +#### 6.2.2 Decoding of Meta Prefix Codes + +As noted earlier, the format allows the use of different prefix codes for +different blocks of the image. _Meta prefix codes_ are indexes identifying which +prefix codes to use in different parts of the image. + +Meta prefix codes may be used _only_ when the image is being used in the +[role](#roles-of-image-data) of an _ARGB image_. + +There are two possibilities for the meta prefix codes, indicated by a 1-bit +value: + + * If this bit is zero, there is only one meta prefix code used everywhere in + the image. No more data is stored. + * If this bit is one, the image uses multiple meta prefix codes. These meta + prefix codes are stored as an _entropy image_ (described below). + +The red and green components of a pixel define a 16-bit meta prefix code used in +a particular block of the ARGB image. + +##### Entropy Image + +The entropy image defines which prefix codes are used in different parts of the +image. + +The first 3 bits contain the `prefix_bits` value. The dimensions of the entropy +image are derived from `prefix_bits`: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +int prefix_bits = ReadBits(3) + 2; +int prefix_xsize = DIV_ROUND_UP(xsize, 1 << prefix_bits); +int prefix_ysize = DIV_ROUND_UP(ysize, 1 << prefix_bits); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +where `DIV_ROUND_UP` is as defined [earlier](#predictor-transform). + +The next bits contain an entropy image of width `prefix_xsize` and height +`prefix_ysize`. + +##### Interpretation of Meta Prefix Codes + +The number of prefix code groups in the ARGB image can be obtained by finding +the _largest meta prefix code_ from the entropy image: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +int num_prefix_groups = max(entropy image) + 1; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +where `max(entropy image)` indicates the largest prefix code stored in the +entropy image. + +As each prefix code group contains five prefix codes, the total number of prefix +codes is: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +int num_prefix_codes = 5 * num_prefix_groups; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Given a pixel (x, y) in the ARGB image, we can obtain the corresponding prefix +codes to be used as follows: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +int position = + (y >> prefix_bits) * prefix_xsize + (x >> prefix_bits); +int meta_prefix_code = (entropy_image[position] >> 8) & 0xffff; +PrefixCodeGroup prefix_group = prefix_code_groups[meta_prefix_code]; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +where we have assumed the existence of `PrefixCodeGroup` structure, which +represents a set of five prefix codes. Also, `prefix_code_groups` is an array of +`PrefixCodeGroup` (of size `num_prefix_groups`). + +The decoder then uses prefix code group `prefix_group` to decode the pixel +(x, y), as explained in ["Decoding Entropy-Coded Image +Data"](#decoding-entropy-coded-image-data). + +#### 6.2.3 Decoding Entropy-Coded Image Data + +For the current position (x, y) in the image, the decoder first identifies the +corresponding prefix code group (as explained in the last section). Given the +prefix code group, the pixel is read and decoded as follows. + +Next, read the symbol S from the bitstream using prefix code #1. Note that S is +any integer in the range `0` to +`(256 + 24 + ` [`color_cache_size`](#color-cache-code)` - 1)`. + +The interpretation of S depends on its value: + + 1. If S < 256 + 1. Use S as the green component. + 1. Read red from the bitstream using prefix code #2. + 1. Read blue from the bitstream using prefix code #3. + 1. Read alpha from the bitstream using prefix code #4. + 1. If S >= 256 & S < 256 + 24 + 1. Use S - 256 as a length prefix code. + 1. Read extra bits for the length from the bitstream. + 1. Determine backward-reference length L from length prefix code and the + extra bits read. + 1. Read the distance prefix code from the bitstream using prefix code #5. + 1. Read extra bits for the distance from the bitstream. + 1. Determine backward-reference distance D from the distance prefix code + and the extra bits read. + 1. Copy L pixels (in scan-line order) from the sequence of pixels starting + at the current position minus D pixels. + 1. If S >= 256 + 24 + 1. Use S - (256 + 24) as the index into the color cache. + 1. Get ARGB color from the color cache at that index. + +7 Overall Structure of the Format +--------------------------------- + +Below is a view into the format in Augmented Backus-Naur Form (ABNF) +[RFC 5234][] [RFC 7405][]. It does not cover all details. The end-of-image (EOI) +is only implicitly coded into the number of pixels (xsize * ysize). + +Note that `*element` means `element` can be repeated 0 or more times. `5element` +means `element` is repeated exactly 5 times. `%b` represents a binary value. + +#### 7.1 Basic Structure + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +format = RIFF-header image-header image-stream +RIFF-header = %s"RIFF" 4OCTET %s"WEBPVP8L" 4OCTET +image-header = %x2F image-size alpha-is-used version +image-size = 14BIT 14BIT ; width - 1, height - 1 +alpha-is-used = 1BIT +version = 3BIT ; 0 +image-stream = optional-transform spatially-coded-image +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#### 7.2 Structure of Transforms + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +optional-transform = (%b1 transform optional-transform) / %b0 +transform = predictor-tx / color-tx / subtract-green-tx +transform =/ color-indexing-tx + +predictor-tx = %b00 predictor-image +predictor-image = 3BIT ; sub-pixel code + entropy-coded-image + +color-tx = %b01 color-image +color-image = 3BIT ; sub-pixel code + entropy-coded-image + +subtract-green-tx = %b10 + +color-indexing-tx = %b11 color-indexing-image +color-indexing-image = 8BIT ; color count + entropy-coded-image +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#### 7.3 Structure of the Image Data + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +spatially-coded-image = color-cache-info meta-prefix data +entropy-coded-image = color-cache-info data + +color-cache-info = %b0 +color-cache-info =/ (%b1 4BIT) ; 1 followed by color cache size + +meta-prefix = %b0 / (%b1 entropy-image) + +data = prefix-codes lz77-coded-image +entropy-image = 3BIT ; subsample value + entropy-coded-image + +prefix-codes = prefix-code-group *prefix-codes +prefix-code-group = + 5prefix-code ; See "Interpretation of Meta Prefix Codes" to + ; understand what each of these five prefix + ; codes are for. + +prefix-code = simple-prefix-code / normal-prefix-code +simple-prefix-code = ; see "Simple Code Length Code" for details +normal-prefix-code = ; see "Normal Code Length Code" for details + +lz77-coded-image = + *((argb-pixel / lz77-copy / color-cache-code) lz77-coded-image) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following is a possible example sequence: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +RIFF-header image-size %b1 subtract-green-tx +%b1 predictor-tx %b0 color-cache-info +%b0 prefix-codes lz77-coded-image +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +[RFC 5234]: https://www.rfc-editor.org/rfc/rfc5234 +[RFC 7405]: https://www.rfc-editor.org/rfc/rfc7405 +[canonical_huff]: https://en.wikipedia.org/wiki/Canonical_Huffman_code diff --git a/third-party/webp/libwebp/examples/Android.mk b/third-party/webp/libwebp/examples/Android.mk new file mode 100644 index 0000000000..ae0f5b4284 --- /dev/null +++ b/third-party/webp/libwebp/examples/Android.mk @@ -0,0 +1,96 @@ +# Ignore this file during non-NDK builds. +ifdef NDK_ROOT +LOCAL_PATH := $(call my-dir) + +################################################################################ +# libexample_util + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + example_util.c \ + +LOCAL_CFLAGS := $(WEBP_CFLAGS) +LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src + +LOCAL_MODULE := example_util + +include $(BUILD_STATIC_LIBRARY) + +################################################################################ +# cwebp + +include $(CLEAR_VARS) + +# Note: to enable jpeg/png encoding the sources from AOSP can be used with +# minor modification to their Android.mk files. +LOCAL_SRC_FILES := \ + cwebp.c \ + +LOCAL_CFLAGS := $(WEBP_CFLAGS) +LOCAL_STATIC_LIBRARIES := example_util imageio_util imagedec webpdemux webp + +LOCAL_MODULE := cwebp + +include $(BUILD_EXECUTABLE) + +################################################################################ +# dwebp + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + dwebp.c \ + +LOCAL_CFLAGS := $(WEBP_CFLAGS) +LOCAL_STATIC_LIBRARIES := example_util imagedec imageenc webpdemux webp +LOCAL_MODULE := dwebp + +include $(BUILD_EXECUTABLE) + +################################################################################ +# webpmux + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + webpmux.c \ + +LOCAL_CFLAGS := $(WEBP_CFLAGS) +LOCAL_STATIC_LIBRARIES := example_util imageio_util webpmux webp + +LOCAL_MODULE := webpmux_example + +include $(BUILD_EXECUTABLE) + +################################################################################ +# img2webp + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + img2webp.c \ + +LOCAL_CFLAGS := $(WEBP_CFLAGS) +LOCAL_STATIC_LIBRARIES := example_util imageio_util imagedec webpmux webpdemux \ + webp + +LOCAL_MODULE := img2webp_example + +include $(BUILD_EXECUTABLE) + +################################################################################ +# webpinfo + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + webpinfo.c \ + +LOCAL_CFLAGS := $(WEBP_CFLAGS) +LOCAL_STATIC_LIBRARIES := example_util imageio_util webp + +LOCAL_MODULE := webpinfo_example + +include $(BUILD_EXECUTABLE) +endif # NDK_ROOT diff --git a/third-party/webp/libwebp/examples/Makefile.am b/third-party/webp/libwebp/examples/Makefile.am new file mode 100644 index 0000000000..bbf0bac95e --- /dev/null +++ b/third-party/webp/libwebp/examples/Makefile.am @@ -0,0 +1,119 @@ +AM_CPPFLAGS += -I$(top_builddir)/src -I$(top_srcdir)/src + +bin_PROGRAMS = +if BUILD_DEMUX + bin_PROGRAMS += dwebp cwebp +endif +if BUILD_ANIMDIFF + noinst_PROGRAMS = anim_diff anim_dump +endif +if BUILD_GIF2WEBP + bin_PROGRAMS += gif2webp +endif +if BUILD_IMG2WEBP + bin_PROGRAMS += img2webp +endif +if BUILD_MUX + bin_PROGRAMS += webpmux +endif +if BUILD_VWEBP + bin_PROGRAMS += vwebp +endif +if BUILD_WEBPINFO + bin_PROGRAMS += webpinfo +endif + +noinst_LTLIBRARIES = libexample_util.la + +libexample_util_la_SOURCES = example_util.c example_util.h +libexample_util_la_LIBADD = ../src/libwebp.la + +anim_diff_SOURCES = anim_diff.c anim_util.c anim_util.h gifdec.c gifdec.h +anim_diff_CPPFLAGS = $(AM_CPPFLAGS) $(GIF_INCLUDES) +anim_diff_LDADD = +anim_diff_LDADD += ../src/demux/libwebpdemux.la +anim_diff_LDADD += libexample_util.la +anim_diff_LDADD += ../imageio/libimageio_util.la +anim_diff_LDADD += $(GIF_LIBS) -lm + +anim_dump_SOURCES = anim_dump.c anim_util.c anim_util.h gifdec.c gifdec.h +anim_dump_CPPFLAGS = $(AM_CPPFLAGS) $(PNG_INCLUDES) +anim_dump_CPPFLAGS += $(GIF_INCLUDES) +anim_dump_LDADD = +anim_dump_LDADD += ../src/demux/libwebpdemux.la +anim_dump_LDADD += libexample_util.la +anim_dump_LDADD += ../imageio/libimageio_util.la +anim_dump_LDADD += ../imageio/libimageenc.la +anim_dump_LDADD += $(PNG_LIBS) $(GIF_LIBS) $(TIFF_LIBS) -lm + +cwebp_SOURCES = cwebp.c stopwatch.h +cwebp_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir) +cwebp_LDADD = +cwebp_LDADD += libexample_util.la +cwebp_LDADD += ../imageio/libimageio_util.la +cwebp_LDADD += ../imageio/libimagedec.la +cwebp_LDADD += ../src/libwebp.la +cwebp_LDADD += $(JPEG_LIBS) $(PNG_LIBS) $(TIFF_LIBS) + +dwebp_SOURCES = dwebp.c stopwatch.h +dwebp_CPPFLAGS = $(AM_CPPFLAGS) +dwebp_CPPFLAGS += $(JPEG_INCLUDES) $(PNG_INCLUDES) +dwebp_LDADD = +dwebp_LDADD += libexample_util.la +dwebp_LDADD += ../imageio/libimagedec.la +dwebp_LDADD += ../imageio/libimageenc.la +dwebp_LDADD += ../imageio/libimageio_util.la +dwebp_LDADD += ../src/libwebp.la +dwebp_LDADD +=$(PNG_LIBS) $(JPEG_LIBS) + +gif2webp_SOURCES = gif2webp.c gifdec.c gifdec.h +gif2webp_CPPFLAGS = $(AM_CPPFLAGS) $(GIF_INCLUDES) +gif2webp_LDADD = +gif2webp_LDADD += libexample_util.la +gif2webp_LDADD += ../imageio/libimageio_util.la +gif2webp_LDADD += ../src/mux/libwebpmux.la +gif2webp_LDADD += ../src/libwebp.la +gif2webp_LDADD += $(GIF_LIBS) + +vwebp_SOURCES = vwebp.c +vwebp_CPPFLAGS = $(AM_CPPFLAGS) $(GL_INCLUDES) +vwebp_LDADD = +vwebp_LDADD += libexample_util.la +vwebp_LDADD += ../imageio/libimageio_util.la +vwebp_LDADD += ../src/demux/libwebpdemux.la +vwebp_LDADD += $(GL_LIBS) + +webpmux_SOURCES = webpmux.c +webpmux_CPPFLAGS = $(AM_CPPFLAGS) +webpmux_LDADD = +webpmux_LDADD += libexample_util.la +webpmux_LDADD += ../imageio/libimageio_util.la +webpmux_LDADD += ../src/mux/libwebpmux.la +webpmux_LDADD += ../src/libwebp.la + +img2webp_SOURCES = img2webp.c +img2webp_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir) +img2webp_LDADD = +img2webp_LDADD += libexample_util.la +img2webp_LDADD += ../imageio/libimageio_util.la +img2webp_LDADD += ../imageio/libimagedec.la +img2webp_LDADD += ../src/mux/libwebpmux.la +img2webp_LDADD += ../src/libwebp.la +img2webp_LDADD += $(PNG_LIBS) $(JPEG_LIBS) $(TIFF_LIBS) + +webpinfo_SOURCES = webpinfo.c +webpinfo_CPPFLAGS = $(AM_CPPFLAGS) +webpinfo_LDADD = +webpinfo_LDADD += libexample_util.la +webpinfo_LDADD += ../imageio/libimageio_util.la +webpinfo_LDADD += ../src/libwebp.la + +if BUILD_LIBWEBPDECODER + anim_diff_LDADD += ../src/libwebpdecoder.la + anim_dump_LDADD += ../src/libwebpdecoder.la + vwebp_LDADD += ../src/libwebpdecoder.la +else + anim_diff_LDADD += ../src/libwebp.la + anim_dump_LDADD += ../src/libwebp.la + vwebp_LDADD += ../src/libwebp.la +endif diff --git a/third-party/webp/libwebp/examples/anim_diff.c b/third-party/webp/libwebp/examples/anim_diff.c new file mode 100644 index 0000000000..7ffabc8fd4 --- /dev/null +++ b/third-party/webp/libwebp/examples/anim_diff.c @@ -0,0 +1,317 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Checks if given pair of animated GIF/WebP images are identical: +// That is: their reconstructed canvases match pixel-by-pixel and their other +// animation properties (loop count etc) also match. +// +// example: anim_diff foo.gif bar.webp + +#include +#include +#include +#include // for 'strtod'. +#include // for 'strcmp'. + +#include "./anim_util.h" +#include "./example_util.h" +#include "./unicode.h" + +#if defined(_MSC_VER) && _MSC_VER < 1900 +#define snprintf _snprintf +#endif + +// Returns true if 'a + b' will overflow. +static int AdditionWillOverflow(int a, int b) { + return (b > 0) && (a > INT_MAX - b); +} + +static int FramesAreEqual(const uint8_t* const rgba1, + const uint8_t* const rgba2, int width, int height) { + const int stride = width * 4; // Always true for 'DecodedFrame.rgba'. + return !memcmp(rgba1, rgba2, stride * height); +} + +static WEBP_INLINE int PixelsAreSimilar(uint32_t src, uint32_t dst, + int max_allowed_diff) { + const int src_a = (src >> 24) & 0xff; + const int src_r = (src >> 16) & 0xff; + const int src_g = (src >> 8) & 0xff; + const int src_b = (src >> 0) & 0xff; + const int dst_a = (dst >> 24) & 0xff; + const int dst_r = (dst >> 16) & 0xff; + const int dst_g = (dst >> 8) & 0xff; + const int dst_b = (dst >> 0) & 0xff; + + return (abs(src_r * src_a - dst_r * dst_a) <= (max_allowed_diff * 255)) && + (abs(src_g * src_a - dst_g * dst_a) <= (max_allowed_diff * 255)) && + (abs(src_b * src_a - dst_b * dst_a) <= (max_allowed_diff * 255)) && + (abs(src_a - dst_a) <= max_allowed_diff); +} + +static int FramesAreSimilar(const uint8_t* const rgba1, + const uint8_t* const rgba2, + int width, int height, int max_allowed_diff) { + int i, j; + assert(max_allowed_diff > 0); + for (j = 0; j < height; ++j) { + for (i = 0; i < width; ++i) { + const int stride = width * 4; + const size_t offset = j * stride + i; + if (!PixelsAreSimilar(rgba1[offset], rgba2[offset], max_allowed_diff)) { + return 0; + } + } + } + return 1; +} + +// Minimize number of frames by combining successive frames that have at max +// 'max_diff' difference per channel between corresponding pixels. +static void MinimizeAnimationFrames(AnimatedImage* const img, int max_diff) { + uint32_t i; + for (i = 1; i < img->num_frames; ++i) { + DecodedFrame* const frame1 = &img->frames[i - 1]; + DecodedFrame* const frame2 = &img->frames[i]; + const uint8_t* const rgba1 = frame1->rgba; + const uint8_t* const rgba2 = frame2->rgba; + int should_merge_frames = 0; + // If merging frames will result in integer overflow for 'duration', + // skip merging. + if (AdditionWillOverflow(frame1->duration, frame2->duration)) continue; + if (max_diff > 0) { + should_merge_frames = FramesAreSimilar(rgba1, rgba2, img->canvas_width, + img->canvas_height, max_diff); + } else { + should_merge_frames = + FramesAreEqual(rgba1, rgba2, img->canvas_width, img->canvas_height); + } + if (should_merge_frames) { // Merge 'i+1'th frame into 'i'th frame. + frame1->duration += frame2->duration; + if (i + 1 < img->num_frames) { + memmove(&img->frames[i], &img->frames[i + 1], + (img->num_frames - i - 1) * sizeof(*img->frames)); + } + --img->num_frames; + --i; + } + } +} + +static int CompareValues(uint32_t a, uint32_t b, const char* output_str) { + if (a != b) { + fprintf(stderr, "%s: %d vs %d\n", output_str, a, b); + return 0; + } + return 1; +} + +static int CompareBackgroundColor(uint32_t bg1, uint32_t bg2, int premultiply) { + if (premultiply) { + const int alpha1 = (bg1 >> 24) & 0xff; + const int alpha2 = (bg2 >> 24) & 0xff; + if (alpha1 == 0 && alpha2 == 0) return 1; + } + if (bg1 != bg2) { + fprintf(stderr, "Background color mismatch: 0x%08x vs 0x%08x\n", + bg1, bg2); + return 0; + } + return 1; +} + +// Note: As long as frame durations and reconstructed frames are identical, it +// is OK for other aspects like offsets, dispose/blend method to vary. +static int CompareAnimatedImagePair(const AnimatedImage* const img1, + const AnimatedImage* const img2, + int premultiply, + double min_psnr) { + int ok = 1; + const int is_multi_frame_image = (img1->num_frames > 1); + uint32_t i; + + ok = CompareValues(img1->canvas_width, img2->canvas_width, + "Canvas width mismatch") && ok; + ok = CompareValues(img1->canvas_height, img2->canvas_height, + "Canvas height mismatch") && ok; + ok = CompareValues(img1->num_frames, img2->num_frames, + "Frame count mismatch") && ok; + if (!ok) return 0; // These are fatal failures, can't proceed. + + if (is_multi_frame_image) { // Checks relevant for multi-frame images only. + int max_loop_count_workaround = 0; + // Transcodes to webp increase the gif loop count by 1 for compatibility. + // When the gif has the maximum value the webp value will be off by one. + if ((img1->format == ANIM_GIF && img1->loop_count == 65536 && + img2->format == ANIM_WEBP && img2->loop_count == 65535) || + (img1->format == ANIM_WEBP && img1->loop_count == 65535 && + img2->format == ANIM_GIF && img2->loop_count == 65536)) { + max_loop_count_workaround = 1; + } + ok = (max_loop_count_workaround || + CompareValues(img1->loop_count, img2->loop_count, + "Loop count mismatch")) && ok; + ok = CompareBackgroundColor(img1->bgcolor, img2->bgcolor, + premultiply) && ok; + } + + for (i = 0; i < img1->num_frames; ++i) { + // Pixel-by-pixel comparison. + const uint8_t* const rgba1 = img1->frames[i].rgba; + const uint8_t* const rgba2 = img2->frames[i].rgba; + int max_diff; + double psnr; + if (is_multi_frame_image) { // Check relevant for multi-frame images only. + const char format[] = "Frame #%d, duration mismatch"; + char tmp[sizeof(format) + 8]; + ok = ok && (snprintf(tmp, sizeof(tmp), format, i) >= 0); + ok = ok && CompareValues(img1->frames[i].duration, + img2->frames[i].duration, tmp); + } + GetDiffAndPSNR(rgba1, rgba2, img1->canvas_width, img1->canvas_height, + premultiply, &max_diff, &psnr); + if (min_psnr > 0.) { + if (psnr < min_psnr) { + fprintf(stderr, "Frame #%d, psnr = %.2lf (min_psnr = %f)\n", i, + psnr, min_psnr); + ok = 0; + } + } else { + if (max_diff != 0) { + fprintf(stderr, "Frame #%d, max pixel diff: %d\n", i, max_diff); + ok = 0; + } + } + } + return ok; +} + +static void Help(void) { + printf("Usage: anim_diff [options]\n"); + printf("\nOptions:\n"); + printf(" -dump_frames dump decoded frames in PAM format\n"); + printf(" -min_psnr ... minimum per-frame PSNR\n"); + printf(" -raw_comparison ..... if this flag is not used, RGB is\n"); + printf(" premultiplied before comparison\n"); + printf(" -max_diff ..... maximum allowed difference per channel\n" + " between corresponding pixels in subsequent\n" + " frames\n"); + printf(" -h .................. this help\n"); + printf(" -version ............ print version number and exit\n"); +} + +int main(int argc, const char* argv[]) { + int return_code = -1; + int dump_frames = 0; + const char* dump_folder = NULL; + double min_psnr = 0.; + int got_input1 = 0; + int got_input2 = 0; + int premultiply = 1; + int max_diff = 0; + int i, c; + const char* files[2] = { NULL, NULL }; + AnimatedImage images[2]; + + INIT_WARGV(argc, argv); + + for (c = 1; c < argc; ++c) { + int parse_error = 0; + if (!strcmp(argv[c], "-dump_frames")) { + if (c < argc - 1) { + dump_frames = 1; + dump_folder = (const char*)GET_WARGV(argv, ++c); + } else { + parse_error = 1; + } + } else if (!strcmp(argv[c], "-min_psnr")) { + if (c < argc - 1) { + min_psnr = ExUtilGetFloat(argv[++c], &parse_error); + } else { + parse_error = 1; + } + } else if (!strcmp(argv[c], "-raw_comparison")) { + premultiply = 0; + } else if (!strcmp(argv[c], "-max_diff")) { + if (c < argc - 1) { + max_diff = ExUtilGetInt(argv[++c], 0, &parse_error); + } else { + parse_error = 1; + } + } else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) { + Help(); + FREE_WARGV_AND_RETURN(0); + } else if (!strcmp(argv[c], "-version")) { + int dec_version, demux_version; + GetAnimatedImageVersions(&dec_version, &demux_version); + printf("WebP Decoder version: %d.%d.%d\nWebP Demux version: %d.%d.%d\n", + (dec_version >> 16) & 0xff, (dec_version >> 8) & 0xff, + (dec_version >> 0) & 0xff, + (demux_version >> 16) & 0xff, (demux_version >> 8) & 0xff, + (demux_version >> 0) & 0xff); + FREE_WARGV_AND_RETURN(0); + } else { + if (!got_input1) { + files[0] = (const char*)GET_WARGV(argv, c); + got_input1 = 1; + } else if (!got_input2) { + files[1] = (const char*)GET_WARGV(argv, c); + got_input2 = 1; + } else { + parse_error = 1; + } + } + if (parse_error) { + Help(); + FREE_WARGV_AND_RETURN(-1); + } + } + if (argc < 3) { + Help(); + FREE_WARGV_AND_RETURN(-1); + } + + + if (!got_input2) { + Help(); + FREE_WARGV_AND_RETURN(-1); + } + + if (dump_frames) { + WPRINTF("Dumping decoded frames in: %s\n", (const W_CHAR*)dump_folder); + } + + memset(images, 0, sizeof(images)); + for (i = 0; i < 2; ++i) { + WPRINTF("Decoding file: %s\n", (const W_CHAR*)files[i]); + if (!ReadAnimatedImage(files[i], &images[i], dump_frames, dump_folder)) { + WFPRINTF(stderr, "Error decoding file: %s\n Aborting.\n", + (const W_CHAR*)files[i]); + return_code = -2; + goto End; + } else { + MinimizeAnimationFrames(&images[i], max_diff); + } + } + + if (!CompareAnimatedImagePair(&images[0], &images[1], + premultiply, min_psnr)) { + WFPRINTF(stderr, "\nFiles %s and %s differ.\n", (const W_CHAR*)files[0], + (const W_CHAR*)files[1]); + return_code = -3; + } else { + WPRINTF("\nFiles %s and %s are identical.\n", (const W_CHAR*)files[0], + (const W_CHAR*)files[1]); + return_code = 0; + } + End: + ClearAnimatedImage(&images[0]); + ClearAnimatedImage(&images[1]); + FREE_WARGV_AND_RETURN(return_code); +} diff --git a/third-party/webp/libwebp/examples/anim_dump.c b/third-party/webp/libwebp/examples/anim_dump.c new file mode 100644 index 0000000000..e4473386aa --- /dev/null +++ b/third-party/webp/libwebp/examples/anim_dump.c @@ -0,0 +1,121 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Decodes an animated WebP file and dumps the decoded frames as PNG or TIFF. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include // for 'strcmp'. + +#include "./anim_util.h" +#include "webp/decode.h" +#include "../imageio/image_enc.h" +#include "./unicode.h" + +#if defined(_MSC_VER) && _MSC_VER < 1900 +#define snprintf _snprintf +#endif + +static void Help(void) { + printf("Usage: anim_dump [options] files...\n"); + printf("\nOptions:\n"); + printf(" -folder .... dump folder (default: '.')\n"); + printf(" -prefix .... prefix for dumped frames " + "(default: 'dump_')\n"); + printf(" -tiff ............... save frames as TIFF\n"); + printf(" -pam ................ save frames as PAM\n"); + printf(" -h .................. this help\n"); + printf(" -version ............ print version number and exit\n"); +} + +int main(int argc, const char* argv[]) { + int error = 0; + const W_CHAR* dump_folder = TO_W_CHAR("."); + const W_CHAR* prefix = TO_W_CHAR("dump_"); + const W_CHAR* suffix = TO_W_CHAR("png"); + WebPOutputFileFormat format = PNG; + int c; + + INIT_WARGV(argc, argv); + + if (argc < 2) { + Help(); + FREE_WARGV_AND_RETURN(-1); + } + + for (c = 1; !error && c < argc; ++c) { + if (!strcmp(argv[c], "-folder")) { + if (c + 1 == argc) { + fprintf(stderr, "missing argument after option '%s'\n", argv[c]); + error = 1; + break; + } + dump_folder = GET_WARGV(argv, ++c); + } else if (!strcmp(argv[c], "-prefix")) { + if (c + 1 == argc) { + fprintf(stderr, "missing argument after option '%s'\n", argv[c]); + error = 1; + break; + } + prefix = GET_WARGV(argv, ++c); + } else if (!strcmp(argv[c], "-tiff")) { + format = TIFF; + suffix = TO_W_CHAR("tiff"); + } else if (!strcmp(argv[c], "-pam")) { + format = PAM; + suffix = TO_W_CHAR("pam"); + } else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) { + Help(); + FREE_WARGV_AND_RETURN(0); + } else if (!strcmp(argv[c], "-version")) { + int dec_version, demux_version; + GetAnimatedImageVersions(&dec_version, &demux_version); + printf("WebP Decoder version: %d.%d.%d\nWebP Demux version: %d.%d.%d\n", + (dec_version >> 16) & 0xff, (dec_version >> 8) & 0xff, + (dec_version >> 0) & 0xff, + (demux_version >> 16) & 0xff, (demux_version >> 8) & 0xff, + (demux_version >> 0) & 0xff); + FREE_WARGV_AND_RETURN(0); + } else { + uint32_t i; + AnimatedImage image; + const W_CHAR* const file = GET_WARGV(argv, c); + memset(&image, 0, sizeof(image)); + WPRINTF("Decoding file: %s as %s/%sxxxx.%s\n", + file, dump_folder, prefix, suffix); + if (!ReadAnimatedImage((const char*)file, &image, 0, NULL)) { + WFPRINTF(stderr, "Error decoding file: %s\n Aborting.\n", file); + error = 1; + break; + } + for (i = 0; !error && i < image.num_frames; ++i) { + W_CHAR out_file[1024]; + WebPDecBuffer buffer; + WebPInitDecBuffer(&buffer); + buffer.colorspace = MODE_RGBA; + buffer.is_external_memory = 1; + buffer.width = image.canvas_width; + buffer.height = image.canvas_height; + buffer.u.RGBA.rgba = image.frames[i].rgba; + buffer.u.RGBA.stride = buffer.width * sizeof(uint32_t); + buffer.u.RGBA.size = buffer.u.RGBA.stride * buffer.height; + WSNPRINTF(out_file, sizeof(out_file), "%s/%s%.4d.%s", + dump_folder, prefix, i, suffix); + if (!WebPSaveImage(&buffer, format, (const char*)out_file)) { + WFPRINTF(stderr, "Error while saving image '%s'\n", out_file); + error = 1; + } + WebPFreeDecBuffer(&buffer); + } + ClearAnimatedImage(&image); + } + } + FREE_WARGV_AND_RETURN(error ? 1 : 0); +} diff --git a/third-party/webp/libwebp/examples/anim_util.c b/third-party/webp/libwebp/examples/anim_util.c new file mode 100644 index 0000000000..cf7da4c0c0 --- /dev/null +++ b/third-party/webp/libwebp/examples/anim_util.c @@ -0,0 +1,782 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Utilities for animated images + +#include "./anim_util.h" + +#include +#include +#include +#include + +#if defined(WEBP_HAVE_GIF) +#include +#endif +#include "webp/format_constants.h" +#include "webp/decode.h" +#include "webp/demux.h" +#include "../imageio/imageio_util.h" +#include "./gifdec.h" +#include "./unicode.h" +#include "./unicode_gif.h" + +#if defined(_MSC_VER) && _MSC_VER < 1900 +#define snprintf _snprintf +#endif + +static const int kNumChannels = 4; + +// ----------------------------------------------------------------------------- +// Common utilities. + +#if defined(WEBP_HAVE_GIF) +// Returns true if the frame covers the full canvas. +static int IsFullFrame(int width, int height, + int canvas_width, int canvas_height) { + return (width == canvas_width && height == canvas_height); +} +#endif // WEBP_HAVE_GIF + +static int CheckSizeForOverflow(uint64_t size) { + return (size == (size_t)size); +} + +static int AllocateFrames(AnimatedImage* const image, uint32_t num_frames) { + uint32_t i; + uint8_t* mem = NULL; + DecodedFrame* frames = NULL; + const uint64_t rgba_size = + (uint64_t)image->canvas_width * kNumChannels * image->canvas_height; + const uint64_t total_size = (uint64_t)num_frames * rgba_size * sizeof(*mem); + const uint64_t total_frame_size = (uint64_t)num_frames * sizeof(*frames); + if (!CheckSizeForOverflow(total_size) || + !CheckSizeForOverflow(total_frame_size)) { + return 0; + } + mem = (uint8_t*)WebPMalloc((size_t)total_size); + frames = (DecodedFrame*)WebPMalloc((size_t)total_frame_size); + + if (mem == NULL || frames == NULL) { + WebPFree(mem); + WebPFree(frames); + return 0; + } + WebPFree(image->raw_mem); + image->num_frames = num_frames; + image->frames = frames; + for (i = 0; i < num_frames; ++i) { + frames[i].rgba = mem + i * rgba_size; + frames[i].duration = 0; + frames[i].is_key_frame = 0; + } + image->raw_mem = mem; + return 1; +} + +void ClearAnimatedImage(AnimatedImage* const image) { + if (image != NULL) { + WebPFree(image->raw_mem); + WebPFree(image->frames); + image->num_frames = 0; + image->frames = NULL; + image->raw_mem = NULL; + } +} + +#if defined(WEBP_HAVE_GIF) +// Clear the canvas to transparent. +static void ZeroFillCanvas(uint8_t* rgba, + uint32_t canvas_width, uint32_t canvas_height) { + memset(rgba, 0, canvas_width * kNumChannels * canvas_height); +} + +// Clear given frame rectangle to transparent. +static void ZeroFillFrameRect(uint8_t* rgba, int rgba_stride, int x_offset, + int y_offset, int width, int height) { + int j; + assert(width * kNumChannels <= rgba_stride); + rgba += y_offset * rgba_stride + x_offset * kNumChannels; + for (j = 0; j < height; ++j) { + memset(rgba, 0, width * kNumChannels); + rgba += rgba_stride; + } +} + +// Copy width * height pixels from 'src' to 'dst'. +static void CopyCanvas(const uint8_t* src, uint8_t* dst, + uint32_t width, uint32_t height) { + assert(src != NULL && dst != NULL); + memcpy(dst, src, width * kNumChannels * height); +} + +// Copy pixels in the given rectangle from 'src' to 'dst' honoring the 'stride'. +static void CopyFrameRectangle(const uint8_t* src, uint8_t* dst, int stride, + int x_offset, int y_offset, + int width, int height) { + int j; + const int width_in_bytes = width * kNumChannels; + const size_t offset = y_offset * stride + x_offset * kNumChannels; + assert(width_in_bytes <= stride); + src += offset; + dst += offset; + for (j = 0; j < height; ++j) { + memcpy(dst, src, width_in_bytes); + src += stride; + dst += stride; + } +} +#endif // WEBP_HAVE_GIF + +// Canonicalize all transparent pixels to transparent black to aid comparison. +static void CleanupTransparentPixels(uint32_t* rgba, + uint32_t width, uint32_t height) { + const uint32_t* const rgba_end = rgba + width * height; + while (rgba < rgba_end) { + const uint8_t alpha = (*rgba >> 24) & 0xff; + if (alpha == 0) { + *rgba = 0; + } + ++rgba; + } +} + +// Dump frame to a PAM file. Returns true on success. +static int DumpFrame(const char filename[], const char dump_folder[], + uint32_t frame_num, const uint8_t rgba[], + int canvas_width, int canvas_height) { + int ok = 0; + size_t max_len; + int y; + const W_CHAR* base_name = NULL; + W_CHAR* file_name = NULL; + FILE* f = NULL; + const char* row; + + if (dump_folder == NULL) dump_folder = (const char*)TO_W_CHAR("."); + + base_name = WSTRRCHR(filename, '/'); + base_name = (base_name == NULL) ? (const W_CHAR*)filename : base_name + 1; + max_len = WSTRLEN(dump_folder) + 1 + WSTRLEN(base_name) + + strlen("_frame_") + strlen(".pam") + 8; + file_name = (W_CHAR*)WebPMalloc(max_len * sizeof(*file_name)); + if (file_name == NULL) goto End; + + if (WSNPRINTF(file_name, max_len, "%s/%s_frame_%d.pam", + (const W_CHAR*)dump_folder, base_name, frame_num) < 0) { + fprintf(stderr, "Error while generating file name\n"); + goto End; + } + + f = WFOPEN(file_name, "wb"); + if (f == NULL) { + WFPRINTF(stderr, "Error opening file for writing: %s\n", file_name); + ok = 0; + goto End; + } + if (fprintf(f, "P7\nWIDTH %d\nHEIGHT %d\n" + "DEPTH 4\nMAXVAL 255\nTUPLTYPE RGB_ALPHA\nENDHDR\n", + canvas_width, canvas_height) < 0) { + WFPRINTF(stderr, "Write error for file %s\n", file_name); + goto End; + } + row = (const char*)rgba; + for (y = 0; y < canvas_height; ++y) { + if (fwrite(row, canvas_width * kNumChannels, 1, f) != 1) { + WFPRINTF(stderr, "Error writing to file: %s\n", file_name); + goto End; + } + row += canvas_width * kNumChannels; + } + ok = 1; + End: + if (f != NULL) fclose(f); + WebPFree(file_name); + return ok; +} + +// ----------------------------------------------------------------------------- +// WebP Decoding. + +// Returns true if this is a valid WebP bitstream. +static int IsWebP(const WebPData* const webp_data) { + return (WebPGetInfo(webp_data->bytes, webp_data->size, NULL, NULL) != 0); +} + +// Read animated WebP bitstream 'webp_data' into 'AnimatedImage' struct. +static int ReadAnimatedWebP(const char filename[], + const WebPData* const webp_data, + AnimatedImage* const image, int dump_frames, + const char dump_folder[]) { + int ok = 0; + int dump_ok = 1; + uint32_t frame_index = 0; + int prev_frame_timestamp = 0; + WebPAnimDecoder* dec; + WebPAnimInfo anim_info; + + memset(image, 0, sizeof(*image)); + + dec = WebPAnimDecoderNew(webp_data, NULL); + if (dec == NULL) { + WFPRINTF(stderr, "Error parsing image: %s\n", (const W_CHAR*)filename); + goto End; + } + + if (!WebPAnimDecoderGetInfo(dec, &anim_info)) { + fprintf(stderr, "Error getting global info about the animation\n"); + goto End; + } + + // Animation properties. + image->canvas_width = anim_info.canvas_width; + image->canvas_height = anim_info.canvas_height; + image->loop_count = anim_info.loop_count; + image->bgcolor = anim_info.bgcolor; + + // Allocate frames. + if (!AllocateFrames(image, anim_info.frame_count)) goto End; + + // Decode frames. + while (WebPAnimDecoderHasMoreFrames(dec)) { + DecodedFrame* curr_frame; + uint8_t* curr_rgba; + uint8_t* frame_rgba; + int timestamp; + + if (!WebPAnimDecoderGetNext(dec, &frame_rgba, ×tamp)) { + fprintf(stderr, "Error decoding frame #%u\n", frame_index); + goto End; + } + assert(frame_index < anim_info.frame_count); + curr_frame = &image->frames[frame_index]; + curr_rgba = curr_frame->rgba; + curr_frame->duration = timestamp - prev_frame_timestamp; + curr_frame->is_key_frame = 0; // Unused. + memcpy(curr_rgba, frame_rgba, + image->canvas_width * kNumChannels * image->canvas_height); + + // Needed only because we may want to compare with GIF later. + CleanupTransparentPixels((uint32_t*)curr_rgba, + image->canvas_width, image->canvas_height); + + if (dump_frames && dump_ok) { + dump_ok = DumpFrame(filename, dump_folder, frame_index, curr_rgba, + image->canvas_width, image->canvas_height); + if (!dump_ok) { // Print error once, but continue decode loop. + fprintf(stderr, "Error dumping frames to %s\n", dump_folder); + } + } + + ++frame_index; + prev_frame_timestamp = timestamp; + } + ok = dump_ok; + if (ok) image->format = ANIM_WEBP; + + End: + WebPAnimDecoderDelete(dec); + return ok; +} + +// ----------------------------------------------------------------------------- +// GIF Decoding. + +#if defined(WEBP_HAVE_GIF) + +// Returns true if this is a valid GIF bitstream. +static int IsGIF(const WebPData* const data) { + return data->size > GIF_STAMP_LEN && + (!memcmp(GIF_STAMP, data->bytes, GIF_STAMP_LEN) || + !memcmp(GIF87_STAMP, data->bytes, GIF_STAMP_LEN) || + !memcmp(GIF89_STAMP, data->bytes, GIF_STAMP_LEN)); +} + +// GIFLIB_MAJOR is only defined in libgif >= 4.2.0. +#if defined(GIFLIB_MAJOR) && defined(GIFLIB_MINOR) +# define LOCAL_GIF_VERSION ((GIFLIB_MAJOR << 8) | GIFLIB_MINOR) +# define LOCAL_GIF_PREREQ(maj, min) \ + (LOCAL_GIF_VERSION >= (((maj) << 8) | (min))) +#else +# define LOCAL_GIF_VERSION 0 +# define LOCAL_GIF_PREREQ(maj, min) 0 +#endif + +#if !LOCAL_GIF_PREREQ(5, 0) + +// Added in v5.0 +typedef struct { + int DisposalMode; +#define DISPOSAL_UNSPECIFIED 0 // No disposal specified +#define DISPOSE_DO_NOT 1 // Leave image in place +#define DISPOSE_BACKGROUND 2 // Set area to background color +#define DISPOSE_PREVIOUS 3 // Restore to previous content + int UserInputFlag; // User confirmation required before disposal + int DelayTime; // Pre-display delay in 0.01sec units + int TransparentColor; // Palette index for transparency, -1 if none +#define NO_TRANSPARENT_COLOR -1 +} GraphicsControlBlock; + +static int DGifExtensionToGCB(const size_t GifExtensionLength, + const GifByteType* GifExtension, + GraphicsControlBlock* gcb) { + if (GifExtensionLength != 4) { + return GIF_ERROR; + } + gcb->DisposalMode = (GifExtension[0] >> 2) & 0x07; + gcb->UserInputFlag = (GifExtension[0] & 0x02) != 0; + gcb->DelayTime = GifExtension[1] | (GifExtension[2] << 8); + if (GifExtension[0] & 0x01) { + gcb->TransparentColor = (int)GifExtension[3]; + } else { + gcb->TransparentColor = NO_TRANSPARENT_COLOR; + } + return GIF_OK; +} + +static int DGifSavedExtensionToGCB(GifFileType* GifFile, int ImageIndex, + GraphicsControlBlock* gcb) { + int i; + if (ImageIndex < 0 || ImageIndex > GifFile->ImageCount - 1) { + return GIF_ERROR; + } + gcb->DisposalMode = DISPOSAL_UNSPECIFIED; + gcb->UserInputFlag = 0; + gcb->DelayTime = 0; + gcb->TransparentColor = NO_TRANSPARENT_COLOR; + + for (i = 0; i < GifFile->SavedImages[ImageIndex].ExtensionBlockCount; i++) { + ExtensionBlock* ep = &GifFile->SavedImages[ImageIndex].ExtensionBlocks[i]; + if (ep->Function == GRAPHICS_EXT_FUNC_CODE) { + return DGifExtensionToGCB( + ep->ByteCount, (const GifByteType*)ep->Bytes, gcb); + } + } + return GIF_ERROR; +} + +#define CONTINUE_EXT_FUNC_CODE 0x00 + +// Signature was changed in v5.0 +#define DGifOpenFileName(a, b) DGifOpenFileName(a) + +#endif // !LOCAL_GIF_PREREQ(5, 0) + +// Signature changed in v5.1 +#if !LOCAL_GIF_PREREQ(5, 1) +#define DGifCloseFile(a, b) DGifCloseFile(a) +#endif + +static int IsKeyFrameGIF(const GifImageDesc* prev_desc, int prev_dispose, + const DecodedFrame* const prev_frame, + int canvas_width, int canvas_height) { + if (prev_frame == NULL) return 1; + if (prev_dispose == DISPOSE_BACKGROUND) { + if (IsFullFrame(prev_desc->Width, prev_desc->Height, + canvas_width, canvas_height)) { + return 1; + } + if (prev_frame->is_key_frame) return 1; + } + return 0; +} + +static int GetTransparentIndexGIF(GifFileType* gif) { + GraphicsControlBlock first_gcb; + memset(&first_gcb, 0, sizeof(first_gcb)); + DGifSavedExtensionToGCB(gif, 0, &first_gcb); + return first_gcb.TransparentColor; +} + +static uint32_t GetBackgroundColorGIF(GifFileType* gif) { + const int transparent_index = GetTransparentIndexGIF(gif); + const ColorMapObject* const color_map = gif->SColorMap; + if (transparent_index != NO_TRANSPARENT_COLOR && + gif->SBackGroundColor == transparent_index) { + return 0x00000000; // Special case: transparent black. + } else if (color_map == NULL || color_map->Colors == NULL + || gif->SBackGroundColor >= color_map->ColorCount) { + return 0xffffffff; // Invalid: assume white. + } else { + const GifColorType color = color_map->Colors[gif->SBackGroundColor]; + return (0xffu << 24) | + (color.Red << 16) | + (color.Green << 8) | + (color.Blue << 0); + } +} + +// Find appropriate app extension and get loop count from the next extension. +// We use Chrome's interpretation of the 'loop_count' semantics: +// if not present -> loop once +// if present and loop_count == 0, return 0 ('infinite'). +// if present and loop_count != 0, it's the number of *extra* loops +// so we need to return loop_count + 1 as total loop number. +static uint32_t GetLoopCountGIF(const GifFileType* const gif) { + int i; + for (i = 0; i < gif->ImageCount; ++i) { + const SavedImage* const image = &gif->SavedImages[i]; + int j; + for (j = 0; (j + 1) < image->ExtensionBlockCount; ++j) { + const ExtensionBlock* const eb1 = image->ExtensionBlocks + j; + const ExtensionBlock* const eb2 = image->ExtensionBlocks + j + 1; + const char* const signature = (const char*)eb1->Bytes; + const int signature_is_ok = + (eb1->Function == APPLICATION_EXT_FUNC_CODE) && + (eb1->ByteCount == 11) && + (!memcmp(signature, "NETSCAPE2.0", 11) || + !memcmp(signature, "ANIMEXTS1.0", 11)); + if (signature_is_ok && + eb2->Function == CONTINUE_EXT_FUNC_CODE && eb2->ByteCount >= 3 && + eb2->Bytes[0] == 1) { + const uint32_t extra_loop = ((uint32_t)(eb2->Bytes[2]) << 8) + + ((uint32_t)(eb2->Bytes[1]) << 0); + return (extra_loop > 0) ? extra_loop + 1 : 0; + } + } + } + return 1; // Default. +} + +// Get duration of 'n'th frame in milliseconds. +static int GetFrameDurationGIF(GifFileType* gif, int n) { + GraphicsControlBlock gcb; + memset(&gcb, 0, sizeof(gcb)); + DGifSavedExtensionToGCB(gif, n, &gcb); + return gcb.DelayTime * 10; +} + +// Returns true if frame 'target' completely covers 'covered'. +static int CoversFrameGIF(const GifImageDesc* const target, + const GifImageDesc* const covered) { + return target->Left <= covered->Left && + covered->Left + covered->Width <= target->Left + target->Width && + target->Top <= covered->Top && + covered->Top + covered->Height <= target->Top + target->Height; +} + +static void RemapPixelsGIF(const uint8_t* const src, + const ColorMapObject* const cmap, + int transparent_color, int len, uint8_t* dst) { + int i; + for (i = 0; i < len; ++i) { + if (src[i] != transparent_color) { + // If a pixel in the current frame is transparent, we don't modify it, so + // that we can see-through the corresponding pixel from an earlier frame. + const GifColorType c = cmap->Colors[src[i]]; + dst[4 * i + 0] = c.Red; + dst[4 * i + 1] = c.Green; + dst[4 * i + 2] = c.Blue; + dst[4 * i + 3] = 0xff; + } + } +} + +static int ReadFrameGIF(const SavedImage* const gif_image, + const ColorMapObject* cmap, int transparent_color, + int out_stride, uint8_t* const dst) { + const GifImageDesc* image_desc = &gif_image->ImageDesc; + const uint8_t* in; + uint8_t* out; + int j; + + if (image_desc->ColorMap) cmap = image_desc->ColorMap; + + if (cmap == NULL || cmap->ColorCount != (1 << cmap->BitsPerPixel)) { + fprintf(stderr, "Potentially corrupt color map.\n"); + return 0; + } + + in = (const uint8_t*)gif_image->RasterBits; + out = dst + image_desc->Top * out_stride + image_desc->Left * kNumChannels; + + for (j = 0; j < image_desc->Height; ++j) { + RemapPixelsGIF(in, cmap, transparent_color, image_desc->Width, out); + in += image_desc->Width; + out += out_stride; + } + return 1; +} + +// Read animated GIF bitstream from 'filename' into 'AnimatedImage' struct. +static int ReadAnimatedGIF(const char filename[], AnimatedImage* const image, + int dump_frames, const char dump_folder[]) { + uint32_t frame_count; + uint32_t canvas_width, canvas_height; + uint32_t i; + int gif_error; + GifFileType* gif; + + gif = DGifOpenFileUnicode((const W_CHAR*)filename, NULL); + if (gif == NULL) { + WFPRINTF(stderr, "Could not read file: %s.\n", (const W_CHAR*)filename); + return 0; + } + + gif_error = DGifSlurp(gif); + if (gif_error != GIF_OK) { + WFPRINTF(stderr, "Could not parse image: %s.\n", (const W_CHAR*)filename); + GIFDisplayError(gif, gif_error); + DGifCloseFile(gif, NULL); + return 0; + } + + // Animation properties. + image->canvas_width = (uint32_t)gif->SWidth; + image->canvas_height = (uint32_t)gif->SHeight; + if (image->canvas_width > MAX_CANVAS_SIZE || + image->canvas_height > MAX_CANVAS_SIZE) { + fprintf(stderr, "Invalid canvas dimension: %d x %d\n", + image->canvas_width, image->canvas_height); + DGifCloseFile(gif, NULL); + return 0; + } + image->loop_count = GetLoopCountGIF(gif); + image->bgcolor = GetBackgroundColorGIF(gif); + + frame_count = (uint32_t)gif->ImageCount; + if (frame_count == 0) { + DGifCloseFile(gif, NULL); + return 0; + } + + if (image->canvas_width == 0 || image->canvas_height == 0) { + image->canvas_width = gif->SavedImages[0].ImageDesc.Width; + image->canvas_height = gif->SavedImages[0].ImageDesc.Height; + gif->SavedImages[0].ImageDesc.Left = 0; + gif->SavedImages[0].ImageDesc.Top = 0; + if (image->canvas_width == 0 || image->canvas_height == 0) { + fprintf(stderr, "Invalid canvas size in GIF.\n"); + DGifCloseFile(gif, NULL); + return 0; + } + } + // Allocate frames. + if (!AllocateFrames(image, frame_count)) { + DGifCloseFile(gif, NULL); + return 0; + } + + canvas_width = image->canvas_width; + canvas_height = image->canvas_height; + + // Decode and reconstruct frames. + for (i = 0; i < frame_count; ++i) { + const int canvas_width_in_bytes = canvas_width * kNumChannels; + const SavedImage* const curr_gif_image = &gif->SavedImages[i]; + GraphicsControlBlock curr_gcb; + DecodedFrame* curr_frame; + uint8_t* curr_rgba; + + memset(&curr_gcb, 0, sizeof(curr_gcb)); + DGifSavedExtensionToGCB(gif, i, &curr_gcb); + + curr_frame = &image->frames[i]; + curr_rgba = curr_frame->rgba; + curr_frame->duration = GetFrameDurationGIF(gif, i); + // Force frames with a small or no duration to 100ms to be consistent + // with web browsers and other transcoding tools (like gif2webp itself). + if (curr_frame->duration <= 10) curr_frame->duration = 100; + + if (i == 0) { // Initialize as transparent. + curr_frame->is_key_frame = 1; + ZeroFillCanvas(curr_rgba, canvas_width, canvas_height); + } else { + DecodedFrame* const prev_frame = &image->frames[i - 1]; + const GifImageDesc* const prev_desc = &gif->SavedImages[i - 1].ImageDesc; + GraphicsControlBlock prev_gcb; + memset(&prev_gcb, 0, sizeof(prev_gcb)); + DGifSavedExtensionToGCB(gif, i - 1, &prev_gcb); + + curr_frame->is_key_frame = + IsKeyFrameGIF(prev_desc, prev_gcb.DisposalMode, prev_frame, + canvas_width, canvas_height); + + if (curr_frame->is_key_frame) { // Initialize as transparent. + ZeroFillCanvas(curr_rgba, canvas_width, canvas_height); + } else { + int prev_frame_disposed, curr_frame_opaque; + int prev_frame_completely_covered; + // Initialize with previous canvas. + uint8_t* const prev_rgba = image->frames[i - 1].rgba; + CopyCanvas(prev_rgba, curr_rgba, canvas_width, canvas_height); + + // Dispose previous frame rectangle. + prev_frame_disposed = + (prev_gcb.DisposalMode == DISPOSE_BACKGROUND || + prev_gcb.DisposalMode == DISPOSE_PREVIOUS); + curr_frame_opaque = + (curr_gcb.TransparentColor == NO_TRANSPARENT_COLOR); + prev_frame_completely_covered = + curr_frame_opaque && + CoversFrameGIF(&curr_gif_image->ImageDesc, prev_desc); + + if (prev_frame_disposed && !prev_frame_completely_covered) { + switch (prev_gcb.DisposalMode) { + case DISPOSE_BACKGROUND: { + ZeroFillFrameRect(curr_rgba, canvas_width_in_bytes, + prev_desc->Left, prev_desc->Top, + prev_desc->Width, prev_desc->Height); + break; + } + case DISPOSE_PREVIOUS: { + int src_frame_num = i - 2; + while (src_frame_num >= 0) { + GraphicsControlBlock src_frame_gcb; + memset(&src_frame_gcb, 0, sizeof(src_frame_gcb)); + DGifSavedExtensionToGCB(gif, src_frame_num, &src_frame_gcb); + if (src_frame_gcb.DisposalMode != DISPOSE_PREVIOUS) break; + --src_frame_num; + } + if (src_frame_num >= 0) { + // Restore pixels inside previous frame rectangle to + // corresponding pixels in source canvas. + uint8_t* const src_frame_rgba = + image->frames[src_frame_num].rgba; + CopyFrameRectangle(src_frame_rgba, curr_rgba, + canvas_width_in_bytes, + prev_desc->Left, prev_desc->Top, + prev_desc->Width, prev_desc->Height); + } else { + // Source canvas doesn't exist. So clear previous frame + // rectangle to background. + ZeroFillFrameRect(curr_rgba, canvas_width_in_bytes, + prev_desc->Left, prev_desc->Top, + prev_desc->Width, prev_desc->Height); + } + break; + } + default: + break; // Nothing to do. + } + } + } + } + + // Decode current frame. + if (!ReadFrameGIF(curr_gif_image, gif->SColorMap, curr_gcb.TransparentColor, + canvas_width_in_bytes, curr_rgba)) { + DGifCloseFile(gif, NULL); + return 0; + } + + if (dump_frames) { + if (!DumpFrame(filename, dump_folder, i, curr_rgba, + canvas_width, canvas_height)) { + DGifCloseFile(gif, NULL); + return 0; + } + } + } + image->format = ANIM_GIF; + DGifCloseFile(gif, NULL); + return 1; +} + +#else + +static int IsGIF(const WebPData* const data) { + (void)data; + return 0; +} + +static int ReadAnimatedGIF(const char filename[], AnimatedImage* const image, + int dump_frames, const char dump_folder[]) { + (void)filename; + (void)image; + (void)dump_frames; + (void)dump_folder; + fprintf(stderr, "GIF support not compiled. Please install the libgif-dev " + "package before building.\n"); + return 0; +} + +#endif // WEBP_HAVE_GIF + +// ----------------------------------------------------------------------------- + +int ReadAnimatedImage(const char filename[], AnimatedImage* const image, + int dump_frames, const char dump_folder[]) { + int ok = 0; + WebPData webp_data; + + WebPDataInit(&webp_data); + memset(image, 0, sizeof(*image)); + + if (!ImgIoUtilReadFile(filename, &webp_data.bytes, &webp_data.size)) { + WFPRINTF(stderr, "Error reading file: %s\n", (const W_CHAR*)filename); + return 0; + } + + if (IsWebP(&webp_data)) { + ok = ReadAnimatedWebP(filename, &webp_data, image, dump_frames, + dump_folder); + } else if (IsGIF(&webp_data)) { + ok = ReadAnimatedGIF(filename, image, dump_frames, dump_folder); + } else { + WFPRINTF(stderr, + "Unknown file type: %s. Supported file types are WebP and GIF\n", + (const W_CHAR*)filename); + ok = 0; + } + if (!ok) ClearAnimatedImage(image); + WebPDataClear(&webp_data); + return ok; +} + +static void Accumulate(double v1, double v2, double* const max_diff, + double* const sse) { + const double diff = fabs(v1 - v2); + if (diff > *max_diff) *max_diff = diff; + *sse += diff * diff; +} + +void GetDiffAndPSNR(const uint8_t rgba1[], const uint8_t rgba2[], + uint32_t width, uint32_t height, int premultiply, + int* const max_diff, double* const psnr) { + const uint32_t stride = width * kNumChannels; + const int kAlphaChannel = kNumChannels - 1; + double f_max_diff = 0.; + double sse = 0.; + uint32_t x, y; + for (y = 0; y < height; ++y) { + for (x = 0; x < stride; x += kNumChannels) { + int k; + const size_t offset = (size_t)y * stride + x; + const int alpha1 = rgba1[offset + kAlphaChannel]; + const int alpha2 = rgba2[offset + kAlphaChannel]; + Accumulate(alpha1, alpha2, &f_max_diff, &sse); + if (!premultiply) { + for (k = 0; k < kAlphaChannel; ++k) { + Accumulate(rgba1[offset + k], rgba2[offset + k], &f_max_diff, &sse); + } + } else { + // premultiply R/G/B channels with alpha value + for (k = 0; k < kAlphaChannel; ++k) { + Accumulate(rgba1[offset + k] * alpha1 / 255., + rgba2[offset + k] * alpha2 / 255., + &f_max_diff, &sse); + } + } + } + } + *max_diff = (int)f_max_diff; + if (*max_diff == 0) { + *psnr = 99.; // PSNR when images are identical. + } else { + sse /= stride * height; + *psnr = 4.3429448 * log(255. * 255. / sse); + } +} + +void GetAnimatedImageVersions(int* const decoder_version, + int* const demux_version) { + *decoder_version = WebPGetDecoderVersion(); + *demux_version = WebPGetDemuxVersion(); +} diff --git a/third-party/webp/libwebp/examples/anim_util.h b/third-party/webp/libwebp/examples/anim_util.h new file mode 100644 index 0000000000..574e032d9e --- /dev/null +++ b/third-party/webp/libwebp/examples/anim_util.h @@ -0,0 +1,73 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Utilities for animated images + +#ifndef WEBP_EXAMPLES_ANIM_UTIL_H_ +#define WEBP_EXAMPLES_ANIM_UTIL_H_ + +#ifdef HAVE_CONFIG_H +#include "webp/config.h" +#endif + +#include "webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + ANIM_GIF, + ANIM_WEBP +} AnimatedFileFormat; + +typedef struct { + uint8_t* rgba; // Decoded and reconstructed full frame. + int duration; // Frame duration in milliseconds. + int is_key_frame; // True if this frame is a key-frame. +} DecodedFrame; + +typedef struct { + AnimatedFileFormat format; + uint32_t canvas_width; + uint32_t canvas_height; + uint32_t bgcolor; + uint32_t loop_count; + DecodedFrame* frames; + uint32_t num_frames; + void* raw_mem; +} AnimatedImage; + +// Deallocate everything in 'image' (but not the object itself). +void ClearAnimatedImage(AnimatedImage* const image); + +// Read animated image file into 'AnimatedImage' struct. +// If 'dump_frames' is true, dump frames to 'dump_folder'. +// Previous content of 'image' is obliterated. +// Upon successful return, content of 'image' must be deleted by +// calling 'ClearAnimatedImage'. +int ReadAnimatedImage(const char filename[], AnimatedImage* const image, + int dump_frames, const char dump_folder[]); + +// Given two RGBA buffers, calculate max pixel difference and PSNR. +// If 'premultiply' is true, R/G/B values will be pre-multiplied by the +// transparency before comparison. +void GetDiffAndPSNR(const uint8_t rgba1[], const uint8_t rgba2[], + uint32_t width, uint32_t height, int premultiply, + int* const max_diff, double* const psnr); + +// Return library versions used by anim_util. +void GetAnimatedImageVersions(int* const decoder_version, + int* const demux_version); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_EXAMPLES_ANIM_UTIL_H_ diff --git a/third-party/webp/libwebp/examples/cwebp.c b/third-party/webp/libwebp/examples/cwebp.c new file mode 100644 index 0000000000..cab70054e5 --- /dev/null +++ b/third-party/webp/libwebp/examples/cwebp.c @@ -0,0 +1,1249 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// simple command line calling the WebPEncode function. +// Encodes a raw .YUV into WebP bitstream +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include "webp/config.h" +#endif + +#include "../examples/example_util.h" +#include "../imageio/image_dec.h" +#include "../imageio/imageio_util.h" +#include "../imageio/webpdec.h" +#include "./stopwatch.h" +#include "./unicode.h" +#include "sharpyuv/sharpyuv.h" +#include "webp/encode.h" + +#ifndef WEBP_DLL +#ifdef __cplusplus +extern "C" { +#endif + +extern void* VP8GetCPUInfo; // opaque forward declaration. + +#ifdef __cplusplus +} // extern "C" +#endif +#endif // WEBP_DLL + +//------------------------------------------------------------------------------ + +static int verbose = 0; + +static int ReadYUV(const uint8_t* const data, size_t data_size, + WebPPicture* const pic) { + const int use_argb = pic->use_argb; + const int uv_width = (pic->width + 1) / 2; + const int uv_height = (pic->height + 1) / 2; + const int y_plane_size = pic->width * pic->height; + const int uv_plane_size = uv_width * uv_height; + const size_t expected_data_size = y_plane_size + 2 * uv_plane_size; + + if (data_size != expected_data_size) { + fprintf(stderr, + "input data doesn't have the expected size (%d instead of %d)\n", + (int)data_size, (int)expected_data_size); + return 0; + } + + pic->use_argb = 0; + if (!WebPPictureAlloc(pic)) return 0; + ImgIoUtilCopyPlane(data, pic->width, pic->y, pic->y_stride, + pic->width, pic->height); + ImgIoUtilCopyPlane(data + y_plane_size, uv_width, + pic->u, pic->uv_stride, uv_width, uv_height); + ImgIoUtilCopyPlane(data + y_plane_size + uv_plane_size, uv_width, + pic->v, pic->uv_stride, uv_width, uv_height); + return use_argb ? WebPPictureYUVAToARGB(pic) : 1; +} + +#ifdef HAVE_WINCODEC_H + +static int ReadPicture(const char* const filename, WebPPicture* const pic, + int keep_alpha, Metadata* const metadata) { + int ok = 0; + const uint8_t* data = NULL; + size_t data_size = 0; + if (pic->width != 0 && pic->height != 0) { + ok = ImgIoUtilReadFile(filename, &data, &data_size); + ok = ok && ReadYUV(data, data_size, pic); + } else { + // If no size specified, try to decode it using WIC. + ok = ReadPictureWithWIC(filename, pic, keep_alpha, metadata); + if (!ok) { + ok = ImgIoUtilReadFile(filename, &data, &data_size); + ok = ok && ReadWebP(data, data_size, pic, keep_alpha, metadata); + } + } + if (!ok) { + WFPRINTF(stderr, "Error! Could not process file %s\n", + (const W_CHAR*)filename); + } + WebPFree((void*)data); + return ok; +} + +#else // !HAVE_WINCODEC_H + +static int ReadPicture(const char* const filename, WebPPicture* const pic, + int keep_alpha, Metadata* const metadata) { + const uint8_t* data = NULL; + size_t data_size = 0; + int ok = 0; + + ok = ImgIoUtilReadFile(filename, &data, &data_size); + if (!ok) goto End; + + if (pic->width == 0 || pic->height == 0) { + WebPImageReader reader = WebPGuessImageReader(data, data_size); + ok = reader(data, data_size, pic, keep_alpha, metadata); + } else { + // If image size is specified, infer it as YUV format. + ok = ReadYUV(data, data_size, pic); + } + End: + if (!ok) { + WFPRINTF(stderr, "Error! Could not process file %s\n", + (const W_CHAR*)filename); + } + WebPFree((void*)data); + return ok; +} + +#endif // !HAVE_WINCODEC_H + +static void AllocExtraInfo(WebPPicture* const pic) { + const int mb_w = (pic->width + 15) / 16; + const int mb_h = (pic->height + 15) / 16; + pic->extra_info = + (uint8_t*)WebPMalloc(mb_w * mb_h * sizeof(*pic->extra_info)); +} + +static void PrintByteCount(const int bytes[4], int total_size, + int* const totals) { + int s; + int total = 0; + for (s = 0; s < 4; ++s) { + fprintf(stderr, "| %7d ", bytes[s]); + total += bytes[s]; + if (totals) totals[s] += bytes[s]; + } + fprintf(stderr, "| %7d (%.1f%%)\n", total, 100.f * total / total_size); +} + +static void PrintPercents(const int counts[4]) { + int s; + const int total = counts[0] + counts[1] + counts[2] + counts[3]; + for (s = 0; s < 4; ++s) { + fprintf(stderr, "| %3d%%", (int)(100. * counts[s] / total + .5)); + } + fprintf(stderr, "| %7d\n", total); +} + +static void PrintValues(const int values[4]) { + int s; + for (s = 0; s < 4; ++s) { + fprintf(stderr, "| %7d ", values[s]); + } + fprintf(stderr, "|\n"); +} + +static void PrintFullLosslessInfo(const WebPAuxStats* const stats, + const char* const description) { + fprintf(stderr, "Lossless-%s compressed size: %d bytes\n", + description, stats->lossless_size); + fprintf(stderr, " * Header size: %d bytes, image data size: %d\n", + stats->lossless_hdr_size, stats->lossless_data_size); + if (stats->lossless_features) { + fprintf(stderr, " * Lossless features used:"); + if (stats->lossless_features & 1) fprintf(stderr, " PREDICTION"); + if (stats->lossless_features & 2) fprintf(stderr, " CROSS-COLOR-TRANSFORM"); + if (stats->lossless_features & 4) fprintf(stderr, " SUBTRACT-GREEN"); + if (stats->lossless_features & 8) fprintf(stderr, " PALETTE"); + fprintf(stderr, "\n"); + } + fprintf(stderr, " * Precision Bits: histogram=%d transform=%d cache=%d\n", + stats->histogram_bits, stats->transform_bits, stats->cache_bits); + if (stats->palette_size > 0) { + fprintf(stderr, " * Palette size: %d\n", stats->palette_size); + } +} + +static void PrintExtraInfoLossless(const WebPPicture* const pic, + int short_output, + const char* const file_name) { + const WebPAuxStats* const stats = pic->stats; + if (short_output) { + fprintf(stderr, "%7d %2.2f\n", stats->coded_size, stats->PSNR[3]); + } else { + WFPRINTF(stderr, "File: %s\n", (const W_CHAR*)file_name); + fprintf(stderr, "Dimension: %d x %d\n", pic->width, pic->height); + fprintf(stderr, "Output: %d bytes (%.2f bpp)\n", stats->coded_size, + 8.f * stats->coded_size / pic->width / pic->height); + PrintFullLosslessInfo(stats, "ARGB"); + } +} + +static void PrintExtraInfoLossy(const WebPPicture* const pic, int short_output, + int full_details, + const char* const file_name) { + const WebPAuxStats* const stats = pic->stats; + if (short_output) { + fprintf(stderr, "%7d %2.2f\n", stats->coded_size, stats->PSNR[3]); + } else { + const int num_i4 = stats->block_count[0]; + const int num_i16 = stats->block_count[1]; + const int num_skip = stats->block_count[2]; + const int total = num_i4 + num_i16; + WFPRINTF(stderr, "File: %s\n", (const W_CHAR*)file_name); + fprintf(stderr, "Dimension: %d x %d%s\n", + pic->width, pic->height, + stats->alpha_data_size ? " (with alpha)" : ""); + fprintf(stderr, "Output: " + "%d bytes Y-U-V-All-PSNR %2.2f %2.2f %2.2f %2.2f dB\n" + " (%.2f bpp)\n", + stats->coded_size, + stats->PSNR[0], stats->PSNR[1], stats->PSNR[2], stats->PSNR[3], + 8.f * stats->coded_size / pic->width / pic->height); + if (total > 0) { + int totals[4] = { 0, 0, 0, 0 }; + fprintf(stderr, "block count: intra4: %6d (%.2f%%)\n" + " intra16: %6d (%.2f%%)\n" + " skipped: %6d (%.2f%%)\n", + num_i4, 100.f * num_i4 / total, + num_i16, 100.f * num_i16 / total, + num_skip, 100.f * num_skip / total); + fprintf(stderr, "bytes used: header: %6d (%.1f%%)\n" + " mode-partition: %6d (%.1f%%)\n", + stats->header_bytes[0], + 100.f * stats->header_bytes[0] / stats->coded_size, + stats->header_bytes[1], + 100.f * stats->header_bytes[1] / stats->coded_size); + if (stats->alpha_data_size > 0) { + fprintf(stderr, " transparency: %6d (%.1f dB)\n", + stats->alpha_data_size, stats->PSNR[4]); + } + fprintf(stderr, " Residuals bytes " + "|segment 1|segment 2|segment 3" + "|segment 4| total\n"); + if (full_details) { + fprintf(stderr, " intra4-coeffs: "); + PrintByteCount(stats->residual_bytes[0], stats->coded_size, totals); + fprintf(stderr, " intra16-coeffs: "); + PrintByteCount(stats->residual_bytes[1], stats->coded_size, totals); + fprintf(stderr, " chroma coeffs: "); + PrintByteCount(stats->residual_bytes[2], stats->coded_size, totals); + } + fprintf(stderr, " macroblocks: "); + PrintPercents(stats->segment_size); + fprintf(stderr, " quantizer: "); + PrintValues(stats->segment_quant); + fprintf(stderr, " filter level: "); + PrintValues(stats->segment_level); + if (full_details) { + fprintf(stderr, "------------------+---------"); + fprintf(stderr, "+---------+---------+---------+-----------------\n"); + fprintf(stderr, " segments total: "); + PrintByteCount(totals, stats->coded_size, NULL); + } + } + if (stats->lossless_size > 0) { + PrintFullLosslessInfo(stats, "alpha"); + } + } +} + +static void PrintMapInfo(const WebPPicture* const pic) { + if (pic->extra_info != NULL) { + const int mb_w = (pic->width + 15) / 16; + const int mb_h = (pic->height + 15) / 16; + const int type = pic->extra_info_type; + int x, y; + for (y = 0; y < mb_h; ++y) { + for (x = 0; x < mb_w; ++x) { + const int c = pic->extra_info[x + y * mb_w]; + if (type == 1) { // intra4/intra16 + fprintf(stderr, "%c", "+."[c]); + } else if (type == 2) { // segments + fprintf(stderr, "%c", ".-*X"[c]); + } else if (type == 3) { // quantizers + fprintf(stderr, "%.2d ", c); + } else if (type == 6 || type == 7) { + fprintf(stderr, "%3d ", c); + } else { + fprintf(stderr, "0x%.2x ", c); + } + } + fprintf(stderr, "\n"); + } + } +} + +//------------------------------------------------------------------------------ + +static int MyWriter(const uint8_t* data, size_t data_size, + const WebPPicture* const pic) { + FILE* const out = (FILE*)pic->custom_ptr; + return data_size ? (fwrite(data, data_size, 1, out) == 1) : 1; +} + +// Dumps a picture as a PGM file using the IMC4 layout. +static int DumpPicture(const WebPPicture* const picture, const char* PGM_name) { + int y; + int ok = 0; + const int uv_width = (picture->width + 1) / 2; + const int uv_height = (picture->height + 1) / 2; + const int stride = (picture->width + 1) & ~1; + const uint8_t* src_y = picture->y; + const uint8_t* src_u = picture->u; + const uint8_t* src_v = picture->v; + const uint8_t* src_a = picture->a; + const int alpha_height = + WebPPictureHasTransparency(picture) ? picture->height : 0; + const int height = picture->height + uv_height + alpha_height; + FILE* const f = WFOPEN(PGM_name, "wb"); + if (f == NULL) return 0; + fprintf(f, "P5\n%d %d\n255\n", stride, height); + for (y = 0; y < picture->height; ++y) { + if (fwrite(src_y, picture->width, 1, f) != 1) goto Error; + if (picture->width & 1) fputc(0, f); // pad + src_y += picture->y_stride; + } + for (y = 0; y < uv_height; ++y) { + if (fwrite(src_u, uv_width, 1, f) != 1) goto Error; + if (fwrite(src_v, uv_width, 1, f) != 1) goto Error; + src_u += picture->uv_stride; + src_v += picture->uv_stride; + } + for (y = 0; y < alpha_height; ++y) { + if (fwrite(src_a, picture->width, 1, f) != 1) goto Error; + if (picture->width & 1) fputc(0, f); // pad + src_a += picture->a_stride; + } + ok = 1; + + Error: + fclose(f); + return ok; +} + +// ----------------------------------------------------------------------------- +// Metadata writing. + +enum { + METADATA_EXIF = (1 << 0), + METADATA_ICC = (1 << 1), + METADATA_XMP = (1 << 2), + METADATA_ALL = METADATA_EXIF | METADATA_ICC | METADATA_XMP +}; + +static const int kChunkHeaderSize = 8; +static const int kTagSize = 4; + +static void PrintMetadataInfo(const Metadata* const metadata, + int metadata_written) { + if (metadata == NULL || metadata_written == 0) return; + + fprintf(stderr, "Metadata:\n"); + if (metadata_written & METADATA_ICC) { + fprintf(stderr, " * ICC profile: %6d bytes\n", (int)metadata->iccp.size); + } + if (metadata_written & METADATA_EXIF) { + fprintf(stderr, " * EXIF data: %6d bytes\n", (int)metadata->exif.size); + } + if (metadata_written & METADATA_XMP) { + fprintf(stderr, " * XMP data: %6d bytes\n", (int)metadata->xmp.size); + } +} + +// Outputs, in little endian, 'num' bytes from 'val' to 'out'. +static int WriteLE(FILE* const out, uint32_t val, int num) { + uint8_t buf[4]; + int i; + for (i = 0; i < num; ++i) { + buf[i] = (uint8_t)(val & 0xff); + val >>= 8; + } + return (fwrite(buf, num, 1, out) == 1); +} + +static int WriteLE24(FILE* const out, uint32_t val) { + return WriteLE(out, val, 3); +} + +static int WriteLE32(FILE* const out, uint32_t val) { + return WriteLE(out, val, 4); +} + +static int WriteMetadataChunk(FILE* const out, const char fourcc[4], + const MetadataPayload* const payload) { + const uint8_t zero = 0; + const size_t need_padding = payload->size & 1; + int ok = (fwrite(fourcc, kTagSize, 1, out) == 1); + ok = ok && WriteLE32(out, (uint32_t)payload->size); + ok = ok && (fwrite(payload->bytes, payload->size, 1, out) == 1); + return ok && (fwrite(&zero, need_padding, need_padding, out) == need_padding); +} + +// Sets 'flag' in 'vp8x_flags' and updates 'metadata_size' with the size of the +// chunk if there is metadata and 'keep' is true. +static int UpdateFlagsAndSize(const MetadataPayload* const payload, + int keep, int flag, + uint32_t* vp8x_flags, uint64_t* metadata_size) { + if (keep && payload->bytes != NULL && payload->size > 0) { + *vp8x_flags |= flag; + *metadata_size += kChunkHeaderSize + payload->size + (payload->size & 1); + return 1; + } + return 0; +} + +// Writes a WebP file using the image contained in 'memory_writer' and the +// metadata from 'metadata'. Metadata is controlled by 'keep_metadata' and the +// availability in 'metadata'. Returns true on success. +// For details see doc/webp-container-spec.txt#extended-file-format. +static int WriteWebPWithMetadata(FILE* const out, + const WebPPicture* const picture, + const WebPMemoryWriter* const memory_writer, + const Metadata* const metadata, + int keep_metadata, + int* const metadata_written) { + const char kVP8XHeader[] = "VP8X\x0a\x00\x00\x00"; + const int kAlphaFlag = 0x10; + const int kEXIFFlag = 0x08; + const int kICCPFlag = 0x20; + const int kXMPFlag = 0x04; + const size_t kRiffHeaderSize = 12; + const size_t kMaxChunkPayload = ~0 - kChunkHeaderSize - 1; + const size_t kMinSize = kRiffHeaderSize + kChunkHeaderSize; + uint32_t flags = 0; + uint64_t metadata_size = 0; + const int write_exif = UpdateFlagsAndSize(&metadata->exif, + !!(keep_metadata & METADATA_EXIF), + kEXIFFlag, &flags, &metadata_size); + const int write_iccp = UpdateFlagsAndSize(&metadata->iccp, + !!(keep_metadata & METADATA_ICC), + kICCPFlag, &flags, &metadata_size); + const int write_xmp = UpdateFlagsAndSize(&metadata->xmp, + !!(keep_metadata & METADATA_XMP), + kXMPFlag, &flags, &metadata_size); + uint8_t* webp = memory_writer->mem; + size_t webp_size = memory_writer->size; + + *metadata_written = 0; + + if (webp_size < kMinSize) return 0; + if (webp_size - kChunkHeaderSize + metadata_size > kMaxChunkPayload) { + fprintf(stderr, "Error! Addition of metadata would exceed " + "container size limit.\n"); + return 0; + } + + if (metadata_size > 0) { + const int kVP8XChunkSize = 18; + const int has_vp8x = !memcmp(webp + kRiffHeaderSize, "VP8X", kTagSize); + const uint32_t riff_size = (uint32_t)(webp_size - kChunkHeaderSize + + (has_vp8x ? 0 : kVP8XChunkSize) + + metadata_size); + // RIFF + int ok = (fwrite(webp, kTagSize, 1, out) == 1); + // RIFF size (file header size is not recorded) + ok = ok && WriteLE32(out, riff_size); + webp += kChunkHeaderSize; + webp_size -= kChunkHeaderSize; + // WEBP + ok = ok && (fwrite(webp, kTagSize, 1, out) == 1); + webp += kTagSize; + webp_size -= kTagSize; + if (has_vp8x) { // update the existing VP8X flags + webp[kChunkHeaderSize] |= (uint8_t)(flags & 0xff); + ok = ok && (fwrite(webp, kVP8XChunkSize, 1, out) == 1); + webp += kVP8XChunkSize; + webp_size -= kVP8XChunkSize; + } else { + const int is_lossless = !memcmp(webp, "VP8L", kTagSize); + if (is_lossless) { + // Presence of alpha is stored in the 37th bit (29th after the + // signature) of VP8L data. + if (webp[kChunkHeaderSize + 4] & (1 << 4)) flags |= kAlphaFlag; + } + ok = ok && (fwrite(kVP8XHeader, kChunkHeaderSize, 1, out) == 1); + ok = ok && WriteLE32(out, flags); + ok = ok && WriteLE24(out, picture->width - 1); + ok = ok && WriteLE24(out, picture->height - 1); + } + if (write_iccp) { + ok = ok && WriteMetadataChunk(out, "ICCP", &metadata->iccp); + *metadata_written |= METADATA_ICC; + } + // Image + ok = ok && (fwrite(webp, webp_size, 1, out) == 1); + if (write_exif) { + ok = ok && WriteMetadataChunk(out, "EXIF", &metadata->exif); + *metadata_written |= METADATA_EXIF; + } + if (write_xmp) { + ok = ok && WriteMetadataChunk(out, "XMP ", &metadata->xmp); + *metadata_written |= METADATA_XMP; + } + return ok; + } + + // No metadata, just write the original image file. + return (fwrite(webp, webp_size, 1, out) == 1); +} + +//------------------------------------------------------------------------------ + +static int ProgressReport(int percent, const WebPPicture* const picture) { + fprintf(stderr, "[%s]: %3d %% \r", + (char*)picture->user_data, percent); + return 1; // all ok +} + +//------------------------------------------------------------------------------ + +static void HelpShort(void) { + printf("Usage:\n\n"); + printf(" cwebp [options] -q quality input.png -o output.webp\n\n"); + printf("where quality is between 0 (poor) to 100 (very good).\n"); + printf("Typical value is around 80.\n\n"); + printf("Try -longhelp for an exhaustive list of advanced options.\n"); +} + +static void HelpLong(void) { + printf("Usage:\n"); + printf(" cwebp [-preset <...>] [options] in_file [-o out_file]\n\n"); + printf("If input size (-s) for an image is not specified, it is\n" + "assumed to be a PNG, JPEG, TIFF or WebP file.\n"); + printf("Note: Animated PNG and WebP files are not supported.\n"); +#ifdef HAVE_WINCODEC_H + printf("Windows builds can take as input any of the files handled by WIC.\n"); +#endif + printf("\nOptions:\n"); + printf(" -h / -help ............. short help\n"); + printf(" -H / -longhelp ......... long help\n"); + printf(" -q ............. quality factor (0:small..100:big), " + "default=75\n"); + printf(" -alpha_q ......... transparency-compression quality (0..100)," + "\n default=100\n"); + printf(" -preset ....... preset setting, one of:\n"); + printf(" default, photo, picture,\n"); + printf(" drawing, icon, text\n"); + printf(" -preset must come first, as it overwrites other parameters\n"); + printf(" -z ............... activates lossless preset with given\n" + " level in [0:fast, ..., 9:slowest]\n"); + printf("\n"); + printf(" -m ............... compression method (0=fast, 6=slowest), " + "default=4\n"); + printf(" -segments ........ number of segments to use (1..4), " + "default=4\n"); + printf(" -size ............ target size (in bytes)\n"); + printf(" -psnr .......... target PSNR (in dB. typically: 42)\n"); + printf("\n"); + printf(" -s ......... input size (width x height) for YUV\n"); + printf(" -sns ............. spatial noise shaping (0:off, 100:max), " + "default=50\n"); + printf(" -f ............... filter strength (0=off..100), " + "default=60\n"); + printf(" -sharpness ....... " + "filter sharpness (0:most .. 7:least sharp), default=0\n"); + printf(" -strong ................ use strong filter instead " + "of simple (default)\n"); + printf(" -nostrong .............. use simple filter instead of strong\n"); + printf(" -sharp_yuv ............. use sharper (and slower) RGB->YUV " + "conversion\n"); + printf(" -partition_limit . limit quality to fit the 512k limit on\n"); + printf(" " + "the first partition (0=no degradation ... 100=full)\n"); + printf(" -pass ............ analysis pass number (1..10)\n"); + printf(" -qrange .... specifies the permissible quality range\n" + " (default: 0 100)\n"); + printf(" -crop .. crop picture with the given rectangle\n"); + printf(" -resize ........ resize picture (*after* any cropping)\n"); + printf(" -mt .................... use multi-threading if available\n"); + printf(" -low_memory ............ reduce memory usage (slower encoding)\n"); + printf(" -map ............. print map of extra info\n"); + printf(" -print_psnr ............ prints averaged PSNR distortion\n"); + printf(" -print_ssim ............ prints averaged SSIM distortion\n"); + printf(" -print_lsim ............ prints local-similarity distortion\n"); + printf(" -d .......... dump the compressed output (PGM file)\n"); + printf(" -alpha_method .... transparency-compression method (0..1), " + "default=1\n"); + printf(" -alpha_filter . predictive filtering for alpha plane,\n"); + printf(" one of: none, fast (default) or best\n"); + printf(" -exact ................. preserve RGB values in transparent area, " + "default=off\n"); + printf(" -blend_alpha ..... blend colors against background color\n" + " expressed as RGB values written in\n" + " hexadecimal, e.g. 0xc0e0d0 for red=0xc0\n" + " green=0xe0 and blue=0xd0\n"); + printf(" -noalpha ............... discard any transparency information\n"); + printf(" -lossless .............. encode image losslessly, default=off\n"); + printf(" -near_lossless ... use near-lossless image preprocessing\n" + " (0..100=off), default=100\n"); + printf(" -hint ......... specify image characteristics hint,\n"); + printf(" one of: photo, picture or graph\n"); + + printf("\n"); + printf(" -metadata ..... comma separated list of metadata to\n"); + printf(" "); + printf("copy from the input to the output if present.\n"); + printf(" " + "Valid values: all, none (default), exif, icc, xmp\n"); + + printf("\n"); + printf(" -short ................. condense printed message\n"); + printf(" -quiet ................. don't print anything\n"); + printf(" -version ............... print version number and exit\n"); +#ifndef WEBP_DLL + printf(" -noasm ................. disable all assembly optimizations\n"); +#endif + printf(" -v ..................... verbose, e.g. print encoding/decoding " + "times\n"); + printf(" -progress .............. report encoding progress\n"); + printf("\n"); + printf("Experimental Options:\n"); + printf(" -jpeg_like ............. roughly match expected JPEG size\n"); + printf(" -af .................... auto-adjust filter strength\n"); + printf(" -pre ............. pre-processing filter\n"); + printf("\n"); + printf("Supported input formats:\n %s\n", WebPGetEnabledInputFileFormats()); +} + +//------------------------------------------------------------------------------ +// Error messages + +static const char* const kErrorMessages[VP8_ENC_ERROR_LAST] = { + "OK", + "OUT_OF_MEMORY: Out of memory allocating objects", + "BITSTREAM_OUT_OF_MEMORY: Out of memory re-allocating byte buffer", + "NULL_PARAMETER: NULL parameter passed to function", + "INVALID_CONFIGURATION: configuration is invalid", + "BAD_DIMENSION: Bad picture dimension. Maximum width and height " + "allowed is 16383 pixels.", + "PARTITION0_OVERFLOW: Partition #0 is too big to fit 512k.\n" + "To reduce the size of this partition, try using less segments " + "with the -segments option, and eventually reduce the number of " + "header bits using -partition_limit. More details are available " + "in the manual (`man cwebp`)", + "PARTITION_OVERFLOW: Partition is too big to fit 16M", + "BAD_WRITE: Picture writer returned an I/O error", + "FILE_TOO_BIG: File would be too big to fit in 4G", + "USER_ABORT: encoding abort requested by user" +}; + +//------------------------------------------------------------------------------ + +int main(int argc, const char* argv[]) { + int return_value = -1; + const char* in_file = NULL, *out_file = NULL, *dump_file = NULL; + FILE* out = NULL; + int c; + int short_output = 0; + int quiet = 0; + int keep_alpha = 1; + int blend_alpha = 0; + uint32_t background_color = 0xffffffu; + int crop = 0, crop_x = 0, crop_y = 0, crop_w = 0, crop_h = 0; + int resize_w = 0, resize_h = 0; + int lossless_preset = 6; + int use_lossless_preset = -1; // -1=unset, 0=don't use, 1=use it + int show_progress = 0; + int keep_metadata = 0; + int metadata_written = 0; + WebPPicture picture; + int print_distortion = -1; // -1=off, 0=PSNR, 1=SSIM, 2=LSIM + WebPPicture original_picture; // when PSNR or SSIM is requested + WebPConfig config; + WebPAuxStats stats; + WebPMemoryWriter memory_writer; + int use_memory_writer; + Metadata metadata; + Stopwatch stop_watch; + + INIT_WARGV(argc, argv); + + MetadataInit(&metadata); + WebPMemoryWriterInit(&memory_writer); + if (!WebPPictureInit(&picture) || + !WebPPictureInit(&original_picture) || + !WebPConfigInit(&config)) { + fprintf(stderr, "Error! Version mismatch!\n"); + FREE_WARGV_AND_RETURN(-1); + } + + if (argc == 1) { + HelpShort(); + FREE_WARGV_AND_RETURN(0); + } + + for (c = 1; c < argc; ++c) { + int parse_error = 0; + if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) { + HelpShort(); + FREE_WARGV_AND_RETURN(0); + } else if (!strcmp(argv[c], "-H") || !strcmp(argv[c], "-longhelp")) { + HelpLong(); + FREE_WARGV_AND_RETURN(0); + } else if (!strcmp(argv[c], "-o") && c + 1 < argc) { + out_file = (const char*)GET_WARGV(argv, ++c); + } else if (!strcmp(argv[c], "-d") && c + 1 < argc) { + dump_file = (const char*)GET_WARGV(argv, ++c); + config.show_compressed = 1; + } else if (!strcmp(argv[c], "-print_psnr")) { + config.show_compressed = 1; + print_distortion = 0; + } else if (!strcmp(argv[c], "-print_ssim")) { + config.show_compressed = 1; + print_distortion = 1; + } else if (!strcmp(argv[c], "-print_lsim")) { + config.show_compressed = 1; + print_distortion = 2; + } else if (!strcmp(argv[c], "-short")) { + ++short_output; + } else if (!strcmp(argv[c], "-s") && c + 2 < argc) { + picture.width = ExUtilGetInt(argv[++c], 0, &parse_error); + picture.height = ExUtilGetInt(argv[++c], 0, &parse_error); + if (picture.width > WEBP_MAX_DIMENSION || picture.width < 0 || + picture.height > WEBP_MAX_DIMENSION || picture.height < 0) { + fprintf(stderr, + "Specified dimension (%d x %d) is out of range.\n", + picture.width, picture.height); + goto Error; + } + } else if (!strcmp(argv[c], "-m") && c + 1 < argc) { + config.method = ExUtilGetInt(argv[++c], 0, &parse_error); + use_lossless_preset = 0; // disable -z option + } else if (!strcmp(argv[c], "-q") && c + 1 < argc) { + config.quality = ExUtilGetFloat(argv[++c], &parse_error); + use_lossless_preset = 0; // disable -z option + } else if (!strcmp(argv[c], "-z") && c + 1 < argc) { + lossless_preset = ExUtilGetInt(argv[++c], 0, &parse_error); + if (use_lossless_preset != 0) use_lossless_preset = 1; + } else if (!strcmp(argv[c], "-alpha_q") && c + 1 < argc) { + config.alpha_quality = ExUtilGetInt(argv[++c], 0, &parse_error); + } else if (!strcmp(argv[c], "-alpha_method") && c + 1 < argc) { + config.alpha_compression = ExUtilGetInt(argv[++c], 0, &parse_error); + } else if (!strcmp(argv[c], "-alpha_cleanup")) { + // This flag is obsolete, does opposite of -exact. + config.exact = 0; + } else if (!strcmp(argv[c], "-exact")) { + config.exact = 1; + } else if (!strcmp(argv[c], "-blend_alpha") && c + 1 < argc) { + blend_alpha = 1; + // background color is given in hex with an optional '0x' prefix + background_color = ExUtilGetInt(argv[++c], 16, &parse_error); + background_color = background_color & 0x00ffffffu; + } else if (!strcmp(argv[c], "-alpha_filter") && c + 1 < argc) { + ++c; + if (!strcmp(argv[c], "none")) { + config.alpha_filtering = 0; + } else if (!strcmp(argv[c], "fast")) { + config.alpha_filtering = 1; + } else if (!strcmp(argv[c], "best")) { + config.alpha_filtering = 2; + } else { + fprintf(stderr, "Error! Unrecognized alpha filter: %s\n", argv[c]); + goto Error; + } + } else if (!strcmp(argv[c], "-noalpha")) { + keep_alpha = 0; + } else if (!strcmp(argv[c], "-lossless")) { + config.lossless = 1; + } else if (!strcmp(argv[c], "-near_lossless") && c + 1 < argc) { + config.near_lossless = ExUtilGetInt(argv[++c], 0, &parse_error); + config.lossless = 1; // use near-lossless only with lossless + } else if (!strcmp(argv[c], "-hint") && c + 1 < argc) { + ++c; + if (!strcmp(argv[c], "photo")) { + config.image_hint = WEBP_HINT_PHOTO; + } else if (!strcmp(argv[c], "picture")) { + config.image_hint = WEBP_HINT_PICTURE; + } else if (!strcmp(argv[c], "graph")) { + config.image_hint = WEBP_HINT_GRAPH; + } else { + fprintf(stderr, "Error! Unrecognized image hint: %s\n", argv[c]); + goto Error; + } + } else if (!strcmp(argv[c], "-size") && c + 1 < argc) { + config.target_size = ExUtilGetInt(argv[++c], 0, &parse_error); + } else if (!strcmp(argv[c], "-psnr") && c + 1 < argc) { + config.target_PSNR = ExUtilGetFloat(argv[++c], &parse_error); + } else if (!strcmp(argv[c], "-sns") && c + 1 < argc) { + config.sns_strength = ExUtilGetInt(argv[++c], 0, &parse_error); + } else if (!strcmp(argv[c], "-f") && c + 1 < argc) { + config.filter_strength = ExUtilGetInt(argv[++c], 0, &parse_error); + } else if (!strcmp(argv[c], "-af")) { + config.autofilter = 1; + } else if (!strcmp(argv[c], "-jpeg_like")) { + config.emulate_jpeg_size = 1; + } else if (!strcmp(argv[c], "-mt")) { + ++config.thread_level; // increase thread level + } else if (!strcmp(argv[c], "-low_memory")) { + config.low_memory = 1; + } else if (!strcmp(argv[c], "-strong")) { + config.filter_type = 1; + } else if (!strcmp(argv[c], "-nostrong")) { + config.filter_type = 0; + } else if (!strcmp(argv[c], "-sharpness") && c + 1 < argc) { + config.filter_sharpness = ExUtilGetInt(argv[++c], 0, &parse_error); + } else if (!strcmp(argv[c], "-sharp_yuv")) { + config.use_sharp_yuv = 1; + } else if (!strcmp(argv[c], "-pass") && c + 1 < argc) { + config.pass = ExUtilGetInt(argv[++c], 0, &parse_error); + } else if (!strcmp(argv[c], "-qrange") && c + 2 < argc) { + config.qmin = ExUtilGetInt(argv[++c], 0, &parse_error); + config.qmax = ExUtilGetInt(argv[++c], 0, &parse_error); + if (config.qmin < 0) config.qmin = 0; + if (config.qmax > 100) config.qmax = 100; + } else if (!strcmp(argv[c], "-pre") && c + 1 < argc) { + config.preprocessing = ExUtilGetInt(argv[++c], 0, &parse_error); + } else if (!strcmp(argv[c], "-segments") && c + 1 < argc) { + config.segments = ExUtilGetInt(argv[++c], 0, &parse_error); + } else if (!strcmp(argv[c], "-partition_limit") && c + 1 < argc) { + config.partition_limit = ExUtilGetInt(argv[++c], 0, &parse_error); + } else if (!strcmp(argv[c], "-map") && c + 1 < argc) { + picture.extra_info_type = ExUtilGetInt(argv[++c], 0, &parse_error); + } else if (!strcmp(argv[c], "-crop") && c + 4 < argc) { + crop = 1; + crop_x = ExUtilGetInt(argv[++c], 0, &parse_error); + crop_y = ExUtilGetInt(argv[++c], 0, &parse_error); + crop_w = ExUtilGetInt(argv[++c], 0, &parse_error); + crop_h = ExUtilGetInt(argv[++c], 0, &parse_error); + } else if (!strcmp(argv[c], "-resize") && c + 2 < argc) { + resize_w = ExUtilGetInt(argv[++c], 0, &parse_error); + resize_h = ExUtilGetInt(argv[++c], 0, &parse_error); +#ifndef WEBP_DLL + } else if (!strcmp(argv[c], "-noasm")) { + VP8GetCPUInfo = NULL; +#endif + } else if (!strcmp(argv[c], "-version")) { + const int version = WebPGetEncoderVersion(); + const int sharpyuv_version = SharpYuvGetVersion(); + printf("%d.%d.%d\n", + (version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff); + printf("libsharpyuv: %d.%d.%d\n", + (sharpyuv_version >> 24) & 0xff, (sharpyuv_version >> 16) & 0xffff, + sharpyuv_version & 0xff); + FREE_WARGV_AND_RETURN(0); + } else if (!strcmp(argv[c], "-progress")) { + show_progress = 1; + } else if (!strcmp(argv[c], "-quiet")) { + quiet = 1; + } else if (!strcmp(argv[c], "-preset") && c + 1 < argc) { + WebPPreset preset; + ++c; + if (!strcmp(argv[c], "default")) { + preset = WEBP_PRESET_DEFAULT; + } else if (!strcmp(argv[c], "photo")) { + preset = WEBP_PRESET_PHOTO; + } else if (!strcmp(argv[c], "picture")) { + preset = WEBP_PRESET_PICTURE; + } else if (!strcmp(argv[c], "drawing")) { + preset = WEBP_PRESET_DRAWING; + } else if (!strcmp(argv[c], "icon")) { + preset = WEBP_PRESET_ICON; + } else if (!strcmp(argv[c], "text")) { + preset = WEBP_PRESET_TEXT; + } else { + fprintf(stderr, "Error! Unrecognized preset: %s\n", argv[c]); + goto Error; + } + if (!WebPConfigPreset(&config, preset, config.quality)) { + fprintf(stderr, "Error! Could initialize configuration with preset.\n"); + goto Error; + } + } else if (!strcmp(argv[c], "-metadata") && c + 1 < argc) { + static const struct { + const char* option; + int flag; + } kTokens[] = { + { "all", METADATA_ALL }, + { "none", 0 }, + { "exif", METADATA_EXIF }, + { "icc", METADATA_ICC }, + { "xmp", METADATA_XMP }, + }; + const size_t kNumTokens = sizeof(kTokens) / sizeof(kTokens[0]); + const char* start = argv[++c]; + const char* const end = start + strlen(start); + + while (start < end) { + size_t i; + const char* token = strchr(start, ','); + if (token == NULL) token = end; + + for (i = 0; i < kNumTokens; ++i) { + if ((size_t)(token - start) == strlen(kTokens[i].option) && + !strncmp(start, kTokens[i].option, strlen(kTokens[i].option))) { + if (kTokens[i].flag != 0) { + keep_metadata |= kTokens[i].flag; + } else { + keep_metadata = 0; + } + break; + } + } + if (i == kNumTokens) { + fprintf(stderr, "Error! Unknown metadata type '%.*s'\n", + (int)(token - start), start); + FREE_WARGV_AND_RETURN(-1); + } + start = token + 1; + } +#ifdef HAVE_WINCODEC_H + if (keep_metadata != 0 && keep_metadata != METADATA_ICC) { + // TODO(jzern): remove when -metadata is supported on all platforms. + fprintf(stderr, "Warning: only ICC profile extraction is currently" + " supported on this platform!\n"); + } +#endif + } else if (!strcmp(argv[c], "-v")) { + verbose = 1; + } else if (!strcmp(argv[c], "--")) { + if (c + 1 < argc) in_file = (const char*)GET_WARGV(argv, ++c); + break; + } else if (argv[c][0] == '-') { + fprintf(stderr, "Error! Unknown option '%s'\n", argv[c]); + HelpLong(); + FREE_WARGV_AND_RETURN(-1); + } else { + in_file = (const char*)GET_WARGV(argv, c); + } + + if (parse_error) { + HelpLong(); + FREE_WARGV_AND_RETURN(-1); + } + } + if (in_file == NULL) { + fprintf(stderr, "No input file specified!\n"); + HelpShort(); + goto Error; + } + + if (use_lossless_preset == 1) { + if (!WebPConfigLosslessPreset(&config, lossless_preset)) { + fprintf(stderr, "Invalid lossless preset (-z %d)\n", lossless_preset); + goto Error; + } + } + + // Check for unsupported command line options for lossless mode and log + // warning for such options. + if (!quiet && config.lossless == 1) { + if (config.target_size > 0 || config.target_PSNR > 0) { + fprintf(stderr, "Encoding for specified size or PSNR is not supported" + " for lossless encoding. Ignoring such option(s)!\n"); + } + if (config.partition_limit > 0) { + fprintf(stderr, "Partition limit option is not required for lossless" + " encoding. Ignoring this option!\n"); + } + } + // If a target size or PSNR was given, but somehow the -pass option was + // omitted, force a reasonable value. + if (config.target_size > 0 || config.target_PSNR > 0) { + if (config.pass == 1) config.pass = 6; + } + + if (!WebPValidateConfig(&config)) { + fprintf(stderr, "Error! Invalid configuration.\n"); + goto Error; + } + + // Read the input. We need to decide if we prefer ARGB or YUVA + // samples, depending on the expected compression mode (this saves + // some conversion steps). + picture.use_argb = (config.lossless || config.use_sharp_yuv || + config.preprocessing > 0 || + crop || (resize_w | resize_h) > 0); + if (verbose) { + StopwatchReset(&stop_watch); + } + if (!ReadPicture(in_file, &picture, keep_alpha, + (keep_metadata == 0) ? NULL : &metadata)) { + WFPRINTF(stderr, "Error! Cannot read input picture file '%s'\n", + (const W_CHAR*)in_file); + goto Error; + } + picture.progress_hook = (show_progress && !quiet) ? ProgressReport : NULL; + + if (blend_alpha) { + WebPBlendAlpha(&picture, background_color); + } + + if (verbose) { + const double read_time = StopwatchReadAndReset(&stop_watch); + fprintf(stderr, "Time to read input: %.3fs\n", read_time); + } + // The bitstream should be kept in memory when metadata must be appended + // before writing it to a file/stream, and/or when the near-losslessly encoded + // bitstream must be decoded for distortion computation (lossy will modify the + // 'picture' but not the lossless pipeline). + // Otherwise directly write the bitstream to a file. + use_memory_writer = (out_file != NULL && keep_metadata) || + (!quiet && print_distortion >= 0 && config.lossless && + config.near_lossless < 100); + + // Open the output + if (out_file != NULL) { + const int use_stdout = !WSTRCMP(out_file, "-"); + out = use_stdout ? ImgIoUtilSetBinaryMode(stdout) : WFOPEN(out_file, "wb"); + if (out == NULL) { + WFPRINTF(stderr, "Error! Cannot open output file '%s'\n", + (const W_CHAR*)out_file); + goto Error; + } else { + if (!short_output && !quiet) { + WFPRINTF(stderr, "Saving file '%s'\n", (const W_CHAR*)out_file); + } + } + if (use_memory_writer) { + picture.writer = WebPMemoryWrite; + picture.custom_ptr = (void*)&memory_writer; + } else { + picture.writer = MyWriter; + picture.custom_ptr = (void*)out; + } + } else { + out = NULL; + if (use_memory_writer) { + picture.writer = WebPMemoryWrite; + picture.custom_ptr = (void*)&memory_writer; + } + if (!quiet && !short_output) { + fprintf(stderr, "No output file specified (no -o flag). Encoding will\n"); + fprintf(stderr, "be performed, but its results discarded.\n\n"); + } + } + if (!quiet) { + picture.stats = &stats; + picture.user_data = (void*)in_file; + } + + // Crop & resize. + if (verbose) { + StopwatchReset(&stop_watch); + } + if (crop != 0) { + // We use self-cropping using a view. + if (!WebPPictureView(&picture, crop_x, crop_y, crop_w, crop_h, &picture)) { + fprintf(stderr, "Error! Cannot crop picture\n"); + goto Error; + } + } + if ((resize_w | resize_h) > 0) { + WebPPicture picture_no_alpha; + if (config.exact) { + // If -exact, we can't premultiply RGB by A otherwise RGB is lost if A=0. + // We rescale an opaque copy and assemble scaled A and non-premultiplied + // RGB channels. This is slower but it's a very uncommon use case. Color + // leak at sharp alpha edges is possible. + if (!WebPPictureCopy(&picture, &picture_no_alpha)) { + fprintf(stderr, "Error! Cannot copy temporary picture\n"); + goto Error; + } + + // We enforced picture.use_argb = 1 above. Now, remove the alpha values. + { + int x, y; + uint32_t* argb_no_alpha = picture_no_alpha.argb; + for (y = 0; y < picture_no_alpha.height; ++y) { + for (x = 0; x < picture_no_alpha.width; ++x) { + argb_no_alpha[x] |= 0xff000000; // Opaque copy. + } + argb_no_alpha += picture_no_alpha.argb_stride; + } + } + + if (!WebPPictureRescale(&picture_no_alpha, resize_w, resize_h)) { + fprintf(stderr, "Error! Cannot resize temporary picture\n"); + goto Error; + } + } + + if (!WebPPictureRescale(&picture, resize_w, resize_h)) { + fprintf(stderr, "Error! Cannot resize picture\n"); + goto Error; + } + + if (config.exact) { // Put back the alpha information. + int x, y; + uint32_t* argb_no_alpha = picture_no_alpha.argb; + uint32_t* argb = picture.argb; + for (y = 0; y < picture_no_alpha.height; ++y) { + for (x = 0; x < picture_no_alpha.width; ++x) { + argb[x] = (argb[x] & 0xff000000) | (argb_no_alpha[x] & 0x00ffffff); + } + argb_no_alpha += picture_no_alpha.argb_stride; + argb += picture.argb_stride; + } + WebPPictureFree(&picture_no_alpha); + } + } + if (verbose && (crop != 0 || (resize_w | resize_h) > 0)) { + const double preproc_time = StopwatchReadAndReset(&stop_watch); + fprintf(stderr, "Time to crop/resize picture: %.3fs\n", preproc_time); + } + + if (picture.extra_info_type > 0) { + AllocExtraInfo(&picture); + } + // Save original picture for later comparison. Only for lossy as lossless does + // not modify 'picture' (even near-lossless). + if (print_distortion >= 0 && !config.lossless && + !WebPPictureCopy(&picture, &original_picture)) { + fprintf(stderr, "Error! Cannot copy temporary picture\n"); + goto Error; + } + + // Compress. + if (verbose) { + StopwatchReset(&stop_watch); + } + if (!WebPEncode(&config, &picture)) { + fprintf(stderr, "Error! Cannot encode picture as WebP\n"); + fprintf(stderr, "Error code: %d (%s)\n", + picture.error_code, kErrorMessages[picture.error_code]); + goto Error; + } + if (verbose) { + const double encode_time = StopwatchReadAndReset(&stop_watch); + fprintf(stderr, "Time to encode picture: %.3fs\n", encode_time); + } + + // Get the decompressed image for the lossless pipeline. + if (!quiet && print_distortion >= 0 && config.lossless) { + if (config.near_lossless == 100) { + // Pure lossless: image was not modified, make 'original_picture' a view + // of 'picture' by copying all members except the freeable pointers. + original_picture = picture; + original_picture.memory_ = original_picture.memory_argb_ = NULL; + } else { + // Decode the bitstream stored in 'memory_writer' to get the altered image + // to 'picture'; save the 'original_picture' beforehand. + assert(use_memory_writer); + original_picture = picture; + if (!WebPPictureInit(&picture)) { // Do not free 'picture'. + fprintf(stderr, "Error! Version mismatch!\n"); + goto Error; + } + + picture.use_argb = 1; + if (!ReadWebP( + memory_writer.mem, memory_writer.size, &picture, + /*keep_alpha=*/WebPPictureHasTransparency(&original_picture), + /*metadata=*/NULL)) { + fprintf(stderr, "Error! Cannot decode encoded WebP bitstream\n"); + fprintf(stderr, "Error code: %d (%s)\n", picture.error_code, + kErrorMessages[picture.error_code]); + goto Error; + } + picture.stats = original_picture.stats; + } + original_picture.stats = NULL; + } + + // Write the YUV planes to a PGM file. Only available for lossy. + if (dump_file) { + if (picture.use_argb) { + fprintf(stderr, "Warning: can't dump file (-d option) " + "in lossless mode.\n"); + } else if (!DumpPicture(&picture, dump_file)) { + WFPRINTF(stderr, "Warning, couldn't dump picture %s\n", + (const W_CHAR*)dump_file); + } + } + + if (use_memory_writer && out != NULL && + !WriteWebPWithMetadata(out, &picture, &memory_writer, &metadata, + keep_metadata, &metadata_written)) { + fprintf(stderr, "Error writing WebP file!\n"); + goto Error; + } + + if (out == NULL && keep_metadata) { + // output is disabled, just display the metadata stats. + const struct { + const MetadataPayload* const payload; + int flag; + } *iter, info[] = {{&metadata.exif, METADATA_EXIF}, + {&metadata.iccp, METADATA_ICC}, + {&metadata.xmp, METADATA_XMP}, + {NULL, 0}}; + uint32_t unused1 = 0; + uint64_t unused2 = 0; + + for (iter = info; iter->payload != NULL; ++iter) { + if (UpdateFlagsAndSize(iter->payload, !!(keep_metadata & iter->flag), + /*flag=*/0, &unused1, &unused2)) { + metadata_written |= iter->flag; + } + } + } + + if (!quiet) { + if (!short_output || print_distortion < 0) { + if (config.lossless) { + PrintExtraInfoLossless(&picture, short_output, in_file); + } else { + PrintExtraInfoLossy(&picture, short_output, config.low_memory, in_file); + } + } + if (!short_output && picture.extra_info_type > 0) { + PrintMapInfo(&picture); + } + if (print_distortion >= 0) { // print distortion + static const char* distortion_names[] = { "PSNR", "SSIM", "LSIM" }; + float values[5]; + if (!WebPPictureDistortion(&picture, &original_picture, + print_distortion, values)) { + fprintf(stderr, "Error while computing the distortion.\n"); + goto Error; + } + if (!short_output) { + fprintf(stderr, "%s: ", distortion_names[print_distortion]); + fprintf(stderr, "B:%.2f G:%.2f R:%.2f A:%.2f Total:%.2f\n", + values[0], values[1], values[2], values[3], values[4]); + } else { + fprintf(stderr, "%7d %.4f\n", picture.stats->coded_size, values[4]); + } + } + if (!short_output) { + PrintMetadataInfo(&metadata, metadata_written); + } + } + return_value = 0; + + Error: + WebPMemoryWriterClear(&memory_writer); + WebPFree(picture.extra_info); + MetadataFree(&metadata); + WebPPictureFree(&picture); + WebPPictureFree(&original_picture); + if (out != NULL && out != stdout) { + fclose(out); + } + + FREE_WARGV_AND_RETURN(return_value); +} + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/examples/dwebp.c b/third-party/webp/libwebp/examples/dwebp.c new file mode 100644 index 0000000000..652de6a6ee --- /dev/null +++ b/third-party/webp/libwebp/examples/dwebp.c @@ -0,0 +1,421 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Command-line tool for decoding a WebP image. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include "webp/config.h" +#endif + +#include "../examples/example_util.h" +#include "../imageio/image_enc.h" +#include "../imageio/webpdec.h" +#include "./stopwatch.h" +#include "./unicode.h" + +static int verbose = 0; +static int quiet = 0; +#ifndef WEBP_DLL +#ifdef __cplusplus +extern "C" { +#endif + +extern void* VP8GetCPUInfo; // opaque forward declaration. + +#ifdef __cplusplus +} // extern "C" +#endif +#endif // WEBP_DLL + + +static int SaveOutput(const WebPDecBuffer* const buffer, + WebPOutputFileFormat format, const char* const out_file) { + const int use_stdout = (out_file != NULL) && !WSTRCMP(out_file, "-"); + int ok = 1; + Stopwatch stop_watch; + + if (verbose) { + StopwatchReset(&stop_watch); + } + ok = WebPSaveImage(buffer, format, out_file); + + if (ok) { + if (!quiet) { + if (use_stdout) { + fprintf(stderr, "Saved to stdout\n"); + } else { + WFPRINTF(stderr, "Saved file %s\n", (const W_CHAR*)out_file); + } + } + if (verbose) { + const double write_time = StopwatchReadAndReset(&stop_watch); + fprintf(stderr, "Time to write output: %.3fs\n", write_time); + } + } else { + if (use_stdout) { + fprintf(stderr, "Error writing to stdout !!\n"); + } else { + WFPRINTF(stderr, "Error writing file %s !!\n", (const W_CHAR*)out_file); + } + } + return ok; +} + +static void Help(void) { + printf("Usage: dwebp in_file [options] [-o out_file]\n\n" + "Decodes the WebP image file to PNG format [Default].\n" + "Note: Animated WebP files are not supported.\n\n" + "Use following options to convert into alternate image formats:\n" + " -pam ......... save the raw RGBA samples as a color PAM\n" + " -ppm ......... save the raw RGB samples as a color PPM\n" + " -bmp ......... save as uncompressed BMP format\n" + " -tiff ........ save as uncompressed TIFF format\n" + " -pgm ......... save the raw YUV samples as a grayscale PGM\n" + " file with IMC4 layout\n" + " -yuv ......... save the raw YUV samples in flat layout\n" + "\n" + " Other options are:\n" + " -version ..... print version number and exit\n" + " -nofancy ..... don't use the fancy YUV420 upscaler\n" + " -nofilter .... disable in-loop filtering\n" + " -nodither .... disable dithering\n" + " -dither .. dithering strength (in 0..100)\n" + " -alpha_dither use alpha-plane dithering if needed\n" + " -mt .......... use multi-threading\n" + " -crop ... crop output with the given rectangle\n" + " -resize ......... resize output (*after* any cropping)\n" + " -flip ........ flip the output vertically\n" + " -alpha ....... only save the alpha plane\n" + " -incremental . use incremental decoding (useful for tests)\n" + " -h ........... this help message\n" + " -v ........... verbose (e.g. print encoding/decoding times)\n" + " -quiet ....... quiet mode, don't print anything\n" +#ifndef WEBP_DLL + " -noasm ....... disable all assembly optimizations\n" +#endif + ); +} + +static const char* const kFormatType[] = { + "unspecified", "lossy", "lossless" +}; + +static uint8_t* AllocateExternalBuffer(WebPDecoderConfig* config, + WebPOutputFileFormat format, + int use_external_memory) { + uint8_t* external_buffer = NULL; + WebPDecBuffer* const output_buffer = &config->output; + int w = config->input.width; + int h = config->input.height; + if (config->options.use_scaling) { + w = config->options.scaled_width; + h = config->options.scaled_height; + } else if (config->options.use_cropping) { + w = config->options.crop_width; + h = config->options.crop_height; + } + if (format >= RGB && format <= rgbA_4444) { + const int bpp = (format == RGB || format == BGR) ? 3 + : (format == RGBA_4444 || format == rgbA_4444 || + format == RGB_565) ? 2 + : 4; + uint32_t stride = bpp * w + 7; // <- just for exercising + external_buffer = (uint8_t*)WebPMalloc(stride * h); + if (external_buffer == NULL) return NULL; + output_buffer->u.RGBA.stride = stride; + output_buffer->u.RGBA.size = stride * h; + output_buffer->u.RGBA.rgba = external_buffer; + } else { // YUV and YUVA + const int has_alpha = WebPIsAlphaMode(output_buffer->colorspace); + uint8_t* tmp; + uint32_t stride = w + 3; + uint32_t uv_stride = (w + 1) / 2 + 13; + uint32_t total_size = stride * h * (has_alpha ? 2 : 1) + + 2 * uv_stride * (h + 1) / 2; + assert(format >= YUV && format <= YUVA); + external_buffer = (uint8_t*)WebPMalloc(total_size); + if (external_buffer == NULL) return NULL; + tmp = external_buffer; + output_buffer->u.YUVA.y = tmp; + output_buffer->u.YUVA.y_stride = stride; + output_buffer->u.YUVA.y_size = stride * h; + tmp += output_buffer->u.YUVA.y_size; + if (has_alpha) { + output_buffer->u.YUVA.a = tmp; + output_buffer->u.YUVA.a_stride = stride; + output_buffer->u.YUVA.a_size = stride * h; + tmp += output_buffer->u.YUVA.a_size; + } else { + output_buffer->u.YUVA.a = NULL; + output_buffer->u.YUVA.a_stride = 0; + } + output_buffer->u.YUVA.u = tmp; + output_buffer->u.YUVA.u_stride = uv_stride; + output_buffer->u.YUVA.u_size = uv_stride * (h + 1) / 2; + tmp += output_buffer->u.YUVA.u_size; + + output_buffer->u.YUVA.v = tmp; + output_buffer->u.YUVA.v_stride = uv_stride; + output_buffer->u.YUVA.v_size = uv_stride * (h + 1) / 2; + tmp += output_buffer->u.YUVA.v_size; + assert(tmp <= external_buffer + total_size); + } + output_buffer->is_external_memory = use_external_memory; + return external_buffer; +} + +int main(int argc, const char* argv[]) { + int ok = 0; + const char* in_file = NULL; + const char* out_file = NULL; + + WebPDecoderConfig config; + WebPDecBuffer* const output_buffer = &config.output; + WebPBitstreamFeatures* const bitstream = &config.input; + WebPOutputFileFormat format = PNG; + uint8_t* external_buffer = NULL; + int use_external_memory = 0; + const uint8_t* data = NULL; + + int incremental = 0; + int c; + + INIT_WARGV(argc, argv); + + if (!WebPInitDecoderConfig(&config)) { + fprintf(stderr, "Library version mismatch!\n"); + FREE_WARGV_AND_RETURN(-1); + } + + for (c = 1; c < argc; ++c) { + int parse_error = 0; + if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) { + Help(); + FREE_WARGV_AND_RETURN(0); + } else if (!strcmp(argv[c], "-o") && c < argc - 1) { + out_file = (const char*)GET_WARGV(argv, ++c); + } else if (!strcmp(argv[c], "-alpha")) { + format = ALPHA_PLANE_ONLY; + } else if (!strcmp(argv[c], "-nofancy")) { + config.options.no_fancy_upsampling = 1; + } else if (!strcmp(argv[c], "-nofilter")) { + config.options.bypass_filtering = 1; + } else if (!strcmp(argv[c], "-pam")) { + format = PAM; + } else if (!strcmp(argv[c], "-ppm")) { + format = PPM; + } else if (!strcmp(argv[c], "-bmp")) { + format = BMP; + } else if (!strcmp(argv[c], "-tiff")) { + format = TIFF; + } else if (!strcmp(argv[c], "-quiet")) { + quiet = 1; + } else if (!strcmp(argv[c], "-version")) { + const int version = WebPGetDecoderVersion(); + printf("%d.%d.%d\n", + (version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff); + FREE_WARGV_AND_RETURN(0); + } else if (!strcmp(argv[c], "-pgm")) { + format = PGM; + } else if (!strcmp(argv[c], "-yuv")) { + format = RAW_YUV; + } else if (!strcmp(argv[c], "-pixel_format") && c < argc - 1) { + const char* const fmt = argv[++c]; + if (!strcmp(fmt, "RGB")) format = RGB; + else if (!strcmp(fmt, "RGBA")) format = RGBA; + else if (!strcmp(fmt, "BGR")) format = BGR; + else if (!strcmp(fmt, "BGRA")) format = BGRA; + else if (!strcmp(fmt, "ARGB")) format = ARGB; + else if (!strcmp(fmt, "RGBA_4444")) format = RGBA_4444; + else if (!strcmp(fmt, "RGB_565")) format = RGB_565; + else if (!strcmp(fmt, "rgbA")) format = rgbA; + else if (!strcmp(fmt, "bgrA")) format = bgrA; + else if (!strcmp(fmt, "Argb")) format = Argb; + else if (!strcmp(fmt, "rgbA_4444")) format = rgbA_4444; + else if (!strcmp(fmt, "YUV")) format = YUV; + else if (!strcmp(fmt, "YUVA")) format = YUVA; + else { + fprintf(stderr, "Can't parse pixel_format %s\n", fmt); + parse_error = 1; + } + } else if (!strcmp(argv[c], "-external_memory") && c < argc - 1) { + use_external_memory = ExUtilGetInt(argv[++c], 0, &parse_error); + parse_error |= (use_external_memory > 2 || use_external_memory < 0); + if (parse_error) { + fprintf(stderr, "Can't parse 'external_memory' value %s\n", argv[c]); + } + } else if (!strcmp(argv[c], "-mt")) { + config.options.use_threads = 1; + } else if (!strcmp(argv[c], "-alpha_dither")) { + config.options.alpha_dithering_strength = 100; + } else if (!strcmp(argv[c], "-nodither")) { + config.options.dithering_strength = 0; + } else if (!strcmp(argv[c], "-dither") && c < argc - 1) { + config.options.dithering_strength = + ExUtilGetInt(argv[++c], 0, &parse_error); + } else if (!strcmp(argv[c], "-crop") && c < argc - 4) { + config.options.use_cropping = 1; + config.options.crop_left = ExUtilGetInt(argv[++c], 0, &parse_error); + config.options.crop_top = ExUtilGetInt(argv[++c], 0, &parse_error); + config.options.crop_width = ExUtilGetInt(argv[++c], 0, &parse_error); + config.options.crop_height = ExUtilGetInt(argv[++c], 0, &parse_error); + } else if ((!strcmp(argv[c], "-scale") || !strcmp(argv[c], "-resize")) && + c < argc - 2) { // '-scale' is left for compatibility + config.options.use_scaling = 1; + config.options.scaled_width = ExUtilGetInt(argv[++c], 0, &parse_error); + config.options.scaled_height = ExUtilGetInt(argv[++c], 0, &parse_error); + } else if (!strcmp(argv[c], "-flip")) { + config.options.flip = 1; + } else if (!strcmp(argv[c], "-v")) { + verbose = 1; +#ifndef WEBP_DLL + } else if (!strcmp(argv[c], "-noasm")) { + VP8GetCPUInfo = NULL; +#endif + } else if (!strcmp(argv[c], "-incremental")) { + incremental = 1; + } else if (!strcmp(argv[c], "--")) { + if (c < argc - 1) in_file = (const char*)GET_WARGV(argv, ++c); + break; + } else if (argv[c][0] == '-') { + fprintf(stderr, "Unknown option '%s'\n", argv[c]); + Help(); + FREE_WARGV_AND_RETURN(-1); + } else { + in_file = (const char*)GET_WARGV(argv, c); + } + + if (parse_error) { + Help(); + FREE_WARGV_AND_RETURN(-1); + } + } + + if (in_file == NULL) { + fprintf(stderr, "missing input file!!\n"); + Help(); + FREE_WARGV_AND_RETURN(-1); + } + + if (quiet) verbose = 0; + + { + VP8StatusCode status = VP8_STATUS_OK; + size_t data_size = 0; + if (!LoadWebP(in_file, &data, &data_size, bitstream)) { + FREE_WARGV_AND_RETURN(-1); + } + + switch (format) { + case PNG: +#ifdef HAVE_WINCODEC_H + output_buffer->colorspace = bitstream->has_alpha ? MODE_BGRA : MODE_BGR; +#else + output_buffer->colorspace = bitstream->has_alpha ? MODE_RGBA : MODE_RGB; +#endif + break; + case PAM: + output_buffer->colorspace = MODE_RGBA; + break; + case PPM: + output_buffer->colorspace = MODE_RGB; // drops alpha for PPM + break; + case BMP: + output_buffer->colorspace = bitstream->has_alpha ? MODE_BGRA : MODE_BGR; + break; + case TIFF: + output_buffer->colorspace = bitstream->has_alpha ? MODE_RGBA : MODE_RGB; + break; + case PGM: + case RAW_YUV: + output_buffer->colorspace = bitstream->has_alpha ? MODE_YUVA : MODE_YUV; + break; + case ALPHA_PLANE_ONLY: + output_buffer->colorspace = MODE_YUVA; + break; + // forced modes: + case RGB: output_buffer->colorspace = MODE_RGB; break; + case RGBA: output_buffer->colorspace = MODE_RGBA; break; + case BGR: output_buffer->colorspace = MODE_BGR; break; + case BGRA: output_buffer->colorspace = MODE_BGRA; break; + case ARGB: output_buffer->colorspace = MODE_ARGB; break; + case RGBA_4444: output_buffer->colorspace = MODE_RGBA_4444; break; + case RGB_565: output_buffer->colorspace = MODE_RGB_565; break; + case rgbA: output_buffer->colorspace = MODE_rgbA; break; + case bgrA: output_buffer->colorspace = MODE_bgrA; break; + case Argb: output_buffer->colorspace = MODE_Argb; break; + case rgbA_4444: output_buffer->colorspace = MODE_rgbA_4444; break; + case YUV: output_buffer->colorspace = MODE_YUV; break; + case YUVA: output_buffer->colorspace = MODE_YUVA; break; + default: goto Exit; + } + + if (use_external_memory > 0 && format >= RGB) { + external_buffer = AllocateExternalBuffer(&config, format, + use_external_memory); + if (external_buffer == NULL) goto Exit; + } + + { + Stopwatch stop_watch; + if (verbose) StopwatchReset(&stop_watch); + + if (incremental) { + status = DecodeWebPIncremental(data, data_size, &config); + } else { + status = DecodeWebP(data, data_size, &config); + } + if (verbose) { + const double decode_time = StopwatchReadAndReset(&stop_watch); + fprintf(stderr, "Time to decode picture: %.3fs\n", decode_time); + } + } + + ok = (status == VP8_STATUS_OK); + if (!ok) { + PrintWebPError(in_file, status); + goto Exit; + } + } + + if (out_file != NULL) { + if (!quiet) { + WFPRINTF(stderr, "Decoded %s.", (const W_CHAR*)in_file); + fprintf(stderr, " Dimensions: %d x %d %s. Format: %s. Now saving...\n", + output_buffer->width, output_buffer->height, + bitstream->has_alpha ? " (with alpha)" : "", + kFormatType[bitstream->format]); + } + ok = SaveOutput(output_buffer, format, out_file); + } else { + if (!quiet) { + WFPRINTF(stderr, "File %s can be decoded ", (const W_CHAR*)in_file); + fprintf(stderr, "(dimensions: %d x %d %s. Format: %s).\n", + output_buffer->width, output_buffer->height, + bitstream->has_alpha ? " (with alpha)" : "", + kFormatType[bitstream->format]); + fprintf(stderr, "Nothing written; " + "use -o flag to save the result as e.g. PNG.\n"); + } + } + Exit: + WebPFreeDecBuffer(output_buffer); + WebPFree((void*)external_buffer); + WebPFree((void*)data); + FREE_WARGV_AND_RETURN(ok ? 0 : -1); +} + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/examples/example_util.c b/third-party/webp/libwebp/examples/example_util.c new file mode 100644 index 0000000000..fa38d3c2a5 --- /dev/null +++ b/third-party/webp/libwebp/examples/example_util.c @@ -0,0 +1,139 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Utility functions used by the example programs. +// + +#include "./example_util.h" + +#include +#include +#include +#include + +#include "webp/mux_types.h" +#include "../imageio/imageio_util.h" + +//------------------------------------------------------------------------------ +// String parsing + +uint32_t ExUtilGetUInt(const char* const v, int base, int* const error) { + char* end = NULL; + const uint32_t n = (v != NULL) ? (uint32_t)strtoul(v, &end, base) : 0u; + if (end == v && error != NULL && !*error) { + *error = 1; + fprintf(stderr, "Error! '%s' is not an integer.\n", + (v != NULL) ? v : "(null)"); + } + return n; +} + +int ExUtilGetInt(const char* const v, int base, int* const error) { + return (int)ExUtilGetUInt(v, base, error); +} + +int ExUtilGetInts(const char* v, int base, int max_output, int output[]) { + int n, error = 0; + for (n = 0; v != NULL && n < max_output; ++n) { + const int value = ExUtilGetInt(v, base, &error); + if (error) return -1; + output[n] = value; + v = strchr(v, ','); + if (v != NULL) ++v; // skip over the trailing ',' + } + return n; +} + +float ExUtilGetFloat(const char* const v, int* const error) { + char* end = NULL; + const float f = (v != NULL) ? (float)strtod(v, &end) : 0.f; + if (end == v && error != NULL && !*error) { + *error = 1; + fprintf(stderr, "Error! '%s' is not a floating point number.\n", + (v != NULL) ? v : "(null)"); + } + return f; +} + +//------------------------------------------------------------------------------ + +static void ResetCommandLineArguments(int argc, const char* argv[], + CommandLineArguments* const args) { + assert(args != NULL); + args->argc_ = argc; + args->argv_ = argv; + args->own_argv_ = 0; + WebPDataInit(&args->argv_data_); +} + +void ExUtilDeleteCommandLineArguments(CommandLineArguments* const args) { + if (args != NULL) { + if (args->own_argv_) { + WebPFree((void*)args->argv_); + WebPDataClear(&args->argv_data_); + } + ResetCommandLineArguments(0, NULL, args); + } +} + +#define MAX_ARGC 16384 +int ExUtilInitCommandLineArguments(int argc, const char* argv[], + CommandLineArguments* const args) { + if (args == NULL || argv == NULL) return 0; + ResetCommandLineArguments(argc, argv, args); + if (argc == 1 && argv[0][0] != '-') { + char* cur; + const char sep[] = " \t\r\n\f\v"; + +#if defined(_WIN32) && defined(_UNICODE) + fprintf(stderr, + "Error: Reading arguments from a file is a feature unavailable " + "with Unicode binaries.\n"); + return 0; +#endif + + if (!ExUtilReadFileToWebPData(argv[0], &args->argv_data_)) { + return 0; + } + args->own_argv_ = 1; + args->argv_ = (const char**)WebPMalloc(MAX_ARGC * sizeof(*args->argv_)); + if (args->argv_ == NULL) { + ExUtilDeleteCommandLineArguments(args); + return 0; + } + + argc = 0; + for (cur = strtok((char*)args->argv_data_.bytes, sep); + cur != NULL; + cur = strtok(NULL, sep)) { + if (argc == MAX_ARGC) { + fprintf(stderr, "ERROR: Arguments limit %d reached\n", MAX_ARGC); + ExUtilDeleteCommandLineArguments(args); + return 0; + } + assert(strlen(cur) != 0); + args->argv_[argc++] = cur; + } + args->argc_ = argc; + } + return 1; +} + +//------------------------------------------------------------------------------ + +int ExUtilReadFileToWebPData(const char* const filename, + WebPData* const webp_data) { + const uint8_t* data; + size_t size; + if (webp_data == NULL) return 0; + if (!ImgIoUtilReadFile(filename, &data, &size)) return 0; + webp_data->bytes = data; + webp_data->size = size; + return 1; +} diff --git a/third-party/webp/libwebp/examples/example_util.h b/third-party/webp/libwebp/examples/example_util.h new file mode 100644 index 0000000000..fe762a4d06 --- /dev/null +++ b/third-party/webp/libwebp/examples/example_util.h @@ -0,0 +1,70 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Utility functions used by the example programs. +// + +#ifndef WEBP_EXAMPLES_EXAMPLE_UTIL_H_ +#define WEBP_EXAMPLES_EXAMPLE_UTIL_H_ + +#include "webp/types.h" +#include "webp/mux_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//------------------------------------------------------------------------------ +// String parsing + +// Parses 'v' using strto(ul|l|d)(). If error is non-NULL, '*error' is set to +// true on failure while on success it is left unmodified to allow chaining of +// calls. An error is only printed on the first occurrence. +uint32_t ExUtilGetUInt(const char* const v, int base, int* const error); +int ExUtilGetInt(const char* const v, int base, int* const error); +float ExUtilGetFloat(const char* const v, int* const error); + +// This variant of ExUtilGetInt() will parse multiple integers from a +// comma-separated list. Up to 'max_output' integers are parsed. +// The result is placed in the output[] array, and the number of integers +// actually parsed is returned, or -1 if an error occurred. +int ExUtilGetInts(const char* v, int base, int max_output, int output[]); + +// Reads a file named 'filename' into a WebPData structure. The content of +// webp_data is overwritten. Returns false in case of error. +int ExUtilReadFileToWebPData(const char* const filename, + WebPData* const webp_data); + +//------------------------------------------------------------------------------ +// Command-line arguments + +typedef struct { + int argc_; + const char** argv_; + WebPData argv_data_; + int own_argv_; +} CommandLineArguments; + +// Initializes the structure from the command-line parameters. If there is +// only one parameter and it does not start with a '-', then it is assumed to +// be a file name. This file will be read and tokenized into command-line +// arguments. The content of 'args' is overwritten. +// Returns false in case of error (memory allocation failure, non +// existing file, too many arguments, ...). +int ExUtilInitCommandLineArguments(int argc, const char* argv[], + CommandLineArguments* const args); + +// Deallocate all memory and reset 'args'. +void ExUtilDeleteCommandLineArguments(CommandLineArguments* const args); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_EXAMPLES_EXAMPLE_UTIL_H_ diff --git a/third-party/webp/libwebp/examples/gif2webp.c b/third-party/webp/libwebp/examples/gif2webp.c new file mode 100644 index 0000000000..cc9b25d989 --- /dev/null +++ b/third-party/webp/libwebp/examples/gif2webp.c @@ -0,0 +1,609 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// simple tool to convert animated GIFs to WebP +// +// Authors: Skal (pascal.massimino@gmail.com) +// Urvang (urvang@google.com) + +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include "webp/config.h" +#endif + +#ifdef WEBP_HAVE_GIF + +#if defined(HAVE_UNISTD_H) && HAVE_UNISTD_H +#include +#endif + +#include +#include "webp/encode.h" +#include "webp/mux.h" +#include "../examples/example_util.h" +#include "../imageio/imageio_util.h" +#include "./gifdec.h" +#include "./unicode.h" +#include "./unicode_gif.h" + +#if !defined(STDIN_FILENO) +#define STDIN_FILENO 0 +#endif + +//------------------------------------------------------------------------------ + +static int transparent_index = GIF_INDEX_INVALID; // Opaque by default. + +static const char* const kErrorMessages[-WEBP_MUX_NOT_ENOUGH_DATA + 1] = { + "WEBP_MUX_NOT_FOUND", "WEBP_MUX_INVALID_ARGUMENT", "WEBP_MUX_BAD_DATA", + "WEBP_MUX_MEMORY_ERROR", "WEBP_MUX_NOT_ENOUGH_DATA" +}; + +static const char* ErrorString(WebPMuxError err) { + assert(err <= WEBP_MUX_NOT_FOUND && err >= WEBP_MUX_NOT_ENOUGH_DATA); + return kErrorMessages[-err]; +} + +enum { + METADATA_ICC = (1 << 0), + METADATA_XMP = (1 << 1), + METADATA_ALL = METADATA_ICC | METADATA_XMP +}; + +//------------------------------------------------------------------------------ + +static void Help(void) { + printf("Usage:\n"); + printf(" gif2webp [options] gif_file -o webp_file\n"); + printf("Options:\n"); + printf(" -h / -help ............. this help\n"); + printf(" -lossy ................. encode image using lossy compression\n"); + printf(" -mixed ................. for each frame in the image, pick lossy\n" + " or lossless compression heuristically\n"); + printf(" -q ............. quality factor (0:small..100:big)\n"); + printf(" -m ............... compression method (0=fast, 6=slowest)\n"); + printf(" -min_size .............. minimize output size (default:off)\n" + " lossless compression by default; can be\n" + " combined with -q, -m, -lossy or -mixed\n" + " options\n"); + printf(" -kmin ............ min distance between key frames\n"); + printf(" -kmax ............ max distance between key frames\n"); + printf(" -f ............... filter strength (0=off..100)\n"); + printf(" -metadata ..... comma separated list of metadata to\n"); + printf(" "); + printf("copy from the input to the output if present\n"); + printf(" "); + printf("Valid values: all, none, icc, xmp (default)\n"); + printf(" -loop_compatibility .... use compatibility mode for Chrome\n"); + printf(" version prior to M62 (inclusive)\n"); + printf(" -mt .................... use multi-threading if available\n"); + printf("\n"); + printf(" -version ............... print version number and exit\n"); + printf(" -v ..................... verbose\n"); + printf(" -quiet ................. don't print anything\n"); + printf("\n"); +} + +//------------------------------------------------------------------------------ + +int main(int argc, const char* argv[]) { + int verbose = 0; + int gif_error = GIF_ERROR; + WebPMuxError err = WEBP_MUX_OK; + int ok = 0; + const W_CHAR* in_file = NULL, *out_file = NULL; + GifFileType* gif = NULL; + int frame_duration = 0; + int frame_timestamp = 0; + GIFDisposeMethod orig_dispose = GIF_DISPOSE_NONE; + + WebPPicture frame; // Frame rectangle only (not disposed). + WebPPicture curr_canvas; // Not disposed. + WebPPicture prev_canvas; // Disposed. + + WebPAnimEncoder* enc = NULL; + WebPAnimEncoderOptions enc_options; + WebPConfig config; + + int frame_number = 0; // Whether we are processing the first frame. + int done; + int c; + int quiet = 0; + WebPData webp_data; + + int keep_metadata = METADATA_XMP; // ICC not output by default. + WebPData icc_data; + int stored_icc = 0; // Whether we have already stored an ICC profile. + WebPData xmp_data; + int stored_xmp = 0; // Whether we have already stored an XMP profile. + int loop_count = 0; // default: infinite + int stored_loop_count = 0; // Whether we have found an explicit loop count. + int loop_compatibility = 0; + WebPMux* mux = NULL; + + int default_kmin = 1; // Whether to use default kmin value. + int default_kmax = 1; + + INIT_WARGV(argc, argv); + + if (!WebPConfigInit(&config) || !WebPAnimEncoderOptionsInit(&enc_options) || + !WebPPictureInit(&frame) || !WebPPictureInit(&curr_canvas) || + !WebPPictureInit(&prev_canvas)) { + fprintf(stderr, "Error! Version mismatch!\n"); + FREE_WARGV_AND_RETURN(-1); + } + config.lossless = 1; // Use lossless compression by default. + + WebPDataInit(&webp_data); + WebPDataInit(&icc_data); + WebPDataInit(&xmp_data); + + if (argc == 1) { + Help(); + FREE_WARGV_AND_RETURN(0); + } + + for (c = 1; c < argc; ++c) { + int parse_error = 0; + if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) { + Help(); + FREE_WARGV_AND_RETURN(0); + } else if (!strcmp(argv[c], "-o") && c < argc - 1) { + out_file = GET_WARGV(argv, ++c); + } else if (!strcmp(argv[c], "-lossy")) { + config.lossless = 0; + } else if (!strcmp(argv[c], "-mixed")) { + enc_options.allow_mixed = 1; + config.lossless = 0; + } else if (!strcmp(argv[c], "-loop_compatibility")) { + loop_compatibility = 1; + } else if (!strcmp(argv[c], "-q") && c < argc - 1) { + config.quality = ExUtilGetFloat(argv[++c], &parse_error); + } else if (!strcmp(argv[c], "-m") && c < argc - 1) { + config.method = ExUtilGetInt(argv[++c], 0, &parse_error); + } else if (!strcmp(argv[c], "-min_size")) { + enc_options.minimize_size = 1; + } else if (!strcmp(argv[c], "-kmax") && c < argc - 1) { + enc_options.kmax = ExUtilGetInt(argv[++c], 0, &parse_error); + default_kmax = 0; + } else if (!strcmp(argv[c], "-kmin") && c < argc - 1) { + enc_options.kmin = ExUtilGetInt(argv[++c], 0, &parse_error); + default_kmin = 0; + } else if (!strcmp(argv[c], "-f") && c < argc - 1) { + config.filter_strength = ExUtilGetInt(argv[++c], 0, &parse_error); + } else if (!strcmp(argv[c], "-metadata") && c < argc - 1) { + static const struct { + const char* option; + int flag; + } kTokens[] = { + { "all", METADATA_ALL }, + { "none", 0 }, + { "icc", METADATA_ICC }, + { "xmp", METADATA_XMP }, + }; + const size_t kNumTokens = sizeof(kTokens) / sizeof(*kTokens); + const char* start = argv[++c]; + const char* const end = start + strlen(start); + + keep_metadata = 0; + while (start < end) { + size_t i; + const char* token = strchr(start, ','); + if (token == NULL) token = end; + + for (i = 0; i < kNumTokens; ++i) { + if ((size_t)(token - start) == strlen(kTokens[i].option) && + !strncmp(start, kTokens[i].option, strlen(kTokens[i].option))) { + if (kTokens[i].flag != 0) { + keep_metadata |= kTokens[i].flag; + } else { + keep_metadata = 0; + } + break; + } + } + if (i == kNumTokens) { + fprintf(stderr, "Error! Unknown metadata type '%.*s'\n", + (int)(token - start), start); + Help(); + FREE_WARGV_AND_RETURN(-1); + } + start = token + 1; + } + } else if (!strcmp(argv[c], "-mt")) { + ++config.thread_level; + } else if (!strcmp(argv[c], "-version")) { + const int enc_version = WebPGetEncoderVersion(); + const int mux_version = WebPGetMuxVersion(); + printf("WebP Encoder version: %d.%d.%d\nWebP Mux version: %d.%d.%d\n", + (enc_version >> 16) & 0xff, (enc_version >> 8) & 0xff, + enc_version & 0xff, (mux_version >> 16) & 0xff, + (mux_version >> 8) & 0xff, mux_version & 0xff); + FREE_WARGV_AND_RETURN(0); + } else if (!strcmp(argv[c], "-quiet")) { + quiet = 1; + enc_options.verbose = 0; + } else if (!strcmp(argv[c], "-v")) { + verbose = 1; + enc_options.verbose = 1; + } else if (!strcmp(argv[c], "--")) { + if (c < argc - 1) in_file = GET_WARGV(argv, ++c); + break; + } else if (argv[c][0] == '-') { + fprintf(stderr, "Error! Unknown option '%s'\n", argv[c]); + Help(); + FREE_WARGV_AND_RETURN(-1); + } else { + in_file = GET_WARGV(argv, c); + } + + if (parse_error) { + Help(); + FREE_WARGV_AND_RETURN(-1); + } + } + + // Appropriate default kmin, kmax values for lossy and lossless. + if (default_kmin) { + enc_options.kmin = config.lossless ? 9 : 3; + } + if (default_kmax) { + enc_options.kmax = config.lossless ? 17 : 5; + } + + if (!WebPValidateConfig(&config)) { + fprintf(stderr, "Error! Invalid configuration.\n"); + goto End; + } + + if (in_file == NULL) { + fprintf(stderr, "No input file specified!\n"); + Help(); + goto End; + } + + // Start the decoder object + gif = DGifOpenFileUnicode(in_file, &gif_error); + if (gif == NULL) goto End; + + // Loop over GIF images + done = 0; + do { + GifRecordType type; + if (DGifGetRecordType(gif, &type) == GIF_ERROR) goto End; + + switch (type) { + case IMAGE_DESC_RECORD_TYPE: { + GIFFrameRect gif_rect; + GifImageDesc* const image_desc = &gif->Image; + + if (!DGifGetImageDesc(gif)) goto End; + + if (frame_number == 0) { + if (verbose) { + printf("Canvas screen: %d x %d\n", gif->SWidth, gif->SHeight); + } + // Fix some broken GIF global headers that report + // 0 x 0 screen dimension. + if (gif->SWidth == 0 || gif->SHeight == 0) { + image_desc->Left = 0; + image_desc->Top = 0; + gif->SWidth = image_desc->Width; + gif->SHeight = image_desc->Height; + if (gif->SWidth <= 0 || gif->SHeight <= 0) { + goto End; + } + if (verbose) { + printf("Fixed canvas screen dimension to: %d x %d\n", + gif->SWidth, gif->SHeight); + } + } + // Allocate current buffer. + frame.width = gif->SWidth; + frame.height = gif->SHeight; + frame.use_argb = 1; + if (!WebPPictureAlloc(&frame)) goto End; + GIFClearPic(&frame, NULL); + if (!(WebPPictureCopy(&frame, &curr_canvas) && + WebPPictureCopy(&frame, &prev_canvas))) { + fprintf(stderr, "Error allocating canvas.\n"); + goto End; + } + + // Background color. + GIFGetBackgroundColor(gif->SColorMap, gif->SBackGroundColor, + transparent_index, + &enc_options.anim_params.bgcolor); + + // Initialize encoder. + enc = WebPAnimEncoderNew(curr_canvas.width, curr_canvas.height, + &enc_options); + if (enc == NULL) { + fprintf(stderr, + "Error! Could not create encoder object. Possibly due to " + "a memory error.\n"); + goto End; + } + } + + // Some even more broken GIF can have sub-rect with zero width/height. + if (image_desc->Width == 0 || image_desc->Height == 0) { + image_desc->Width = gif->SWidth; + image_desc->Height = gif->SHeight; + } + + if (!GIFReadFrame(gif, transparent_index, &gif_rect, &frame)) { + goto End; + } + // Blend frame rectangle with previous canvas to compose full canvas. + // Note that 'curr_canvas' is same as 'prev_canvas' at this point. + GIFBlendFrames(&frame, &gif_rect, &curr_canvas); + + if (!WebPAnimEncoderAdd(enc, &curr_canvas, frame_timestamp, &config)) { + fprintf(stderr, "Error while adding frame #%d: %s\n", frame_number, + WebPAnimEncoderGetError(enc)); + goto End; + } else { + ++frame_number; + } + + // Update canvases. + GIFDisposeFrame(orig_dispose, &gif_rect, &prev_canvas, &curr_canvas); + GIFCopyPixels(&curr_canvas, &prev_canvas); + + // Force frames with a small or no duration to 100ms to be consistent + // with web browsers and other transcoding tools. This also avoids + // incorrect durations between frames when padding frames are + // discarded. + if (frame_duration <= 10) { + frame_duration = 100; + } + + // Update timestamp (for next frame). + frame_timestamp += frame_duration; + + // In GIF, graphic control extensions are optional for a frame, so we + // may not get one before reading the next frame. To handle this case, + // we reset frame properties to reasonable defaults for the next frame. + orig_dispose = GIF_DISPOSE_NONE; + frame_duration = 0; + transparent_index = GIF_INDEX_INVALID; + break; + } + case EXTENSION_RECORD_TYPE: { + int extension; + GifByteType* data = NULL; + if (DGifGetExtension(gif, &extension, &data) == GIF_ERROR) { + goto End; + } + if (data == NULL) continue; + + switch (extension) { + case COMMENT_EXT_FUNC_CODE: { + break; // Do nothing for now. + } + case GRAPHICS_EXT_FUNC_CODE: { + if (!GIFReadGraphicsExtension(data, &frame_duration, &orig_dispose, + &transparent_index)) { + goto End; + } + break; + } + case PLAINTEXT_EXT_FUNC_CODE: { + break; + } + case APPLICATION_EXT_FUNC_CODE: { + if (data[0] != 11) break; // Chunk is too short + if (!memcmp(data + 1, "NETSCAPE2.0", 11) || + !memcmp(data + 1, "ANIMEXTS1.0", 11)) { + if (!GIFReadLoopCount(gif, &data, &loop_count)) { + goto End; + } + if (verbose) { + fprintf(stderr, "Loop count: %d\n", loop_count); + } + stored_loop_count = loop_compatibility ? (loop_count != 0) : 1; + } else { // An extension containing metadata. + // We only store the first encountered chunk of each type, and + // only if requested by the user. + const int is_xmp = (keep_metadata & METADATA_XMP) && + !stored_xmp && + !memcmp(data + 1, "XMP DataXMP", 11); + const int is_icc = (keep_metadata & METADATA_ICC) && + !stored_icc && + !memcmp(data + 1, "ICCRGBG1012", 11); + if (is_xmp || is_icc) { + if (!GIFReadMetadata(gif, &data, + is_xmp ? &xmp_data : &icc_data)) { + goto End; + } + if (is_icc) { + stored_icc = 1; + } else if (is_xmp) { + stored_xmp = 1; + } + } + } + break; + } + default: { + break; // skip + } + } + while (data != NULL) { + if (DGifGetExtensionNext(gif, &data) == GIF_ERROR) goto End; + } + break; + } + case TERMINATE_RECORD_TYPE: { + done = 1; + break; + } + default: { + if (verbose) { + fprintf(stderr, "Skipping over unknown record type %d\n", type); + } + break; + } + } + } while (!done); + + // Last NULL frame. + if (!WebPAnimEncoderAdd(enc, NULL, frame_timestamp, NULL)) { + fprintf(stderr, "Error flushing WebP muxer.\n"); + fprintf(stderr, "%s\n", WebPAnimEncoderGetError(enc)); + } + + if (!WebPAnimEncoderAssemble(enc, &webp_data)) { + fprintf(stderr, "%s\n", WebPAnimEncoderGetError(enc)); + goto End; + } + // If there's only one frame, we don't need to handle loop count. + if (frame_number == 1) { + loop_count = 0; + } else if (!loop_compatibility) { + if (!stored_loop_count) { + // if no loop-count element is seen, the default is '1' (loop-once) + // and we need to signal it explicitly in WebP. Note however that + // in case there's a single frame, we still don't need to store it. + if (frame_number > 1) { + stored_loop_count = 1; + loop_count = 1; + } + } else if (loop_count > 0 && loop_count < 65535) { + // adapt GIF's semantic to WebP's (except in the infinite-loop case) + loop_count += 1; + } + } + // loop_count of 0 is the default (infinite), so no need to signal it + if (loop_count == 0) stored_loop_count = 0; + + if (stored_loop_count || stored_icc || stored_xmp) { + // Re-mux to add loop count and/or metadata as needed. + mux = WebPMuxCreate(&webp_data, 1); + if (mux == NULL) { + fprintf(stderr, "ERROR: Could not re-mux to add loop count/metadata.\n"); + goto End; + } + WebPDataClear(&webp_data); + + if (stored_loop_count) { // Update loop count. + WebPMuxAnimParams new_params; + err = WebPMuxGetAnimationParams(mux, &new_params); + if (err != WEBP_MUX_OK) { + fprintf(stderr, "ERROR (%s): Could not fetch loop count.\n", + ErrorString(err)); + goto End; + } + new_params.loop_count = loop_count; + err = WebPMuxSetAnimationParams(mux, &new_params); + if (err != WEBP_MUX_OK) { + fprintf(stderr, "ERROR (%s): Could not update loop count.\n", + ErrorString(err)); + goto End; + } + } + + if (stored_icc) { // Add ICCP chunk. + err = WebPMuxSetChunk(mux, "ICCP", &icc_data, 1); + if (verbose) { + fprintf(stderr, "ICC size: %d\n", (int)icc_data.size); + } + if (err != WEBP_MUX_OK) { + fprintf(stderr, "ERROR (%s): Could not set ICC chunk.\n", + ErrorString(err)); + goto End; + } + } + + if (stored_xmp) { // Add XMP chunk. + err = WebPMuxSetChunk(mux, "XMP ", &xmp_data, 1); + if (verbose) { + fprintf(stderr, "XMP size: %d\n", (int)xmp_data.size); + } + if (err != WEBP_MUX_OK) { + fprintf(stderr, "ERROR (%s): Could not set XMP chunk.\n", + ErrorString(err)); + goto End; + } + } + + err = WebPMuxAssemble(mux, &webp_data); + if (err != WEBP_MUX_OK) { + fprintf(stderr, "ERROR (%s): Could not assemble when re-muxing to add " + "loop count/metadata.\n", ErrorString(err)); + goto End; + } + } + + if (out_file != NULL) { + if (!ImgIoUtilWriteFile((const char*)out_file, webp_data.bytes, + webp_data.size)) { + WFPRINTF(stderr, "Error writing output file: %s\n", out_file); + goto End; + } + if (!quiet) { + if (!WSTRCMP(out_file, "-")) { + fprintf(stderr, "Saved %d bytes to STDIO\n", + (int)webp_data.size); + } else { + WFPRINTF(stderr, "Saved output file (%d bytes): %s\n", + (int)webp_data.size, out_file); + } + } + } else { + if (!quiet) { + fprintf(stderr, "Nothing written; use -o flag to save the result " + "(%d bytes).\n", (int)webp_data.size); + } + } + + // All OK. + ok = 1; + gif_error = GIF_OK; + + End: + WebPDataClear(&icc_data); + WebPDataClear(&xmp_data); + WebPMuxDelete(mux); + WebPDataClear(&webp_data); + WebPPictureFree(&frame); + WebPPictureFree(&curr_canvas); + WebPPictureFree(&prev_canvas); + WebPAnimEncoderDelete(enc); + + if (gif_error != GIF_OK) { + GIFDisplayError(gif, gif_error); + } + if (gif != NULL) { +#if LOCAL_GIF_PREREQ(5,1) + DGifCloseFile(gif, &gif_error); +#else + DGifCloseFile(gif); +#endif + } + + FREE_WARGV_AND_RETURN(!ok); +} + +#else // !WEBP_HAVE_GIF + +int main(int argc, const char* argv[]) { + fprintf(stderr, "GIF support not enabled in %s.\n", argv[0]); + (void)argc; + return 0; +} + +#endif + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/examples/gifdec.c b/third-party/webp/libwebp/examples/gifdec.c new file mode 100644 index 0000000000..99ee9966e2 --- /dev/null +++ b/third-party/webp/libwebp/examples/gifdec.c @@ -0,0 +1,416 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// GIF decode. + +#include "./gifdec.h" + +#include + +#ifdef WEBP_HAVE_GIF +#include +#include +#include + +#include "webp/encode.h" +#include "webp/mux_types.h" + +#define GIF_TRANSPARENT_COLOR 0x00000000u +#define GIF_WHITE_COLOR 0xffffffffu +#define GIF_TRANSPARENT_MASK 0x01 +#define GIF_DISPOSE_MASK 0x07 +#define GIF_DISPOSE_SHIFT 2 + +// from utils/utils.h +#ifdef __cplusplus +extern "C" { +#endif +extern void WebPCopyPlane(const uint8_t* src, int src_stride, + uint8_t* dst, int dst_stride, + int width, int height); +extern void WebPCopyPixels(const WebPPicture* const src, + WebPPicture* const dst); +#ifdef __cplusplus +} +#endif + +void GIFGetBackgroundColor(const ColorMapObject* const color_map, + int bgcolor_index, int transparent_index, + uint32_t* const bgcolor) { + if (transparent_index != GIF_INDEX_INVALID && + bgcolor_index == transparent_index) { + *bgcolor = GIF_TRANSPARENT_COLOR; // Special case. + } else if (color_map == NULL || color_map->Colors == NULL + || bgcolor_index >= color_map->ColorCount) { + *bgcolor = GIF_WHITE_COLOR; + fprintf(stderr, + "GIF decode warning: invalid background color index. Assuming " + "white background.\n"); + } else { + const GifColorType color = color_map->Colors[bgcolor_index]; + *bgcolor = (0xffu << 24) + | (color.Red << 16) + | (color.Green << 8) + | (color.Blue << 0); + } +} + +int GIFReadGraphicsExtension(const GifByteType* const buf, int* const duration, + GIFDisposeMethod* const dispose, + int* const transparent_index) { + const int flags = buf[1]; + const int dispose_raw = (flags >> GIF_DISPOSE_SHIFT) & GIF_DISPOSE_MASK; + const int duration_raw = buf[2] | (buf[3] << 8); // In 10 ms units. + if (buf[0] != 4) return 0; + *duration = duration_raw * 10; // Duration is in 1 ms units. + switch (dispose_raw) { + case 3: + *dispose = GIF_DISPOSE_RESTORE_PREVIOUS; + break; + case 2: + *dispose = GIF_DISPOSE_BACKGROUND; + break; + case 1: + case 0: + default: + *dispose = GIF_DISPOSE_NONE; + break; + } + *transparent_index = + (flags & GIF_TRANSPARENT_MASK) ? buf[4] : GIF_INDEX_INVALID; + return 1; +} + +static int Remap(const GifFileType* const gif, const uint8_t* const src, + int len, int transparent_index, uint32_t* dst) { + int i; + const GifColorType* colors; + const ColorMapObject* const cmap = + gif->Image.ColorMap ? gif->Image.ColorMap : gif->SColorMap; + if (cmap == NULL) return 1; + if (cmap->Colors == NULL || cmap->ColorCount <= 0) return 0; + colors = cmap->Colors; + + for (i = 0; i < len; ++i) { + if (src[i] == transparent_index) { + dst[i] = GIF_TRANSPARENT_COLOR; + } else if (src[i] < cmap->ColorCount) { + const GifColorType c = colors[src[i]]; + dst[i] = c.Blue | (c.Green << 8) | (c.Red << 16) | (0xffu << 24); + } else { + return 0; + } + } + return 1; +} + +int GIFReadFrame(GifFileType* const gif, int transparent_index, + GIFFrameRect* const gif_rect, WebPPicture* const picture) { + WebPPicture sub_image; + const GifImageDesc* const image_desc = &gif->Image; + uint32_t* dst = NULL; + uint8_t* tmp = NULL; + const GIFFrameRect rect = { + image_desc->Left, image_desc->Top, image_desc->Width, image_desc->Height + }; + const uint64_t memory_needed = 4 * rect.width * (uint64_t)rect.height; + int ok = 0; + *gif_rect = rect; + + if (memory_needed != (size_t)memory_needed || memory_needed > (4ULL << 32)) { + fprintf(stderr, "Image is too large (%d x %d).", rect.width, rect.height); + return 0; + } + + // Use a view for the sub-picture: + if (!WebPPictureView(picture, rect.x_offset, rect.y_offset, + rect.width, rect.height, &sub_image)) { + fprintf(stderr, "Sub-image %dx%d at position %d,%d is invalid!\n", + rect.width, rect.height, rect.x_offset, rect.y_offset); + return 0; + } + dst = sub_image.argb; + + tmp = (uint8_t*)WebPMalloc(rect.width * sizeof(*tmp)); + if (tmp == NULL) goto End; + + if (image_desc->Interlace) { // Interlaced image. + // We need 4 passes, with the following offsets and jumps. + const int interlace_offsets[] = { 0, 4, 2, 1 }; + const int interlace_jumps[] = { 8, 8, 4, 2 }; + int pass; + for (pass = 0; pass < 4; ++pass) { + const size_t stride = (size_t)sub_image.argb_stride; + int y = interlace_offsets[pass]; + uint32_t* row = dst + y * stride; + const size_t jump = interlace_jumps[pass] * stride; + for (; y < rect.height; y += interlace_jumps[pass], row += jump) { + if (DGifGetLine(gif, tmp, rect.width) == GIF_ERROR) goto End; + if (!Remap(gif, tmp, rect.width, transparent_index, row)) goto End; + } + } + } else { // Non-interlaced image. + int y; + uint32_t* ptr = dst; + for (y = 0; y < rect.height; ++y, ptr += sub_image.argb_stride) { + if (DGifGetLine(gif, tmp, rect.width) == GIF_ERROR) goto End; + if (!Remap(gif, tmp, rect.width, transparent_index, ptr)) goto End; + } + } + ok = 1; + + End: + if (!ok) picture->error_code = sub_image.error_code; + WebPPictureFree(&sub_image); + WebPFree(tmp); + return ok; +} + +int GIFReadLoopCount(GifFileType* const gif, GifByteType** const buf, + int* const loop_count) { + assert(!memcmp(*buf + 1, "NETSCAPE2.0", 11) || + !memcmp(*buf + 1, "ANIMEXTS1.0", 11)); + if (DGifGetExtensionNext(gif, buf) == GIF_ERROR) { + return 0; + } + if (*buf == NULL) { + return 0; // Loop count sub-block missing. + } + if ((*buf)[0] < 3 || (*buf)[1] != 1) { + return 0; // wrong size/marker + } + *loop_count = (*buf)[2] | ((*buf)[3] << 8); + return 1; +} + +int GIFReadMetadata(GifFileType* const gif, GifByteType** const buf, + WebPData* const metadata) { + const int is_xmp = !memcmp(*buf + 1, "XMP DataXMP", 11); + const int is_icc = !memcmp(*buf + 1, "ICCRGBG1012", 11); + assert(is_xmp || is_icc); + (void)is_icc; // silence unused warning. + // Construct metadata from sub-blocks. + // Usual case (including ICC profile): In each sub-block, the + // first byte specifies its size in bytes (0 to 255) and the + // rest of the bytes contain the data. + // Special case for XMP data: In each sub-block, the first byte + // is also part of the XMP payload. XMP in GIF also has a 257 + // byte padding data. See the XMP specification for details. + while (1) { + WebPData subblock; + const uint8_t* tmp; + if (DGifGetExtensionNext(gif, buf) == GIF_ERROR) { + return 0; + } + if (*buf == NULL) break; // Finished. + subblock.size = is_xmp ? (*buf)[0] + 1 : (*buf)[0]; + assert(subblock.size > 0); + subblock.bytes = is_xmp ? *buf : *buf + 1; + // Note: We store returned value in 'tmp' first, to avoid + // leaking old memory in metadata->bytes on error. + tmp = (uint8_t*)realloc((void*)metadata->bytes, + metadata->size + subblock.size); + if (tmp == NULL) { + return 0; + } + memcpy((void*)(tmp + metadata->size), + subblock.bytes, subblock.size); + metadata->bytes = tmp; + metadata->size += subblock.size; + } + if (is_xmp) { + // XMP padding data is 0x01, 0xff, 0xfe ... 0x01, 0x00. + const size_t xmp_pading_size = 257; + if (metadata->size > xmp_pading_size) { + metadata->size -= xmp_pading_size; + } + } + return 1; +} + +static void ClearRectangle(WebPPicture* const picture, + int left, int top, int width, int height) { + int i, j; + const size_t stride = picture->argb_stride; + uint32_t* dst = picture->argb + top * stride + left; + for (j = 0; j < height; ++j, dst += stride) { + for (i = 0; i < width; ++i) dst[i] = GIF_TRANSPARENT_COLOR; + } +} + +void GIFClearPic(WebPPicture* const pic, const GIFFrameRect* const rect) { + if (rect != NULL) { + ClearRectangle(pic, rect->x_offset, rect->y_offset, + rect->width, rect->height); + } else { + ClearRectangle(pic, 0, 0, pic->width, pic->height); + } +} + +void GIFCopyPixels(const WebPPicture* const src, WebPPicture* const dst) { + WebPCopyPixels(src, dst); +} + +void GIFDisposeFrame(GIFDisposeMethod dispose, const GIFFrameRect* const rect, + const WebPPicture* const prev_canvas, + WebPPicture* const curr_canvas) { + assert(rect != NULL); + if (dispose == GIF_DISPOSE_BACKGROUND) { + GIFClearPic(curr_canvas, rect); + } else if (dispose == GIF_DISPOSE_RESTORE_PREVIOUS) { + const size_t src_stride = prev_canvas->argb_stride; + const uint32_t* const src = prev_canvas->argb + rect->x_offset + + rect->y_offset * src_stride; + const size_t dst_stride = curr_canvas->argb_stride; + uint32_t* const dst = curr_canvas->argb + rect->x_offset + + rect->y_offset * dst_stride; + assert(prev_canvas != NULL); + WebPCopyPlane((uint8_t*)src, (int)(4 * src_stride), + (uint8_t*)dst, (int)(4 * dst_stride), + 4 * rect->width, rect->height); + } +} + +void GIFBlendFrames(const WebPPicture* const src, + const GIFFrameRect* const rect, WebPPicture* const dst) { + int i, j; + const size_t src_stride = src->argb_stride; + const size_t dst_stride = dst->argb_stride; + assert(src->width == dst->width && src->height == dst->height); + for (j = rect->y_offset; j < rect->y_offset + rect->height; ++j) { + for (i = rect->x_offset; i < rect->x_offset + rect->width; ++i) { + const uint32_t src_pixel = src->argb[j * src_stride + i]; + const int src_alpha = src_pixel >> 24; + if (src_alpha != 0) { + dst->argb[j * dst_stride + i] = src_pixel; + } + } + } +} + +void GIFDisplayError(const GifFileType* const gif, int gif_error) { + // libgif 4.2.0 has retired PrintGifError() and added GifErrorString(). +#if LOCAL_GIF_PREREQ(4,2) +#if LOCAL_GIF_PREREQ(5,0) + // Static string actually, hence the const char* cast. + const char* error_str = (const char*)GifErrorString( + (gif == NULL) ? gif_error : gif->Error); +#else + const char* error_str = (const char*)GifErrorString(); + (void)gif; +#endif + if (error_str == NULL) error_str = "Unknown error"; + fprintf(stderr, "GIFLib Error %d: %s\n", gif_error, error_str); +#else + (void)gif; + fprintf(stderr, "GIFLib Error %d: ", gif_error); + PrintGifError(); + fprintf(stderr, "\n"); +#endif +} + +#else // !WEBP_HAVE_GIF + +static void ErrorGIFNotAvailable() { + fprintf(stderr, "GIF support not compiled. Please install the libgif-dev " + "package before building.\n"); +} + +void GIFGetBackgroundColor(const struct ColorMapObject* const color_map, + int bgcolor_index, int transparent_index, + uint32_t* const bgcolor) { + (void)color_map; + (void)bgcolor_index; + (void)transparent_index; + (void)bgcolor; + ErrorGIFNotAvailable(); +} + +int GIFReadGraphicsExtension(const GifByteType* const data, int* const duration, + GIFDisposeMethod* const dispose, + int* const transparent_index) { + (void)data; + (void)duration; + (void)dispose; + (void)transparent_index; + ErrorGIFNotAvailable(); + return 0; +} + +int GIFReadFrame(struct GifFileType* const gif, int transparent_index, + GIFFrameRect* const gif_rect, + struct WebPPicture* const picture) { + (void)gif; + (void)transparent_index; + (void)gif_rect; + (void)picture; + ErrorGIFNotAvailable(); + return 0; +} + +int GIFReadLoopCount(struct GifFileType* const gif, GifByteType** const buf, + int* const loop_count) { + (void)gif; + (void)buf; + (void)loop_count; + ErrorGIFNotAvailable(); + return 0; +} + +int GIFReadMetadata(struct GifFileType* const gif, GifByteType** const buf, + struct WebPData* const metadata) { + (void)gif; + (void)buf; + (void)metadata; + ErrorGIFNotAvailable(); + return 0; +} + +void GIFDisposeFrame(GIFDisposeMethod dispose, const GIFFrameRect* const rect, + const struct WebPPicture* const prev_canvas, + struct WebPPicture* const curr_canvas) { + (void)dispose; + (void)rect; + (void)prev_canvas; + (void)curr_canvas; + ErrorGIFNotAvailable(); +} + +void GIFBlendFrames(const struct WebPPicture* const src, + const GIFFrameRect* const rect, + struct WebPPicture* const dst) { + (void)src; + (void)rect; + (void)dst; + ErrorGIFNotAvailable(); +} + +void GIFDisplayError(const struct GifFileType* const gif, int gif_error) { + (void)gif; + (void)gif_error; + ErrorGIFNotAvailable(); +} + +void GIFClearPic(struct WebPPicture* const pic, + const GIFFrameRect* const rect) { + (void)pic; + (void)rect; + ErrorGIFNotAvailable(); +} + +void GIFCopyPixels(const struct WebPPicture* const src, + struct WebPPicture* const dst) { + (void)src; + (void)dst; + ErrorGIFNotAvailable(); +} + +#endif // WEBP_HAVE_GIF + +// ----------------------------------------------------------------------------- diff --git a/third-party/webp/libwebp/examples/gifdec.h b/third-party/webp/libwebp/examples/gifdec.h new file mode 100644 index 0000000000..5eba9dd39e --- /dev/null +++ b/third-party/webp/libwebp/examples/gifdec.h @@ -0,0 +1,116 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// GIF decode. + +#ifndef WEBP_EXAMPLES_GIFDEC_H_ +#define WEBP_EXAMPLES_GIFDEC_H_ + +#include +#include "webp/types.h" + +#ifdef HAVE_CONFIG_H +#include "webp/config.h" +#endif + +#ifdef WEBP_HAVE_GIF +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// GIFLIB_MAJOR is only defined in libgif >= 4.2.0. +#if defined(GIFLIB_MAJOR) && defined(GIFLIB_MINOR) +# define LOCAL_GIF_VERSION ((GIFLIB_MAJOR << 8) | GIFLIB_MINOR) +# define LOCAL_GIF_PREREQ(maj, min) \ + (LOCAL_GIF_VERSION >= (((maj) << 8) | (min))) +#else +# define LOCAL_GIF_VERSION 0 +# define LOCAL_GIF_PREREQ(maj, min) 0 +#endif + +#define GIF_INDEX_INVALID (-1) + +typedef enum GIFDisposeMethod { + GIF_DISPOSE_NONE, + GIF_DISPOSE_BACKGROUND, + GIF_DISPOSE_RESTORE_PREVIOUS +} GIFDisposeMethod; + +typedef struct { + int x_offset, y_offset, width, height; +} GIFFrameRect; + +struct WebPData; +struct WebPPicture; + +#ifndef WEBP_HAVE_GIF +struct ColorMapObject; +struct GifFileType; +typedef unsigned char GifByteType; +#endif + +// Given the index of background color and transparent color, returns the +// corresponding background color (in BGRA format) in 'bgcolor'. +void GIFGetBackgroundColor(const struct ColorMapObject* const color_map, + int bgcolor_index, int transparent_index, + uint32_t* const bgcolor); + +// Parses the given graphics extension data to get frame duration (in 1ms +// units), dispose method and transparent color index. +// Returns true on success. +int GIFReadGraphicsExtension(const GifByteType* const buf, int* const duration, + GIFDisposeMethod* const dispose, + int* const transparent_index); + +// Reads the next GIF frame from 'gif' into 'picture'. Also, returns the GIF +// frame dimensions and offsets in 'rect'. +// Returns true on success. +int GIFReadFrame(struct GifFileType* const gif, int transparent_index, + GIFFrameRect* const gif_rect, + struct WebPPicture* const picture); + +// Parses loop count from the given Netscape extension data. +int GIFReadLoopCount(struct GifFileType* const gif, GifByteType** const buf, + int* const loop_count); + +// Parses the given ICC or XMP extension data and stores it into 'metadata'. +// Returns true on success. +int GIFReadMetadata(struct GifFileType* const gif, GifByteType** const buf, + struct WebPData* const metadata); + +// Dispose the pixels within 'rect' of 'curr_canvas' based on 'dispose' method +// and 'prev_canvas'. +void GIFDisposeFrame(GIFDisposeMethod dispose, const GIFFrameRect* const rect, + const struct WebPPicture* const prev_canvas, + struct WebPPicture* const curr_canvas); + +// Given 'src' picture and its frame rectangle 'rect', blend it into 'dst'. +void GIFBlendFrames(const struct WebPPicture* const src, + const GIFFrameRect* const rect, + struct WebPPicture* const dst); + +// Prints an error string based on 'gif_error'. +void GIFDisplayError(const struct GifFileType* const gif, int gif_error); + +// In the given 'pic', clear the pixels in 'rect' to transparent color. +void GIFClearPic(struct WebPPicture* const pic, const GIFFrameRect* const rect); + +// Copy pixels from 'src' to 'dst' honoring strides. 'src' and 'dst' are assumed +// to be already allocated. +void GIFCopyPixels(const struct WebPPicture* const src, + struct WebPPicture* const dst); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_EXAMPLES_GIFDEC_H_ diff --git a/third-party/webp/libwebp/examples/img2webp.c b/third-party/webp/libwebp/examples/img2webp.c new file mode 100644 index 0000000000..3735030c15 --- /dev/null +++ b/third-party/webp/libwebp/examples/img2webp.c @@ -0,0 +1,339 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// generate an animated WebP out of a sequence of images +// (PNG, JPEG, ...) +// +// Example usage: +// img2webp -o out.webp -q 40 -mixed -duration 40 input??.png +// +// Author: skal@google.com (Pascal Massimino) + +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include "webp/config.h" +#endif + +#include "../examples/example_util.h" +#include "../imageio/image_dec.h" +#include "../imageio/imageio_util.h" +#include "./stopwatch.h" +#include "./unicode.h" +#include "sharpyuv/sharpyuv.h" +#include "webp/encode.h" +#include "webp/mux.h" + +//------------------------------------------------------------------------------ + +static void Help(void) { + printf("Usage:\n\n"); + printf(" img2webp [file_options] [[frame_options] frame_file]..."); + printf(" [-o webp_file]\n\n"); + + printf("File-level options (only used at the start of compression):\n"); + printf(" -min_size ............ minimize size\n"); + printf(" -kmax .......... maximum number of frame between key-frames\n" + " (0=only keyframes)\n"); + printf(" -kmin .......... minimum number of frame between key-frames\n" + " (0=disable key-frames altogether)\n"); + printf(" -mixed ............... use mixed lossy/lossless automatic mode\n"); + printf(" -near_lossless . use near-lossless image preprocessing\n" + " (0..100=off), default=100\n"); + printf(" -sharp_yuv ........... use sharper (and slower) RGB->YUV " + "conversion\n " + "(lossy only)\n"); + printf(" -loop .......... loop count (default: 0, = infinite loop)\n"); + printf(" -v ................... verbose mode\n"); + printf(" -h ................... this help\n"); + printf(" -version ............. print version number and exit\n"); + printf("\n"); + + printf("Per-frame options (only used for subsequent images input):\n"); + printf(" -d ............. frame duration in ms (default: 100)\n"); + printf(" -lossless ........... use lossless mode (default)\n"); + printf(" -lossy ... ........... use lossy mode\n"); + printf(" -q ........... quality\n"); + printf(" -m ............. method to use\n"); + + printf("\n"); + printf("example: img2webp -loop 2 in0.png -lossy in1.jpg\n" + " -d 80 in2.tiff -o out.webp\n"); + printf("\nNote: if a single file name is passed as the argument, the " + "arguments will be\n"); + printf("tokenized from this file. The file name must not start with " + "the character '-'.\n"); + printf("\nSupported input formats:\n %s\n", + WebPGetEnabledInputFileFormats()); +} + +//------------------------------------------------------------------------------ + +static int ReadImage(const char filename[], WebPPicture* const pic) { + const uint8_t* data = NULL; + size_t data_size = 0; + WebPImageReader reader; + int ok; +#ifdef HAVE_WINCODEC_H + // Try to decode the file using WIC falling back to the other readers for + // e.g., WebP. + ok = ReadPictureWithWIC(filename, pic, 1, NULL); + if (ok) return 1; +#endif + if (!ImgIoUtilReadFile(filename, &data, &data_size)) return 0; + reader = WebPGuessImageReader(data, data_size); + ok = reader(data, data_size, pic, 1, NULL); + WebPFree((void*)data); + return ok; +} + +static int SetLoopCount(int loop_count, WebPData* const webp_data) { + int ok = 1; + WebPMuxError err; + uint32_t features; + WebPMuxAnimParams new_params; + WebPMux* const mux = WebPMuxCreate(webp_data, 1); + if (mux == NULL) return 0; + + err = WebPMuxGetFeatures(mux, &features); + ok = (err == WEBP_MUX_OK); + if (!ok || !(features & ANIMATION_FLAG)) goto End; + + err = WebPMuxGetAnimationParams(mux, &new_params); + ok = (err == WEBP_MUX_OK); + if (ok) { + new_params.loop_count = loop_count; + err = WebPMuxSetAnimationParams(mux, &new_params); + ok = (err == WEBP_MUX_OK); + } + if (ok) { + WebPDataClear(webp_data); + err = WebPMuxAssemble(mux, webp_data); + ok = (err == WEBP_MUX_OK); + } + + End: + WebPMuxDelete(mux); + if (!ok) { + fprintf(stderr, "Error during loop-count setting\n"); + } + return ok; +} + +//------------------------------------------------------------------------------ + +int main(int argc, const char* argv[]) { + const char* output = NULL; + WebPAnimEncoder* enc = NULL; + int verbose = 0; + int pic_num = 0; + int duration = 100; + int timestamp_ms = 0; + int loop_count = 0; + int width = 0, height = 0; + WebPAnimEncoderOptions anim_config; + WebPConfig config; + WebPPicture pic; + WebPData webp_data; + int c; + int have_input = 0; + CommandLineArguments cmd_args; + int ok; + + INIT_WARGV(argc, argv); + + ok = ExUtilInitCommandLineArguments(argc - 1, argv + 1, &cmd_args); + if (!ok) FREE_WARGV_AND_RETURN(1); + + argc = cmd_args.argc_; + argv = cmd_args.argv_; + + WebPDataInit(&webp_data); + if (!WebPAnimEncoderOptionsInit(&anim_config) || + !WebPConfigInit(&config) || + !WebPPictureInit(&pic)) { + fprintf(stderr, "Library version mismatch!\n"); + ok = 0; + goto End; + } + + // 1st pass of option parsing + for (c = 0; ok && c < argc; ++c) { + if (argv[c][0] == '-') { + int parse_error = 0; + if (!strcmp(argv[c], "-o") && c + 1 < argc) { + argv[c] = NULL; + output = (const char*)GET_WARGV_SHIFTED(argv, ++c); + } else if (!strcmp(argv[c], "-kmin") && c + 1 < argc) { + argv[c] = NULL; + anim_config.kmin = ExUtilGetInt(argv[++c], 0, &parse_error); + } else if (!strcmp(argv[c], "-kmax") && c + 1 < argc) { + argv[c] = NULL; + anim_config.kmax = ExUtilGetInt(argv[++c], 0, &parse_error); + } else if (!strcmp(argv[c], "-loop") && c + 1 < argc) { + argv[c] = NULL; + loop_count = ExUtilGetInt(argv[++c], 0, &parse_error); + if (loop_count < 0) { + fprintf(stderr, "Invalid non-positive loop-count (%d)\n", loop_count); + parse_error = 1; + } + } else if (!strcmp(argv[c], "-min_size")) { + anim_config.minimize_size = 1; + } else if (!strcmp(argv[c], "-mixed")) { + anim_config.allow_mixed = 1; + config.lossless = 0; + } else if (!strcmp(argv[c], "-near_lossless") && c + 1 < argc) { + argv[c] = NULL; + config.near_lossless = ExUtilGetInt(argv[++c], 0, &parse_error); + } else if (!strcmp(argv[c], "-sharp_yuv")) { + config.use_sharp_yuv = 1; + } else if (!strcmp(argv[c], "-v")) { + verbose = 1; + } else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) { + Help(); + FREE_WARGV_AND_RETURN(0); + } else if (!strcmp(argv[c], "-version")) { + const int enc_version = WebPGetEncoderVersion(); + const int mux_version = WebPGetMuxVersion(); + const int sharpyuv_version = SharpYuvGetVersion(); + printf("WebP Encoder version: %d.%d.%d\nWebP Mux version: %d.%d.%d\n", + (enc_version >> 16) & 0xff, (enc_version >> 8) & 0xff, + enc_version & 0xff, (mux_version >> 16) & 0xff, + (mux_version >> 8) & 0xff, mux_version & 0xff); + printf("libsharpyuv: %d.%d.%d\n", (sharpyuv_version >> 24) & 0xff, + (sharpyuv_version >> 16) & 0xffff, sharpyuv_version & 0xff); + goto End; + } else { + continue; + } + ok = !parse_error; + if (!ok) goto End; + argv[c] = NULL; // mark option as 'parsed' during 1st pass + } else { + have_input |= 1; + } + } + if (!have_input) { + fprintf(stderr, "No input file(s) for generating animation!\n"); + goto End; + } + + // image-reading pass + pic_num = 0; + config.lossless = 1; + for (c = 0; ok && c < argc; ++c) { + if (argv[c] == NULL) continue; + if (argv[c][0] == '-') { // parse local options + int parse_error = 0; + if (!strcmp(argv[c], "-lossy")) { + if (!anim_config.allow_mixed) config.lossless = 0; + } else if (!strcmp(argv[c], "-lossless")) { + if (!anim_config.allow_mixed) config.lossless = 1; + } else if (!strcmp(argv[c], "-q") && c + 1 < argc) { + config.quality = ExUtilGetFloat(argv[++c], &parse_error); + } else if (!strcmp(argv[c], "-m") && c + 1 < argc) { + config.method = ExUtilGetInt(argv[++c], 0, &parse_error); + } else if (!strcmp(argv[c], "-d") && c + 1 < argc) { + duration = ExUtilGetInt(argv[++c], 0, &parse_error); + if (duration <= 0) { + fprintf(stderr, "Invalid negative duration (%d)\n", duration); + parse_error = 1; + } + } else { + parse_error = 1; // shouldn't be here. + fprintf(stderr, "Unknown option [%s]\n", argv[c]); + } + ok = !parse_error; + if (!ok) goto End; + continue; + } + + if (ok) { + ok = WebPValidateConfig(&config); + if (!ok) { + fprintf(stderr, "Invalid configuration.\n"); + goto End; + } + } + + // read next input image + pic.use_argb = 1; + ok = ReadImage((const char*)GET_WARGV_SHIFTED(argv, c), &pic); + if (!ok) goto End; + + if (enc == NULL) { + width = pic.width; + height = pic.height; + enc = WebPAnimEncoderNew(width, height, &anim_config); + ok = (enc != NULL); + if (!ok) { + fprintf(stderr, "Could not create WebPAnimEncoder object.\n"); + } + } + + if (ok) { + ok = (width == pic.width && height == pic.height); + if (!ok) { + fprintf(stderr, "Frame #%d dimension mismatched! " + "Got %d x %d. Was expecting %d x %d.\n", + pic_num, pic.width, pic.height, width, height); + } + } + + if (ok) { + ok = WebPAnimEncoderAdd(enc, &pic, timestamp_ms, &config); + if (!ok) { + fprintf(stderr, "Error while adding frame #%d\n", pic_num); + } + } + WebPPictureFree(&pic); + if (!ok) goto End; + + if (verbose) { + WFPRINTF(stderr, "Added frame #%3d at time %4d (file: %s)\n", + pic_num, timestamp_ms, GET_WARGV_SHIFTED(argv, c)); + } + timestamp_ms += duration; + ++pic_num; + } + + // add a last fake frame to signal the last duration + ok = ok && WebPAnimEncoderAdd(enc, NULL, timestamp_ms, NULL); + ok = ok && WebPAnimEncoderAssemble(enc, &webp_data); + if (!ok) { + fprintf(stderr, "Error during final animation assembly.\n"); + } + + End: + // free resources + WebPAnimEncoderDelete(enc); + + if (ok && loop_count > 0) { // Re-mux to add loop count. + ok = SetLoopCount(loop_count, &webp_data); + } + + if (ok) { + if (output != NULL) { + ok = ImgIoUtilWriteFile(output, webp_data.bytes, webp_data.size); + if (ok) WFPRINTF(stderr, "output file: %s ", (const W_CHAR*)output); + } else { + fprintf(stderr, "[no output file specified] "); + } + } + + if (ok) { + fprintf(stderr, "[%d frames, %u bytes].\n", + pic_num, (unsigned int)webp_data.size); + } + WebPDataClear(&webp_data); + ExUtilDeleteCommandLineArguments(&cmd_args); + FREE_WARGV_AND_RETURN(ok ? 0 : 1); +} diff --git a/third-party/webp/libwebp/examples/stopwatch.h b/third-party/webp/libwebp/examples/stopwatch.h new file mode 100644 index 0000000000..f1b0faca02 --- /dev/null +++ b/third-party/webp/libwebp/examples/stopwatch.h @@ -0,0 +1,63 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Helper functions to measure elapsed time. +// +// Author: Mikolaj Zalewski (mikolajz@google.com) + +#ifndef WEBP_EXAMPLES_STOPWATCH_H_ +#define WEBP_EXAMPLES_STOPWATCH_H_ + +#include "webp/types.h" + +#if defined _WIN32 && !defined __GNUC__ +#include + +typedef LARGE_INTEGER Stopwatch; + +static WEBP_INLINE void StopwatchReset(Stopwatch* watch) { + QueryPerformanceCounter(watch); +} + +static WEBP_INLINE double StopwatchReadAndReset(Stopwatch* watch) { + const LARGE_INTEGER old_value = *watch; + LARGE_INTEGER freq; + if (!QueryPerformanceCounter(watch)) + return 0.0; + if (!QueryPerformanceFrequency(&freq)) + return 0.0; + if (freq.QuadPart == 0) + return 0.0; + return (watch->QuadPart - old_value.QuadPart) / (double)freq.QuadPart; +} + + +#else /* !_WIN32 */ +#include // memcpy +#include + +typedef struct timeval Stopwatch; + +static WEBP_INLINE void StopwatchReset(Stopwatch* watch) { + gettimeofday(watch, NULL); +} + +static WEBP_INLINE double StopwatchReadAndReset(Stopwatch* watch) { + struct timeval old_value; + double delta_sec, delta_usec; + memcpy(&old_value, watch, sizeof(old_value)); + gettimeofday(watch, NULL); + delta_sec = (double)watch->tv_sec - old_value.tv_sec; + delta_usec = (double)watch->tv_usec - old_value.tv_usec; + return delta_sec + delta_usec / 1000000.0; +} + +#endif /* _WIN32 */ + +#endif // WEBP_EXAMPLES_STOPWATCH_H_ diff --git a/third-party/webp/libwebp/examples/test.webp b/third-party/webp/libwebp/examples/test.webp new file mode 100644 index 0000000000000000000000000000000000000000..3e4bca1d8500ec465177ebac7c30d6cfde656c10 GIT binary patch literal 4880 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 Cu81!H literal 0 HcmV?d00001 diff --git a/third-party/webp/libwebp/examples/test_ref.ppm b/third-party/webp/libwebp/examples/test_ref.ppm new file mode 100644 index 0000000000..97719f01f0 --- /dev/null +++ b/third-party/webp/libwebp/examples/test_ref.ppm @@ -0,0 +1,4 @@ +P6 +128 128 +255 +ËáûËáûËáûËáûËáûËáûËáûËáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÍâýÍâýÍâýÍâýÎãþÎãþÎãþÎãþÎãþÎãþÎãþÎãþÎãûÎãûÎãûÎãûÏäýÏäýÏäýÏäýÐãýÐãýÐãýÐãýÒäþÒäþÒäþÒäþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÒäþÒäþÒäþÒäþÓåÿÓåÿÓåÿÓåÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèýÔèýÔèýÔèýÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÔêûÔêûÔêûÔêûÔêûÔêûÔêûÔêûÓéúÓéúÓéúÓéúÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÏå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷ËáûËáûËáûËáûËáûËáûËáûËáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÍâýÍâýÍâýÍâýÎãþÎãþÎãþÎãþÎãþÎãþÎãþÎãþÎãûÎãûÎãûÎãûÏäýÏäýÏäýÏäýÏäýÐãýÐãýÐãýÒäþÒäþÒäþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÒäþÒäþÒäþÒäþÓåÿÓåÿÓåÿÓåÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèýÔèýÔèýÔèýÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÔêûÔêûÔêûÔêûÔêûÔêûÔêûÔêûÓéúÓéúÓéúÓéúÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÏå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷ËáûËáûËáûËáûËáûËáûËáûËáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÍâýÍâýÍâýÍâýÎãþÎãþÎãþÎãþÎãþÎãþÎãþÎãþÎãûÎãûÎãûÎãûÏäýÏäýÏäýÏäýÏäûÏäûÏäûÏäûÐåýÐåýÐåýÐåýÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÒäþÒäþÒäþÒäþÓåÿÓåÿÓåÿÓåÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèýÔèýÔèýÔèýÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÔêûÔêûÔêûÔêûÔêûÔêûÔêûÔêûÓéúÓéúÓéúÓéúÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÏå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷ËáûËáûËáûËáûËáûËáûËáûËáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÌáûÍâýÍâýÍâýÍâýÎãþÎãþÎãþÎãþÎãþÎãþÎãþÎãþÎãûÎãûÎãûÎãûÏäýÏäýÏäýÏäýÎåûÎåûÎåûÎåûÏæýÏæýÏæýÏæýÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÒäþÒäþÒäþÒäþÓåÿÓåÿÓåÿÓåÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèýÔèýÔèýÔèýÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÔêûÔêûÔêûÔêûÔêûÔêûÔêûÔêûÓéúÓéúÓéúÓéúÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÏå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷Ïå÷ËáûËáûËáûËáûÌâýÌâýÌâýÌâýÍâýÍâýÍâýÍâýÍâýÍâýÍâýÍâýÎãþÎãþÎãþÎãþÎãþÎãþÎãþÎãþÏäÿÏäÿÏäÿÏäÿÏäÿÏäÿÏäÿÏäÿÏäýÏäýÏäýÏäýÐåþÐåþÐåþÐåþÎåûÎåùÎåùÎåùÏæúÏæúÏæúÏæýÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÓåÿÓåÿÓåÿÓåÿÔæÿÔæÿÔæÿÔæÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÖêÿÖêÿÖêÿÖêÿÔêûÔêûÔêûÔêûÔêûÔêûÔêûÔêûÓéúÓéúÓéúÓéúÒèùÒèùÒèùÒèùÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÏå÷Ïå÷Ïå÷Ïå÷ËáûËáûËáûËáûÌâýÌâýÌâýÌâýÍâýÍâýÍâýÍâýÍâýÍâýÍâýÍâýÎãþÎãþÎãþÎãþÎãþÎãþÎãþÎãþÏäÿÏäÿÏäÿÏäÿÏäÿÏäÿÏäÿÏäÿÏäýÏäýÏäýÏäýÐåþÐåþÐåþÐåýÒèûÒèûÒèûÒèûÐæúÐæúÐæúÐæúÐåýÐåþÐåþÐåþÐåþÐåþÐåþÐåþÓåÿÓåÿÓåÿÓåÿÔæÿÔæÿÔæÿÔæÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÖêÿÖêÿÖêÿÖêÿÔêûÔêûÔêûÔêûÔêûÔêûÔêûÔêûÓéúÓéúÓéúÓéúÒèùÒèùÒèùÒèùÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÏå÷Ïå÷Ïå÷Ïå÷ËáûËáûËáûËáûÌâýÌâýÌâýÌâýÍâýÍâýÍâýÍâýÍâýÍâýÍâýÍâýÎãþÎãþÎãþÎãþÎãþÎãþÎãþÎãþÏäÿÏäÿÏäÿÏäÿÏäÿÏäÿÏäÿÏäÿÏäýÏäýÏäýÏäýÐåþÐåþÐåþÐåýÐæúÒåøÒåøÒåøÒåøÒåøÒåøÐæúÐåýÐåþÐåþÐåþÐåþÐåþÐåþÐåþÓåÿÓåÿÓåÿÓåÿÔæÿÔæÿÔæÿÔæÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÖêÿÖêÿÖêÿÖêÿÔêûÔêûÔêûÔêûÔêûÔêûÔêûÔêûÓéúÓéúÓéúÓéúÒèùÒèùÒèùÒèùÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÏå÷Ïå÷Ïå÷Ïå÷ËáûËáûËáûËáûÌâýÌâýÌâýÌâýÍâýÍâýÍâýÍâýÍâýÍâýÍâýÍâýÎãþÎãþÎãþÎãþÎãþÎãþÎãþÎãþÏäÿÏäÿÏäÿÏäÿÏäÿÐãÿÐãÿÐãÿÏäýÏäýÏäýÐãýÒäþÒåýÒåýÒåýÏáóÏáóÏáóÏáñÔåöÔåöÔåöÔåøÒåúÒåýÒåýÐåýÐåýÐåýÐåýÐåþÓåÿÓåÿÓåÿÓåÿÔæÿÔæÿÔæÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÔèÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéÿÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÖêÿÖêÿÖêÿÖêÿÔêûÔêûÔêûÔêûÔêûÔêûÔêûÔêûÓéúÓéúÓéúÓéúÒèùÒèùÒèùÒèùÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÏå÷Ïå÷Ïå÷Ïå÷ÍâýÍâýÍâýÍâýÎãþÎãþÎãþÎãþÎãûÎãûÎãûÎãûÏäýÏäýÏäýÏäýÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÒæÿÐåþÒäþÐãýÎáúÒâûÐáúÕåÿÎáýÔæÿÔæÿÓãýÏßøÉÚð·ÆÜ‡–ª‰—©›­±»ÎŸª»©³ÅÌÖèÖáòÓáñÖèøÔåö×éûÒåøÒåúÖêÿÐæúÒæþÓæþÓæþÓæþÓæþÔèÿÔèÿÔèÿÔèýÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÕëÿÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëý×ëþ×ëþ×ëþ×ëþÖêýÖêýÖêýÖêýÕéûÕéûÕéûÕéûÔèúÔèúÔèúÔèúÓæùÓæùÓæùÓæùÒåøÒåøÒåøÒåøÐæøÐæøÐæøÐæøÏå÷Ïå÷Ïå÷Ïå÷ÍâýÍâýÍâýÍâýÎãþÎãþÎãþÎãþÎãûÎãûÎãûÎãûÏäýÏäýÏäýÏäýÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÒäþÒäþÓãý×èÿÕãþÒßúÕäÿÌÛøÈÙò«Åm{•dqˆhtŒlvŒs{…‹y‘‡Ÿ‘—¨¤ªº°¶Æ½ÆÕÎÜêÓäóÕæ÷ÔåöÖèúÓæùÐäùÔêþÓæûÓæûÓæûÓæûÔèýÔèýÔèýÔèýÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëý×ëþ×ëþ×ëþ×ëþÖêýÖêýÖêýÖêýÕéûÕéûÕéûÕéûÔèúÔèúÔèúÔèúÓæùÓæùÓæùÓæùÒåøÒåøÒåøÒåøÐæøÐæøÐæøÐæøÏå÷Ïå÷Ïå÷Ïå÷ÍâýÍâýÍâýÍâýÎãþÎãþÎãþÎãþÎãûÎãûÎãûÎãûÏäýÏäýÏäýÏäýÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÌáùÎãûÓåÿÕèÿÒâûÓãýÔâýÙæÿÓáû©·Òlz•\j„mz”hqŒmw‚‹¡†‰ž¥‚–‡‹ž‚”°³Å¸½Ë•›©¿ËÙÓãòÖæö׿øÔåöÖèúÕéûÐä÷ÓæûÓæûÓæûÓæûÔèýÔèýÔèýÔèýÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëý×ëþ×ëþ×ëþ×ëþÖêýÖêýÖêýÖêýÕéûÕéûÕéûÕéûÔèúÔèúÔèúÔèúÓæùÓæùÓæùÓæùÒåøÒåøÒåøÒåøÐæøÐæøÐæøÐæøÏå÷Ïå÷Ïå÷Ïå÷ÍâýÍâýÍâýÍâýÎãþÎãþÎãþÎãþÎãûÎãûÎãûÎãûÏäýÏäýÏäýÏäýÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÓèÿÒæÿÐãýÏâûÓãýÕåÿ±¿Úªr€›Wd~\i‚~‹¤˜¢½jq‡Žªz˜„…›œ²‚„š…†›‚…–—𩲴Á¯³¿–Ÿ¬±½ËÆÔäÔâòÙèùÔãôÖèúÕæùÓæûÓæûÓæûÓæûÔèýÔèýÔèýÔèýÕéþÕéþÕéþÕéþÕéþÕéþÕéþÕéþÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëýÕëý×ëþ×ëþ×ëþ×ëþÖêýÖêýÖêýÖêýÕéûÕéûÕéûÕéûÔèúÔèúÔèúÔèúÓæùÓæùÓæùÓæùÒåøÒåøÒåøÒåøÐæøÐæøÐæøÐæøÏå÷Ïå÷Ïå÷Ïå÷ÎãþÎãþÎãþÎãþÏäÿÏäÿÏäÿÏäÿÏäýÏäýÏäýÏäýÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÓèÿÉÞ÷ÚìÿÔæÿÈÙòy‰£M[vXfVc}[deo‰ipŒ‡Žªfj‡Œ¬xz—}}˜~{•qo†‘¥—–©‰ˆ˜——¤ž¡­ÆÌÚ½ÆÕ˜¢±¯¹ËÖáò×å÷Úèù׿úÖæýÔèýÔèýÔèýÔèýÔèýÔèýÔèýÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþ×íÿ×íÿ×íÿ×íÿ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþÖêýÕéûÔèúÕéûÕéûÕéûÕéûÓæùÓæùÓæùÓæùÓæùÓæùÓæùÓæùÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÎãþÎãþÎãþÎãþÏäÿÏäÿÏäÿÏäÿÏäýÏäýÏäýÏäýÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÒæÿÒäþÅ×ñfwM]wLZtMZsOXq_f€jq~žrv“rs“ˆ‰©……¤ss‘vs}–ž²›š¬€€šš¥¤¨²·»Ç‹ž‘—¨ˆ‘¡­¶ÈÓÝïÚä÷ÛéúÖèúÔèýÔèýÔèýÔèýÔèýÔèýÔèýÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþ×íÿ×íÿ×íÿ×íÿ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþÖêýÕéûÔèúÕéûÕéûÕéûÕéûÓæùÓæùÓæùÓæùÓæùÓæùÓæùÓæùÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÎãþÎãþÎãþÎãþÏäÿÏäÿÏäÿÏäÿÏäýÏäýÏäýÏäýÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÒæÿÏäý½ÏéXk…IZsL\vP^yN[tbi‚sx‘Ž“¬€‚Ÿ~€‚‚¢©¨Ë¡}}›qq~—œ²œž­‚…‘±´¿¤¨²„¨¬º{€Ž‰Ÿ˜ž¯³»Î×ßò×å÷ÖèúÔèýÔèýÔèýÔèýÔèýÔèýÔèýÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþ×íÿ×íÿ×íÿ×íÿ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþÖêýÕéûÔèúÕéûÕéûÕéûÕéûÓæùÓæùÓæùÓæùÓæùÓæùÓæùÓæùÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÎãþÎãþÎãþÎãþÏäÿÏäÿÏäÿÏäÿÏäýÏäýÏäýÏäýÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåýÐåýÐåþÐåþÍßù[m‡GWqLZtIWrFQmox“›Ÿ´¡¤¸‘•ªyzss¤¤Â½¹Ù²°Ì‰‹£lm„z{vx‰œž««¯¹ÌÏÚ“›Œš›ž©˜›¨„‘•£ª°ÀÔÚê×âó׿úÔèýÔèýÔèýÔèýÔèýÔèýÔèýÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖêÿÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþÖìþ×íÿ×íÿ×íÿ×íÿ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþÖêýÕéûÔèúÕéûÕéûÕéûÕéûÓæùÓæùÓæùÓæùÓæùÓæùÓæùÓæùÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐæøÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÏåÿÏåÿÏæþÏæþÎãúÏåùÖêÿÒåýºÍæk~šJXvLWvLTqFNkQXtlqˆÆÈÚ£¥²áäï··Ä…„–£¢·ÎÍâÝÜïìëû¸¸Å£¢²yy†——£²²»ººÆˆˆ‘•–œž¤­­·•˜£‚…‘¡¥±¬±¿ÕÞíÖå÷×éûÔèúÓæùÔêþÔêþÔéÿÕéþÖêÿÙêýÙêýÙêýÙêýÙêýÙêýÙêýÖêýÖêýÖêýÖêý×ëþ×ëþ×ëþ×ëþ×íÿ×íý×íý×íý×íý×íý×íý×íý×íý×íý×íý×íý×íý×íý×íý×íýÙíýÙíýÙíýÙíý×ìû×ìû×ìû×ìû×íýÖìûÕëúÔêùÔêùÔêùÔêùÔêùÓéøÓéøÓéøÓéøÒè÷Òè÷Òè÷Òè÷ÐæöÐæöÐæöÐæöÐæöÐæöÐæöÐæöÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÏåÿÏåÿÏæþÐåýÕêÿÐäùÏãø¬ÀÕVi‚IXvN\yHPpLSpHOlei†¨“•¢²²»ÚÛáÒÒÛ‚‘”“£º¹ÉÌÌÙ°°»——£ŒŒ˜yy†··À££¬žžª‹›š¡¯­´ªª³»»Åª­¸œŸªšžª£©·ÌÚêÒãóÚëûÚíÿÕéûÔêþÔéÿÕéþÙêýÙêýÙêýÙêýÙêýÙêýÙêýÙêýÖêýÖêýÖêýÖêý×ëþ×ëþ×ëþ×ëþ×íý×íý×íý×íý×íý×íý×íý×íý×ïû×ïû×ïû×ïû×ïû×ïû×ïû×ïûÙíûÙíûÙíûÙíû×ìú×ìú×ìú×ìú×ïûÖíúÕìùÔëøÔëøÔëøÔëøÔëøÓê÷Óê÷Óê÷Óê÷ÒéöÒéöÒéöÒéöÐèôÐèôÐèôÐèôÐèôÐèôÐèôÐèôÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÏæþÏæþÐåþÐåýÐäûÐäû½ÍãSc{FVpIWtS^}MUtLSpHOllp“•­ˆ‹š¡©Ž‘—‰•jly…‡–wy†“Ÿikxjlysv…ˆ‹šÉÍ×…ˆ“xz‡œ¦¥¯©¨±šš£­­·²¶À•˜£¦«¶‡Ž˜¦²ÀÈÖæ×è÷×éùÙêýÕéþÕéþÕéþÙêýÙêýÙêýÙêýÙêýÙêýÙêýÙêýÖêýÖêýÖêýÖêý×ëþ×ëþ×ëþ×ëþ×íý×íý×íý×íý×íý×íý×íý×íý×ïû×ïû×ïû×ïû×ïû×ïû×ïû×ïûÙíûÙíûÙíûÙíû×ìú×ìú×ìú×ìú×ïûÖíúÕìùÔëøÔëøÔëøÔëøÔëøÓê÷Óê÷Óê÷Óê÷ÒéöÒéöÒéöÒéöÐèôÐèôÐèôÐèôÐèôÐèôÐèôÐèôÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÏæþÐåýÐåýÒåýÒåý£³ÌTd}IWqIWrQ]{P\zOWwLTqFMjcf„z–il~x{†y}…z~ˆ]_o~€¥¨´kmzikxehw^artwˆŽ~€‡‰˜sv…iit£¢«ÂÂÌ••ž‰—}€‹‘–¡†‹•—ž©ÌÕâÖâðÝëûÜëý×éûÕéûÕéþÙêýÙêýÙêýÙêýÙêýÙêýÙêýÙêýÖêýÖêýÖêýÖêý×ëþ×ëþ×ëþ×ëþ×íý×íý×íý×íý×íý×íý×íý×íý×ïû×ïû×ïû×ïû×ïû×ïû×ïû×ïûÙíûÙíûÙíûÙíû×ìú×ìú×ìú×ìú×ïûÖíúÕìùÔëøÔëøÔëøÔëøÔëøÓê÷Óê÷Óê÷Óê÷ÒéöÒéöÒéöÒéöÐèôÐèôÐèôÐèôÐèôÐèôÐèôÐèôÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÓèÿÎãúÕéÿÈÜóqšIZrJXrIWrO[yJVtPXxT\{FNkV]zv}˜osX\pqv„fkw‚‡“fj{ˆŒ†‘sx„†‹˜y}Žhkei}X]kty‡‡‹œcewbbo†„°°»½½È±´½ÇËÓ·½Ä¡¦­·»Æ¶ºÅÀÇÒ×ãïÙæ÷ÙèùÖèúÙìÿÖêýÖêýÖêýÖêý×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþÙìÿÙìÿÙìÿÙìÿ×íý×íý×íý×íý×íý×íý×íý×íý×ïû×ïû×ïû×ïû×ïû×ïû×ïû×ïûÙíûÙíûÙíûÙíû×ìú×ìú×ìú×ìúÕìùÕìùÕìùÕìùÔëøÔëøÔëøÔëøÔëøÔëøÔëøÔëøÓê÷Óê÷Óê÷Óê÷ÒéöÒéöÒéöÒéöÐèôÐèôÐèôÐèôÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåýÎäøÓæûÄ×ï^o‡HXqM[vDQlP\xNZxIUsLTsMUtHPm]e‚krŽSZsSWoW[pfj{qt†txŒjm]arZ^lmq‚^bv[^sdh}fj{dhyil€ehy~~‹˜–£¢¢­©©´¢¥­»¿Çª°·±·¾ÁÅËÌÏ×¶ºÅÁÈÓÚåóÚèøÛìýÖêýÖêýÖêýÖêýÖêý×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþ×ëþÙìÿÙìÿÙìÿÙìÿ×íý×íý×íý×íý×íý×íý×íý×íý×ïû×ïû×ïû×ïû×ïû×ïû×ïû×ïûÙíûÙíûÙíûÙíû×ìú×ìú×ìú×ìúÕìùÕìùÕìùÕìùÔëøÔëøÔëøÔëøÔëøÔëøÔëøÔëøÓê÷Óê÷Óê÷Óê÷ÒéöÒéöÒéöÒéöÐèôÐèôÐèôÐèôÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåýÕéþ²ÆÛTdzEUmM[tAOjWcMXwJSrS[zIQqJSr[c€^f„NWrLSoPTqINhW\sim‚X]tae}V\oX^qU[m]bwW\s]bykq„flV[pTWkqp€•“¡ªª¶˜˜¤ˆŒ”Œ—…‹²¶»·¸»ÌËÏÚÝå½Á̹ÂÏÔâòÛêûÕéûÖêýÕëýÕëýÕëýÖìþÖìþÖìþÖìþ×ëþ×ëþ×ëþ×ëþÙìÿÙìÿÙìÿÙìÿ×íý×íý×íý×íý×íý×íý×íý×íý×ïû×ïû×ïû×ïû×ïû×ïû×ïû×ïûÙíûÙíûÙíûÙíû×ìú×ìú×ìú×ìúÕìùÕìùÕìùÕìùÔëøÔëøÔëøÔëøÔëøÔëøÔëøÔëøÓê÷Óê÷Óê÷Óê÷ÒéöÒéöÒéöÒéöÐèôÐèôÐèôÐèôÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÐåþÒåý³ÄÚN^tIZpIWqHVqQ_zJXvLWvNZxEPoLWvQZyV^{W_}U\yOVsQUsTWt{€š\azSWqPUoPUlOTiV[pmr‡TXrOTmmr‡x}‘_d{X\qz}Œœœ¨›––¢z~ˆ†‰”{‰ww€Œ‹‘ÆÅÌÌÌÕ¥ª´°·ÁÅÐÞ×åöÛëúÙêúÖêýÖêýÕëýÖìþÖìþÖìþÖìþ×ëþ×ëþ×ëþ×ëþÙìÿÙìÿÙìÿÙìÿ×íý×íý×íý×íý×íý×íý×íý×íý×ïû×ïû×ïû×ïû×ïû×ïû×ïû×ïûÙíûÙíûÙíûÙíû×ìú×ìú×ìú×ìúÕìùÕìùÕìùÕìùÔëøÔëøÔëøÔëøÔëøÔëøÔëøÔëøÓê÷Óê÷Óê÷Óê÷ÒéöÒéöÒéöÒéöÐèôÐèôÐèôÐèôÒæþÒæþÒæþÒæþÓèÿÓèÿÓèÿÓèÿÒäþÔæÿÕèÿÐãýÐãýÕèÿÕèÿ¨¸ÒZhN[tN[tO]xQ_zM[vLZtL\vJZwBQoP^{Q]{W_W]~W[{UXwQUs\_}hl†TXrLOmIMkDGdDH_EI^‚‡œlq‹TXr~‚š„›TWtaeqv„¦ª´‡‹•~€qp€‡†–Œœ‚€‰‡”¡Ÿ©ÅÅг·Á¡¥°¤©³ÅÌÕÙâìÜêúÞíÿÚëûÖëúÖìû×íý×ðþÙñÿ×íýÙíýÙíýÙíýÙíýÙíýÙíýÙíý×íý×ïû×ïû×ïûÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðúÙðúÙðúÙðú×ïù×ïù×ïù×ïùÖíúÖíúÖíúÖíúÕìùÕìùÕìùÕìùÕìùÔëøÔëøÔëøÓê÷Óê÷ÒéöÒéöÓê÷ÒéöÒéöÒéöÒéöÐèôÐèôÐèôÒæþÒæþÒæþÒæþÓèÿÓèÿÓèÿÓèÿÒäþÖéÿÒäþÓåÿÐãýÐãý}©O_yNZvNVsLWsQ]yLWsN\wN\wHXrIZsHWtSa~S^}[abe†hi‹WXxW[yVZwZ^xTWtPTrOSqNQoBGaINc{€•^c}[_y–›²€…œX\yQVpjo}ˆ—¢¤±­°¿wv†‰ˆ›‰†šš–ª‰‡•rp}——£¿¿Ë„‡¢¥­»ÁÆÉÐÚÝé÷ÙæøÜëýÝïÿÚïþÙïþÖïýÕíû×íýÙíýÙíýÙíýÙíýÙíýÙíýÙíý×ïû×ïû×ïû×ïûÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðúÙðúÙðúÙðú×ïù×ïù×ïù×ïùÖíúÖíúÖíúÖíúÕìùÕìùÕìùÕìùÕìùÕìùÕìùÔëøÓê÷Óê÷Óê÷Óê÷Óê÷Óê÷ÒéöÒéöÒéöÒéöÐèôÐèôÒæþÒæþÒæþÒæþÓèÿÓèÿÓèÿÓèÿÔæÿÓãýÖæÿÕåÿÛëÿw‡¡M]wDQlLWsLTqS[xV^{O[wS^zLWsBPkLZtO]xUa}Zbls_copž^bUXv\azW\vGJiHLjMPmFJbIObX^qZ^vy~•Ÿ¥¸w{UZq[_tty‡ty…‡‰–ž…„”‰ˆ˜£¡±¬ªº»»Èvv‚‹ŸŸ«¦ª²©¬´¤¨°¹¾ÈÛæôÛéùÛëúÙêùÛðþÙðýÖïûÕíú×íýÙíýÙíýÙíýÙíýÙíýÙíýÙíý×ïû×ïû×ïû×ïûÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðúÙðúÙðúÙðú×ïù×ïù×ïù×ïùÖíúÖíúÖíúÖíúÕìùÕìùÕìùÕìùÕìùÕìùÕìùÕìùÔëøÓê÷Óê÷Óê÷Óê÷Óê÷Óê÷ÒéöÒéöÒéöÒéöÐèôÒæþÒæþÒæþÒæþÓèÿÓèÿÓèÿÔèÿÖæÿÔäþÓãý×èÿ~ލHXrHXrIWrIUqMUrQZwNVsQZwPXvNVsJVrS_yO\vU^y^eVZw^bsv“†ˆ¥y}šUZs]byX]wPTqPTqMQkNSjPViLQdSWo~‚—ž¤·jp‚]bw[_trv‡UZhZ\kkm}€šš¦±¯½À¾Ì©©¶ffsxx…‰‰•Œš–š¢˜œ¤ž£­ÆÏÞÝëûÜêúÛëúÙíûÖíúÙðýÚñþÙíýÙíýÙíýÙíýÙíýÙíýÙíýÙíý×ïû×ïû×ïû×ïûÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðúÙðúÙðúÙðú×ïù×ïù×ïù×ïùÖíúÖíúÖíúÖíúÕìùÕìùÕìùÕìùÕìùÕìùÕìùÕìùÔëøÔëøÔëøÓê÷Óê÷Óê÷Óê÷Óê÷ÒéöÒéöÒéöÒéöÒæþÒæþÒæþÒæþÒæþÒæþÒæþÓæþÚêÿÏÝøÎÜ÷hvHVqHVqHVqGUpHTpOWtU]zLTqLTqOVsLSpS\wOXqV]wU\v]b{ptŽjoˆkmˆz}—kp‰X]wLPhNSjTWtOSpW\vLPhMQfPUjV[rae}U[mU[mkp…X]r^bv^bvehybdseerŸŸ«©¦³¢Ÿ¬‹‰škm}fixtw„Œ˜˜¢¤±Ÿ¥³ÎÚèÜêøÙéöÞñýÙíùÙðúÕìùÚïþÚïþÚïþÚïþÚïþÚïþÚïþÚïþÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÚñþÚñþÚñþÚñþÚñþÚñþÚñþÚñþÚñûÚñûÚñûÚñûÙðúÙðúÙðúÙðú×ïû×ïû×ïû×ïûÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÕìùÔëøÔëøÔëøÔëøÔëøÔëøÓê÷ÒéöÒéöÒéöÒæþÒæþÒæþÒæþÒæþÒæþÒæþÓæþÕåÿÎÜ÷drFToIWrESmFToMXtS^zU]zHPmLSpJQoU\y\c€sw”[_w\ax^czdi€chchdf_bzSWoNSjX]r\ax\azOTmPUlae}QVmHMdLPjINhMQfdj}y~“ejVZojm‚€–‹œŽ‡‡“¨¦°žž¨y{‹…‡˜€‚‘z}Œ}{Œœ‘‘ž¨ª·•›©ÀÉÙÙäòÙæôÚê÷ÜïúÙíùÛòýÚïýÚïþÚïþÚïþÚïþÚïþÚïþÚïþÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÚñþÚñþÚñþÚñþÚñþÚñþÚñþÚñþÚñûÚñûÚñûÚñûÙðúÙðúÙðúÙðú×ïû×ïû×ïû×ïûÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÕìùÔëøÔëøÔëøÔëøÔëøÓê÷ÒéöÒéöÒæþÒæþÒæþÒæþÒæþÒæþÒæþÓæþÕãþw‚žHTpMXtO[wLWsNZvT_{P\xLTqIQoLSpOSq\_~il‹„¡mpˆSVkdh}…ˆW[p[^sUZoNShV[r_h~^fzw“qx‘PWqPXockDJdGNjNUqFMiXawt}€ˆœV[rSUmtw‘¦”–¨ª››¤±°·‰‹xz‡‚”„†—‹ž}{Œ”“£œš¨´´Á‘–¤¦°½ËÖâÜëöÝíøÝðù×íöÚïúÚïýÚïþÚïþÚïþÚïþÚïþÚïþÚïþÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÚñþÚñþÚñþÚñþÚñþÚñþÚñþÚñþÚñûÚñûÚñûÚñûÙðúÙðúÙðúÙðú×ïû×ïû×ïû×ïûÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÔëøÔëøÔëøÔëøÔëøÔëøÓê÷ÒéöÒæÿÒæþÒæþÒæþÒæþÓæþÓæþÕåþ}‹¥DOkIUqMXtJVrMXtP\xS^zLWvHPpGNkELiNQodh…Œª¦©Ä›ž³[^r{“ilSVkQUjMQfGLaJSf_h{ltˆW_vT[t^eJSiGNhNUqLSoFMjFMiIPjrzV^tLPhOQlxz“˜š°„…š‡†–˜¸·¾•”‚‚„†—„†—xw‰ts„Ÿ››¨´´Á«­º—œ¨©°ºÍÙâÛêòÚêôßòûÜòúÚïýÚïþÚïþÚïþÚïþÚïþÚïþÚïýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÙðýÚñþÚñþÚñþÚñþÚñþÚñþÚñþÚñûÚñûÚñûÚñûÚñûÙðúÙðúÙðúÙðú×ïù×ïû×ïû×ïûÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÖíúÔëøÔëøÔëøÔëøÔëøÔëøÔëøÓê÷ÓèÿÐåþÓåÿÓåÿÒåýÓãûÔäúm{•LWsJSpJSpNVsT\yZbXa~NVvGOqFLoGMmIPlQXrbj~𢴴ºÍˆ¢fk€im‚\axNSjJOfQVmLPeV[p^cxchFIfMTqHOlFOjNUqZa}FIfQUrMPmTWtej„MQkMQkWZt}šxz“[\rbasfev˜–¤›‹˜ŽŒœŸœ°]\oa_r‹‰šŸŸ¬ÄÄл»Ç¤¤­¡¤¯¦­·Ë×ÞÝìôÝð÷ÝðùÜïúÜíýÜíýÜíýÜñÿÜñÿÛòÿÛòýÛòýÛòýÛòýÛòýÛòýÛòýÛòýÛòýÜóþÜóþÜóþÜóþÜóþÜóþÜóþÜóûÛòúÛòúÚñùÚñùÚñùÚñùÚñùÚñùÙðøÙðúÙðúÙðú×ïù×ïù×ïù×ïù×ïù×ïù×ïù×ïùÖíøÖíøÖíøÖíøÕì÷Õì÷Õì÷Õì÷ÔëöÔëöÔëöÓêôÐãýÖéÿÓæþÔäýÔäý×åÿp~—TazNVsLTsLTsNVvV^~V^~NVvEMlGMpNTwLSpFMi[cypxŒ¦¶«´Ä^cx_d{\axW\sTXpNSjNSj\avioZ^sdi‚FIfGNkIOpGOlSZvfk…^c}}›[_yPTqei†OTmNSlbdª]_x]^t{zzyŒœšªŽŒœ•Ÿ—“¤ž›¯]Zm[Zlkj}›¬³³¿º¹Â¾½Ä¬¬¶¨­´±»ÄÐÝäßñøÚêôÝíúÝíúÜïúÜïúÜñýÜñýÛòýÛòýÛòýÛòýÛòýÛòýÛòýÛòýÛòýÛòýÜóûÜóûÜóûÜóûÜóûÜóûÜóûÜóûÜóûÜóûÛòúÛòúÚñùÚñùÚñùÚñùÙðøÙðøÙðøÙðø×ï÷×ï÷×ï÷×ï÷×ï÷×ï÷×ï÷×ï÷ÖíöÖíöÖíöÖíöÕìôÕìôÕìôÕìôÔëóÔëóÔëóÓêò×éûÒãöÕåû׿ýÖäþ„ªIVpW_}PXxMUwMUwPXzU]NVxGOqDLmNTwIOpBIfJQmLTjmv‰¯·Épx‹W\schZ^vMQiSWoOTkPUjaez\btioae}AEbLSpLSpGOlJQkW\sswŒ£¥¾twX[vik†JMjQTopršMOh\]syx‹‰ˆ˜£¡±‹˜˜¨ˆšsp„ro‚a_r^]p‰Œ›¯¯º³²»·¶½ÀÀÉ£ª¯¶¿¿ÌÓÛêòÜì÷ÝíúÝíúÜïúÜïúÜñýÜñýÛòýÛòýÛòýÛòýÛòýÛòýÛòýÛòýÛòýÛòýÜóûÜóûÜóûÜóûÜóûÜóûÜóûÜóûÜóûÜóûÜóûÜóûÚñùÚñùÚñùÚñùÙðøÙðøÙðøÙðø×ï÷×ï÷×ï÷×ï÷×ï÷×ï÷×ï÷×ï÷ÖíöÖíöÖíöÖíöÕìôÕìôÕìôÕìôÔëóÔëóÔëóÓêòÕåô×è÷Öå÷×äùŒ˜°PZtS\wLTqQZyNVxNVxQZ{OWyHPrFNpIQqQWxW^{LSoMTmHOiS[qz‚–[cwX]wV[tHMf@E\INebf~PUjrx‹iodjzPUjHMfOVrHOlMUrFMiHMdX\qjm‚ei~š€‚›PSkik„wy‘lo‡TWl_av{zŽ¢Ÿ­Žœ¡œ«“ŽŸŒŸ¡rq„ZXkmp¡¡¬–•žº¹ÀËËÔ›ž¦ž¥¯¬·¿ËÖßÛêôÝíúÝíúÜïúÜïúÜñýÜñýÛòýÛòýÛòýÛòýÛòýÛòýÛòýÛòýÛòýÛòýÜóûÜóûÜóûÜóûÜóûÜóûÜóûÜóûÜóûÜóûÜóûÜóûÚñùÚñùÚñùÚñùÙðøÙðøÙðøÙðø×ï÷×ï÷×ï÷×ï÷×ï÷×ï÷×ï÷×ï÷ÖíöÖíöÖíöÖíöÕìôÕìôÕìôÕìôÔëóÔëóÔëóÓêò•¤¯¯¾È½ËÙz…–S\rV]wQXtV]zS[zT\{PXxLTsFNmIQqOWwT\{W^zQXtJQkELeELeNUoU]sGNhGLePTqNSlUZqMQipt‰[_tz€jq{}„ŽX^oHMdT[wOVsNVvSZwUWrHI_TUkrsˆ€•wxhi~st‰UXmMPeUXmst‰Œœ••¢­«¹•“Ÿ¤Ÿ¯ª¥·¨¤¸¢ž²¡Ÿ²qp‚mp››¦¡Ÿ©¬«²´´¾³·¿Ÿ¤¯«²»ª±»ÙäðáïýÜìùáóÿáóÿÜñýÜñýÛòýÛòýÜóþÜóþÜóþÜóþÜóþÜóþÜóþÜóþÝôýÝôýÝôýÝôýÝôýÝôýÝôýÝôýÜóûÜóûÜóûÜóûÛòúÛòúÛòúÛòúÚñùÚñùÚñùÚñùÙðøÙðøÙðøÙðø×ï÷×ï÷×ï÷×ï÷ÖíöÖíöÖíöÖíöÖíöÖíöÖíöÖíöÕìôÕìôÕìôÔëóeqzit~NZeOXhPXlX]tX]w[^{QXvS[xS[xPXvNVsQZwT\yT\yMTmMTmBIcAHbMTmELeBIc@GcIMjOSpOTmjoˆrwŽhldj}MScPWaahrMScV[pT[tQXvOWtT[wVXqVWlijqs…actqs…ŒŽvx‰SVjTWlW[ohj{‘¡¦¦³œš¦›¨¶±À£ž°Ž‹žŒˆœ¢š˜«“¢›š˜¢Œ“¹¹ÂÅÅΦª´¯³¾¦«·¶¿ÌáïýÞïûáóÿáóÿÜñýÜñýÛòýÛòýÜóþÜóþÜóþÜóþÜóþÜóþÜóþÜóþÝôýÝôýÝôýÝôýÝôýÝôýÝôýÝôýÜóûÜóûÜóûÜóûÛòúÛòúÛòúÛòúÚñùÚñùÚñùÚñùÙðøÙðøÙðøÙðø×ï÷×ï÷×ï÷×ï÷ÖíöÖíöÖíöÖíöÖíöÖíöÖíöÖíöÕìôÕìôÕìôÔë󀉔y‚bkxNTdV\oX\qW[p^aySZsU^yU^yQ[vS\wU^yS\wNWpFNdAI_BJa>E^GNhGNj7>Z;B_?Ba?B_BGaX]wINech}‰¢GM]DIWOUeafy_dyJSiMTmWawdl€[]ofevsr‚hfwfevml}š˜«ž¡²qtˆ_cxadx[]o€¦¦³›¨œš¦­©¸–‘£}yzw‹{z†…—•—¦œŽ–Œ‹‘©©²ÀÀɲ¶À¸»Æ´·Äœ¢°ÁÏÝÜìùáóÿÞñýÜñýÜñýÛòýÛòýÜóþÜóþÜóþÜóþÜóþÜóþÜóþÜóþÝôýÝôýÝôýÝôýÝôýÝôýÝôýÝôýÜóûÜóûÜóûÜóûÛòúÛòúÛòúÛòúÚñùÚñùÚñùÚñùÙðøÙðøÙðøÙðø×ï÷×ï÷×ï÷×ï÷ÖíöÖíöÖíöÖíöÖíöÖíöÖíöÖíöÕìôÕìôÕìôÔë󅌖t{†pt€lqhlzehyTVh_avZ^sXatU]sPXoQXrT[tNUoELeAHbDH_AF_@GaELh=Da=Da@Gd>A_>A^JNkHMfAF]PUjOTiOUhX^qsyŒejOTiS[qFNdLViT\pX\pZ\m^arihzdcvjiy‹‰š£¢´rsˆy}~“xz‰wy†„„——£‰‡”~{‰‡…“‰‡—‰†…—‹‰š”–£ŒŒ—š˜¢¸·¾»»Å¾¾Ç¿¿Ë½½È¶¶Áª¯º›¦ÓãðáñþÜïúÞñýÜñýÜñýÛòýÜóþÜóþÜóþÜóþÜóþÜóþÜóþÜóþÝôýÝôýÝôýÝôýÝôýÝôýÝôýÝôýÜóûÜóûÜóûÜóûÛòúÛòúÛòúÛòúÚñùÚñùÚñùÚñùÙðøÙðøÙðøÙðø×ï÷×ï÷×ï÷×ï÷ÖíöÖíöÖíöÖíöÖíöÖíöÖíöÖíöÕìôÕìôÕìôÔë󓕘£ˆŒ–‹Ž˜ÆÉÔ±±½šš¥››¨sv‚hjyps…VZmUZqPUoLOlFIhFIhGHhEFeAEc@Db@Dd>Dd>Eb>Eb?FbHOkFMiAHbAHbBIcNVlXatS[m]eydl€U]sLSlJQkLSlTWtHJhOQj]^tcdyxz‰±±¾‡†–mp}~“‘”£ž¡­–˜¥‚…‘Žvv‚Œss€‹‹—Žž€……‘““Ÿ©œ›¤­¬¶º¹Â¾½Æ¤£¬¹¸Á¾½Æ²¶À—ž©œ¨³ßïùáñûÛíùßòþÝòÿÚïúÞóÿÞôýÞôýÞôýÞôýÞôýÞôýÞôýÞöþÞöþÞöþÞöþÞöþÞöþÞöþÞöþÝöúÝöúÝöúÝöúÜôùÜôùÜôùÜôùÛòúÛòúÛòúÛòúÚñùÚñùÚñùÚñùÙðøÙðøÙðøÙðø×ï÷×ï÷×ï÷×ï÷ÕïöÕïöÕïöÕïöÔíôÔíôÔíôÓì󖉋›œ¢¢£©³´ºÙÚßÈÉϬ­³½¾Ä··À¨ª·[]obc{bdMNmIMkJLkLMlIJjFGi@Dd@Dd>Dd>Eb?Fb>EaGNjDJfBIeAHd?FbFMfDLb@H\IQeckQZpIPjFMfOVrMPoLOmPSm]_x]^spr„……‘~}“~€‘vx‡‡‰–¢¥°£¥²prvx‡Ž……‘ss€ŽŽ›~~‹šªš—¤œ›¤¤£¬ÓÒÛ¤£¬­¬¶³²»°°¹±¶À‚Œ–ÒÝéßïùáñþáóÿßôÿÝòþÞôýÞôýÞôýÞôýÞôýÞôýÞôýÞôýÞöþÞöþÞöþÞöþÞöþÞöþÞöþÞöþÝöúÝöúÝöúÝöúÜôùÜôùÜôùÜôùÛòúÛòúÛòúÛòúÚñùÚñùÚñùÚñùÙðøÙðøÙðøÙðø×ï÷×ï÷×ï÷×ï÷ÕïöÕïöÕïöÕïöÔíôÔíôÔíôÓìóÁÂÆ¤¥©Œ”•˜—˜œÞßãÎÏÓÅÆÉ¿ÀÄ´¶»··Â{zcd}hh†VWyLMoILiJMjHJhEFe@Db@Db>Eb>Eb?Fb>EaELhAHdAHdAHd>Ea@GcELh>E^ELe]e{JSiGOcNVjV^rPUoNSlOQjX\qQShbdvom€{z{}‘mpQTc[]j…ˆ“‹š†ˆ—ŒŽ††“ddqbboyy†ˆˆ•ŒŒ˜œ““Ÿ›¨›š£ž¦²±ºž¦¦¥¯¡Ÿ©š´¹Ä˜Ÿª¬¶ÀâíùáñûÞñýÛðûÝòþÞôýÞôýÞôýÞôýÞôýÞôýÞôýÞôýÞöþÞöþÞöþÞöþÞöþÞöþÞöþÞöþÝöúÝöúÝöúÝöúÜôùÜôùÜôùÜôùÛòúÛòúÛòúÛòúÚñùÚñùÚñùÚñùÙðøÙðøÙðøÙðø×ï÷×ï÷×ï÷×ï÷ÕïöÕïöÕïöÕïöÔíôÔíôÔíôÓìóÉËÍ´¶¸¦¨ª‘“•‹ŒŽ·¸ºÜÝßÚÛݸ¹»²³·ÇÇЪ©¹zxdd€__NOoDFaDFaAD^?A^@Da@Db>Eb>Eb@Gc>EaDJf?Fb=D_@Gc>Ea@GcFMi@GcJQkXawPXoJSfXasPXlGLcQVm\_tQUjSTi\^pts„vt‡‚—ik}UWfikxx{†…‡”‡‰˜‘¡^^kzz‡‚‚‰‰–‡‡”‘‘ž””¡”‘ž£¢«¡Ÿ©±°¹†…Ž£¢«¢¡ªŸŸ©²¶À­²½‹‘œÚãíãòýáóýÞóÿáöÿÞôýÞôýÞôýÞôýÞôýÞôýÞôýÞôýÞöþÞöþÞöþÞöþÞöþÞöþÞöþÞöþÝöúÝöúÝöúÝöúÜôùÜôùÜôùÜôùÛòúÛòúÛòúÛòúÚñùÚñùÚñùÚñùÙðøÙðøÙðøÙðø×ï÷×ï÷×ï÷×ï÷ÕïöÕïöÕïöÕïöÔíôÔíôÔíôÓì󩫪¾À¿‘”“ˆ‹‰mpoz}{ËÍÌßâáÖÖÖÒÒÔÁÀÇÀ¾Ë²±Ä–”«de~OOkHLaGJ_HJcFHa@E^=@]:A]=D_>Ea?Fb>Ea;B^>Ea?Fb@GcAHdMTmSZsHPfFNdS[qOWmQZpLTjJOi_d{JNc_cw]_qjl{llyŒy{VXjWZirtlpz€‚•—¦¢¤³””¡ww„}}‰‹‹—††“””¡¡¡­““Ÿ›˜¥”“œ›š£ÆÅΣ¢«ž¦ª©²°¯¸ßß黻ǔ˜£ºÄÎÝìôáóýßöþÛòúÞôýÞôýÞôýÞôýßöþßöþßöþßöþÞöþÞöþÞöþÞöþÞöþÞöþÞöþÞöþÞ÷ûÞ÷ûÞ÷ûÞ÷ûÝöúÝöúÝöúÝöúÜóûÜóûÜóûÜóûÛòúÛòúÛòúÛòúÚñùÚñùÚñùÚñùÙðøÙðøÙðøÙðø×ñø×ñø×ñø×ñøÖð÷Öð÷Öð÷Õïö~±²´‰‹‚…deh‘”¯°²ÎÎθ¶·ÓÐÔÜÚÞÒÐ×°­ºª©¹wvˆWXmOSdNQeNQeLOd@E\>B\:A]>Ea?Fb>Ea;B^=D_@Gc?Fb>Ea=D]=E[FNdDLbMUkS[qQZpT[tU\vV[rejTWlX\pcewjlyyy…ŽŽ›y{\^plo~y{ˆ‹Ž˜”–£vx‡~€••¢‘‘ž‚‚““Ÿ••¢‰‰–––£˜˜¥Ÿª¡Ÿ©¦¥¯Ÿž¨±°¹£¢«©¨±ª©²±°¹´³½¬°º‹‘›ßëôÛíôÞôýß÷ÿÞôýÞôýÞôýÞôýßöþßöþßöþßöþÞöþÞöþÞöþÞöþÞöþÞöþÞöþÞöþÞ÷ûÞ÷ûÞ÷ûÞ÷ûÝöúÝöúÝöúÝöúÜóûÜóûÜóûÜóûÛòúÛòúÛòúÛòúÚñùÚñùÚñùÚñùÙðøÙðøÙðøÙðø×ñø×ñø×ñø×ñøÖð÷Öð÷Öð÷Õïö¡¢¥”•˜‚„‡{}€dei…†‰˜šššœ›˜šÅÀÁÛÙÜÓÐÔÍÌÐÆÅ̰°¹eisV[fTXfQUfOSfAF]>B\;B^?Fb>Ea;B^=D_=D_?Fb>Ea=D_;B\BJaEMa@H^MUkIQhJSiNUoV^tdi~{”W[odhysv…z}Œ¢¢¯qp€VXjxzŒrt„vx…€„Ž“•¢fixdfvŽŽ›ww„‡‡”££°¾¾Ë——¤››¨œš¦š˜¢¯­·ÁÀÉ¥¤­´³½­¬¶°¯¸¦£«ÍÉÔ½½Æž£­©¶½Þð÷ÞôúÝöúÞôýÞôýÞôýÞôýßöþßöþßöþßöþÞöþÞöþÞöþÞöþÞöþÞöþÞöþÞöþÞ÷ûÞ÷ûÞ÷ûÞ÷ûÝöúÝöúÝöúÝöúÜóûÜóûÜóûÜóûÛòúÛòúÛòúÛòúÚñùÚñùÚñùÚñùÙðøÙðøÙðøÙðø×ñø×ñø×ñø×ñøÖð÷Öð÷Öð÷Õïö°±´°±´¥¦ªŽ“{}€efjmor_^c¯¬°ÕÓÖ—•˜¦¤¨”Œ‹•–œ‰‰“^blV[fSWePTeBF[?D[?B_>Ea;B^=D_=D_>Ea:A];B^=D_>EaFNdAI_;DZJQkHOiBIc;B\AHbV[pafy]arhlzy{‹ž­jiywy‹bdvjl{}Œfiv~€oq~zz‡˜˜¤ŽŽšœ‡‡“~~‰““Ÿ««¸““žœ›¤¡Ÿ©˜—¡£¢«œ¥ª©²Ÿž¨¶´»¥¢ªÒÐ×ÀÁǯ´»¥°¶Úéðßñ÷ãöýÞôúÞôýÞôýÞôýßöþßöûßöûßöûÞöþÞöþÞöþÞöþÞöþÞ÷ûÞ÷ûÞ÷ûÞ÷ûÞ÷ûÞ÷ûÞ÷ûÝöúÝöúÝöúÝöúÜôùÜóûÜóûÜóûÛòúÛòúÛòúÛòúÚñùÚñùÚñùÚñùÙðøÙðøÙðøÙðø×ñø×ñø×ñø×ñøÖð÷Öð÷Öð÷Õïö¶´¹¨¦«Ÿž£š˜~}zy~‹‰Žtsxqpt«ª¯ÄÂÉŒ“VU^WV_ljwyy…lpzTWbSVaUWfGJ^GIb@Da>Eb?Fc>Gb=Fa;E];E];E_;E_;E_?Ha?Ha?Ha?Hc@Id>Gb>GbAHdMQiNSh_ctqv„‡‰–Žvt…sr‚zy‰kjzvt…~Žyy†••¢““Ÿ––¢±°¹©¨¯ž¦•”€‰”‘žŽ›¡ž«¢¡ª—–Ÿ‹‰£¢©ÐÏÖª©°¥¤«°¯³±°´ª«¯³¸º²¶»°¶½´»ÂÖáæßïöáóúÝöúÞ÷ûÞ÷ûßøýáùýâøýá÷ûá÷ýá÷ýá÷ýá÷ýâøþâøýâøýâøýáùýáùýßøûÞ÷úÞ÷úÞ÷úÞ÷úÞ÷úÝöùÝöúÝöúÝöúÜôùÜôùÜôùÜôùÛóøÛóøÛóøÛóøÚò÷Úò÷Úò÷Úò÷×ñö×ñö×ñö×ñöÖðôÖðôÖðôÕïórqv¥¤©›šžœ›Ÿ{z“‘–„‚‡wvz€†¥¤«º¹Â˜—¡a^k_]jb_mdbpss\_hNQ\\^kNQeGIbDGd>A_?Fc>Fc=Fa;E];E];E_;Da;Da>Gb>G_>Gb>Gb=Fa=Fa?GdELhUZsOTi]ar€…“‚…‘sv‚yxˆkjzom~dcs~މˆ˜~~‹}}‰šš¥““œ°¯¶¬«°¨¦­›š¡•”¬«´”‘ž”‘ž¥¤­–•ž”“𢡍´³¸ÅÄÈÓÒÖ½»À¬­°ª«­º»¿»¿Å¤¨°ÀÆÍž¤«äï÷âôûÞ÷ûÝöúÜôùâúþÞ÷úß÷øãùþá÷ýá÷ýá÷ýá÷ýâøýâøýâùúâùúáùýáùýßøûÞ÷úÞ÷úÞ÷úÞ÷úÞ÷úÝöùÝöùÝöùÝöùÜôøÜôøÜôøÜôøÛóøÛóøÛóøÛóøÚò÷Úò÷Úò÷Úò÷×òô×òô×òô×òôÖñóÖñóÖñóÕðò}{€wvzrqvvty€…°¯³¡Ÿ¤”‹‰‰ˆ‰ˆ‘š˜¢„ŽŒ‰–a^lZWe^^j[^iZ]h]_lPTeJNcGLe@Db?Fc>Fc=Fa;E_;E_;E_;Da;Da=Fa=F^=Fa=Fa=Fa=Fa?GdELh\azOTicfx€…“jly\^k{z‹_^oVUebaqqp€~Ž}}‰ss€˜–©¨¯«ª¯¯­´œ£¡Ÿ©ÆÅΨ¥²Ž›­¬¶‘šž¤¥¤«¡Ÿ¤ÂÁÆëêïÌËÏÆÆÈ±±³ÅÆÉ¾¿Å¯²º½ÀÈ“˜ŸÁÌÔßñøßöûÞôúßöûßöúãùþâúûÞ÷úá÷ýá÷ýá÷ýá÷ýâøýâøýâùúâùúáùýáùýßøûÞ÷úÞ÷úÞ÷úÞ÷úÞ÷úÝöùÝöùÝöùÝöùÜôøÜôøÜôøÜôøÛóøÛóøÛóøÛóøÚò÷Úò÷Úò÷Úò÷×òô×òô×òô×òôÖñóÖñóÖñóÕðò¿¾Â‰ˆ\[_edi„‚‡±°´¶´¹—–›”“š‹‰„‚Œ[Zc…‚¿½É“žcao]]iVZdkoy_boNQcNQfGLeGJh?Fb>Fc=Fa;E_;E_;E_;Da;E_=F^=F^=Fa=Fa@Id>Gb>FcAHdGLeX]rcfxdiw]_leht~Žbaq\[ksr‚xw‡{z‹‚‚yy†‰‰•••ž£¢©ª©­³²¹ž¤”“œª©²¡ž«¤¢¯·¶¿Œ‹”¤£ªª©°¦¥ª©¨¬ÇÆËÁÀ޽¿¿¿Áº¹¾ÆÇ͹¹Â¾ÁɾÁÉ”ÒáéÞñøä÷þäúÿâøýá÷ûßøùáùýá÷ýá÷ýá÷ýá÷ýâøýâøýâùúâùúáùýáùýßøûÞ÷úÞ÷úÞ÷úÞ÷úÞ÷úÝöùÝöùÝöùÝöùÜôøÜôøÜôøÜôøÛóøÛóøÛóøÛóøÚò÷Úò÷Úò÷Úò÷×òô×òô×òô×òôÖñóÖñóÖñóÕðò©¨¬´³¸edi~‚¡Ÿ¤—–›­¬±¬«°š˜Ÿ–•œž¦~}†WUb¬ª·ÍËÙhesbbmps~Z]ecfq_drMPdINeJOiAHd=Fa=Eb;Da;Da;Da;E_;E_;E];E];E_;E_>Gb;E_AIfJQmJOiW\qZ]olq_boz}‰€ml}ihxrq~}vt…tttt””Ÿ¦¬«²¬«°ª©°š˜Ÿ“‘›ž¦¥£°½ºÇ¦¥¯–•žŒ“š˜Ÿœ›Ÿ¦¥ª¿¾ÂÆÅÉÀ¾ÁÅÂÆ¿¾ÂÔÓÚ²²»»»Å¾ÁÉŸ¤¯…šÉÙáäöýÜïöá÷ûãùþãûýäýÿâøþâøþâøþâøþâøýâøýâùúâùúáùýáùýáùýáùýßøûßøûßøûßøûÞ÷úÞ÷úÞ÷úÞ÷úÝöùÝöùÝöùÝöùÛó÷Ûó÷Ûó÷Ûó÷ÚòöÚòöÚòöÚòö×òô×òô×òô×òôÖñóÖñóÖñóÕðò»º¿ÂÁÆ¡Ÿ¤Œ‹©¨¬£¢¦–•𔓗¨¦­œ›¢ž¦°¯¸‚€[Xe^\j¸¶Ä]]iX\f_ck\_jlq}fj{DH]GLcDJd>Gb=Eb;Da;Da;Da;E_;E_;E];E];E_;E_=Fa;E_?GdGNjPUoQVkSVhlqvx…y{ˆedtedtxw‡xw‡sr‚„‚“‰‰–qq~‰‰•¨¨±ÆÅ̽»À±°·½»ÂŸž¨Ž—“{y†€ˆ˜¤£ª“‘˜”¦¥ª»º¿ËÉÎÈÆÉËÈÌÂÀÅÀ¿Æ»ºÄ¿¿ÈÂÂ̰´¿}†œ¥ßï÷èùÿáôùá÷ûáùúáùýâøþâøþâøþâøþâøýâøýâùúâùúáùýáùýáùýáùýßøûßøûßøûßøûÞ÷úÞ÷úÞ÷úÞ÷úÝöùÝöùÝöùÝöùÛó÷Ûó÷Ûó÷Ûó÷ÚòöÚòöÚòöÚòö×òô×òô×òô×òôÖñóÖñóÖñóÕðòÐÏÔ¯­²¥¤©¦¥ª—–››šžœ¡‘•‘—ˆ‡Ž–•ž¸·ÀÆÄÐ^\ib_mqo}SS^Z]h[^fadohlx}FL^=AVFMf@Id=Eb=Eb;Da;Da;E_;E];E];E];E_;E_:D^:D^=EbAHdFJdNShMPb]bp„‘ž„‚“‡†–xw‡€yxˆ€šŒtt€ŽŽ—±°·º¹¾¦¥¬¹¸¿­¬¶–•ž¥£°š˜—¡š˜¢•”›š˜ŸŽ‘©¨¬»º¿ËÉÎâßãÔÎÓÄÁÆÌÈÐÏÎ×ÎÍÖ»»Å¦ª´£ª´y‚¬¸Áè÷ÿåùþßöúßøùßøûâøþâøþâøþâøþâøýâøýâùúâùúáùýáùýáùýáùýßøûßøûßøûßøûÞ÷úÞ÷úÞ÷úÞ÷úÝöùÝöùÝöùÝöùÛóôÛóôÛóôÛóôÚòóÚòóÚòóÚòó×òô×òô×òô×òôÖñóÖñóÖñóÕðòÈÇ̪©­–•𝭲©¨¬£¢¦³²·­¬±£¢¦{z‡†œ›¤¤¢¯ljwVTbVVcNP]Z]hilwbepcfqimyrv‡FL^BJaDJd?Fb>Eb=Da;Da;E_;E];E];E_;E_;E_9B]:D^;Da=D_@Ga?D[FI]ps…ŒŽœž«——¤‚‘‚‘xw‡~Ž€€‡‡”„„vv††¿¾Å²±¶ª©°–•œ‰ˆ‘¡Ÿ©¸·À©¨±»ºÄ­¬³¸·¾¡Ÿ¦—–›­¬±¾½ÁÄÂÇÍËÎÍËι·»½º¿°¯¶³²»ÁÁËÁÁ˾ÁÌ¢¦²‚‰”Ë×ÞåôûèûÿâøýßøûáùýáùþâøþâøýâøýâøýáùúáùúáùúáùýáùýáùýßøûßøûßøûßøûÞ÷úÞ÷úÞ÷úÞ÷úÝöùÝöùÝöùÝöùÛóôÛóôÛóôÛóôÚòóÚòóÚòóÚòó×òô×òô×òô×òôÖñóÖñóÖñóÕðòÇÇÉÏÏÒÀÀÂ¥¥¨““•¨¨ª··¹¯¯±›››œœœ‚…rsy˜˜¢hhtNM]NP_SUdacrllxffrllxrt}ŽfizAEZHJcJNkDGd>A_9@];B^@Ga?Fb?Fc>Eb>Eb=D_;B^;B^=D_;B\AF_DHb@B[LOcmpŽ˜›¨‹‹—zz‡Žrr~xx„tt€‹‚‚Œ¶·½¹ºÀ°±·¥¦¬•–œ«¬²³´º±²¸¯­´²±¶·¶ºº¹¾Ÿž£¡Ÿ¤½»ÀÇÆËÁÀŲ±¶´³¸º¹¾³²·ÐÏÖÆÅÌÄÂɾ½Æ´´ÀŽ‘œ•œ¥Ýêñè÷ÿåøÿá÷ýáûþáûþâúþãúûäûýãûýâýýâýýâúûâúûâúûâúûáùúáùúáùúáùúßøùßøùßøùßøùÞ÷øÞ÷øÞ÷øÞ÷øÛööÛööÛööÛööÚôôÚôôÚôôÚôôÙñòÙñòÙñòÙñò×ðñ×ðñ×ðñÖïðÞÞáÈÈ˽½¿³³¶••—““•ÀÀÂÇÇÉ«««¯¯¯º»¾‰‹Ž[^fTVcPSbX[lVXjbdsoo{±±½››¦~~‰hhtkjz^_tHI_HJeMOlFIf?B_9@\;B^>Eb>Eb>Eb>Eb>Ea=D_;B^;B^;B\@Ga>A^@E^QUjNQcUWd…••¡……‡‡“iitffrllx€€Œ‰‰•°°¹´¶»±²¸£¤ª…†Œ¯°¶¦¨­²³¹¹¸½²±¶¸·»ÁÀʏ½›šž¢¡¥»º¿ÉÈ͹¸½¬«°·¶º´³¸Ù×ÜÄÂÇÈÇÎÀ½Ç¥¤­²²»‡Œ–¥¯¹ßëôæ÷ÿäúÿáûþáûûâúûãúûäûýãûýâýýâýýâûùâûùâûùâûùáúøáúøáúøáúøßøùßøùßøùßøùÞ÷øÞ÷øÞ÷øÞ÷øÛööÛööÛööÛööÚôôÚôôÚôôÚôôÙñòÙñòÙñòÙñò×ðñ×ðñ×ðñÖïðßßâÒÒÔššœŸ££¥““•­­°³³¶¯¯¯ŸŸŸ—˜›¯°³z~†jlyNP_QTewy‹hjyzz‡””¡ÈÈÔ\\hllyts„y{PQfEG_HJeGJhAEb=D_>Ea>Eb>Eb=Da=Da>Ea>Ea=D_;B^=D]9@Z@Da?D]PTi^bsdfswz…]]immy‰‰•{{‡jjvzz†††‘““ž¢¢«³´º¹ºÀ²³¹–—‘“˜³´º©ª°¸·»²±¶­¬±¯­²¾½Á¸·»±°´¥¤©¾½ÁÇÆËº¹¾”“—½»À·¶ºÀ¿ÄÎÍÔÇÆÏ°¯¸½½Æšž©x‰±½Æéøÿä÷þâúþáûûâúûâúûãûýãûýâýýâýýâûùâûùâûùâûùáúøáúøáúøáúøßøùßøùßøùßøùÞ÷øÞ÷øÞ÷øÞ÷øÛööÛööÛööÛööÚôôÚôôÚôôÚôôÙñòÙñòÙñòÙñò×ðñ×ðñ×ðñÖïðÌÌÎ××Ú³³¶ªª¬°°²¬¬¯ššœ””–¡¡¡¥¥¥£¤¦¤¥©˜œ¤‚…‘WZiTVhpr„\^m~Žffs““ŸZZe‰‰–¡¡­¤¦¶twˆEH]FHaLPjGJh?Fb;B^=Da=Da=Da=Da=D_>Ea>Ea=D_>E^:A[;?\@E^NQfcfx…‡”£¦±ŒŒ—€€Œww‚„„{{‡‹œŽŽš˜˜¢´¶»³´º³´º¤¥«‚ˆ¤¥«¡¢¨´³¸³²·±°´·¶ºÌËϽ»À¾½Á¹¸½¿¾Â»º¿ÆÅɘ—œÌËÏÂÁÆìëðáßæÄÂÌÇÆÏ¶¶¿°³¾y€‹‰“ë÷ÿãôûãùþáûûâúûâúûãûýãûýâýýâýýâûùâûùâûùâûùáúøáúøáúøáúøßøùßøùßøùßøùÞ÷øÞ÷øÞ÷øÞ÷øÛööÛööÛööÛööÚôôÚôôÚôôÚôôÙñòÙñòÙñòÙñò×ðñ×ðñ×ðñÖïðÄÄÆÌÌÎÏÏÒ¸¸ººº½³³¶ÂÂŬ¬¯˜˜˜“”–—˜œœŸ¨‡‰–LN]IL]qs‚lo~kjzNM]FFSOO\eeq~~‹y{ˆ…‡–_cw>@XOTmFIfAHd>Ea>Eb>Eb>Eb>Eb9@\:A]>Ea>Ea=D]=D];?\HMfHLa\_q„¬°º¯¯º““ž††‘‰‰•ŽŽšˆˆ”——£ˆˆ”¦¥¦¬¯°¶²³¹¸¹¿š›¡Ž”°±·´³¸¹¸½±°´º¹¾ÅÄÈÇÆË½»À¹¸½ÅÄÈÈÇÌÅÄȤ£¨¨¦«ÖÕÚãâæÝÜãÔÓÜËÉÓÀÀÉÍÐÛ–›¦—¢ÈÎÜë÷ÿãùþãûýâýýâýýâýýâýýãûýãûýãýúâûùáúøáúøáúøáúøáúøáúøßøùßøùßøùßøùÞ÷øÞ÷øÞ÷øÞ÷øÜ÷÷Ü÷÷Ü÷÷Ü÷÷ÛööÛööÛööÛööÙñòÙñòÙñòÙñò×ðñ×ðñ×ðñÖïðÀÀ··¹ËË;¾À¨¨ª¶¶¸ÈÈËÇÇɲ²²ªªª¬­°Ÿ¡¤˜œ¤›ªGIXIL]SUdehw„‚“XWhML\^^k]]ipp{Ž‘œ¯±À“–ªILdINhHLiAHdAHd?Fc>Eb>Eb>Eb:A]:A]=D_>Ea>E^@Ga>A^AF_AEZ]arrt{‰}}ˆˆˆ”……›——£¥¥±ŸŸ«¦¦°ª«±¸¹¿¶·½­¯´±²¸†‡ª«±»º¿ÌËÏÂÁÆ«ª¯¹¸½ÍÌÐÄÂǺ¹¾·¶º½»À¾½Á±°´¿¾ÂßÞãÄÂÇÝÜãíìöÂÁËÇÇÐÐÐÜÅÇÔ”Ÿª¯½ëôÿåùþâúûâýýâýýâýýâýýãûýãûýãýúâûùáúøáúøáúøáúøáúøáúøßøùßøùßøùßøùÞ÷øÞ÷øÞ÷øÞ÷øÜ÷÷Ü÷÷Ü÷÷Ü÷÷ÛööÛööÛööÛööÙñòÙñòÙñòÙñò×ðñ×ðñ×ðñÖïðÁÁĺº½ÅÅǾ¾À“¥¥¨»»¾ÁÁÄÅÅž¾¾³´·°±´¬°¸”–£LN]OQc\^macr…„”ji{TScbboZZejjs¯²ºº½É_ctVZo@E^>A^FMiBIeBIf?Fc>Eb>Eb:A];B^=D_=D_?F_>E^@Da@E^GJ_\_q{~‹z~ˆss††‘……‹‹‹–˜˜¤““ž›¤¤­ÍÎÔ»½Â³´º¤¥«Ÿ¡¦­¯´ž¤±°´¿¾ÂÏÎÓ­¬±±°´ž¢¯­²ÂÁÆ¿¾Â³²·¸·»«ª¯º¹¾¿¾ÂÍÌÐ÷öýÙ×áÄÂ̽½ÆÆÆÒ××äšœ©“¢ÉÐÛèùÿâúûâýýßþýßþýâýýãûýäûýãýúâûùáúøáúøáúøáúøáúøáúøßøùßøùßøùßøùÞ÷øÞ÷øÞ÷øÞ÷øÜ÷÷Ü÷÷Ü÷÷Ü÷÷ÛööÛööÛööÛööÙñòÙñòÙñòÙñò×ðñ×ðñ×ðñÖïðÇÇÉÄÄÆ½½¿½½¿¦¦©¹¹»±±³³³³ÁÁ¿ÇÇDz³¶°±´ªª³¡¡­NM_IL]UWiik}PObqp‚edt^^kaaljjs­­·©¬·}Ž{}‘SUmFHcHLiGJhDJfAJe>Gb>Ea:A];B^>Ea=D_?F_9@Z@DaFJd=?WLOc~‚Žwz…ooz‚‚Ž——£‚‚Žˆˆ”––¢……–—•–œ³´º¿ÀÆŒ“¡¢¨½½Æ¦¨­¨¦«ÅÄÈÎÍÒ´³¸¬«°·¶ºÀ¿Ä²±¶»º¿ÅÄÈÇÆË¶´¹À¿ÄÎÍÒÜÛßÔÓ××ÖÝãâé¿ÀƬ¬¶ÀÀÌ´´ÁŒœ¡¬áð÷åùûâúûâýýâýýâýýãûýãýúãýúâûùáúøáúøáúøáúøáúøáúøßøùßøùßøùßøùÞ÷øÞ÷øÞ÷øÞ÷øÜ÷÷Ü÷÷Ü÷÷Ü÷÷ÛööÛööÛööÛööÙñòÙñòÙñòÙñò×ðñ×ðñ×ðñÖïð‘‘‘ÀÀÀ«««ËË˾¾¾ÁÁÁ¹¹¹½½½ÄÄÁ¿¿¿ÎÎЭ¬³¯¬¹Ÿ­PMaNMbHF]qo†\[pzyŒ€\\i‚‚Žllv}~„‚‚Œ˜˜¤­¬½›²NLeNLhJMjJTlGTkANe=F^=D]:A[;?\=@]?D]?D]?B_?B_AF_?DXfmx~„‹swvvŽŽ—~~‡ww„žž«‡‡“–¥¤«‹‰“£¢«“‘˜œ›¤¯¬¹¡Ÿ©¢¡¥²²´ÏÏÒÀÀÂÆÆÈ±±³££¥±±³½½¿ÈÈËÇÇÉÂÂÅÄÄÆÇÇÉÍÍÏÌÌÎñðôöôùÈÇÌ­¬³¿¾ÅÅÄÍ‘œ–š¤¸ÂËæöýäöùëÿÿãýúãþûÞýùâþøäþùãýøâû÷âû÷áúöáúöáúöáúøßù÷ßù÷ßù÷ßù÷ÞøöÞøöÞøöÞøöÝ÷ôÝ÷ôÝ÷ôÝ÷ôÜöóÜöóÜöóÛôòÚóñÚóñÚóñÚóñÙòðÙòðÙòð×ñïxxxÌÌÌÒÒÒ¶¶¶ÌÌÌœœœ‡‡‡°°°¦¦¤¢¢¢¸¸º²±¸°­º¢Ÿ­OL_LH^VTkWUlMLahfy˜˜¥ddpœœ¥ss}iho…„‹¥¤­±¯½ÉÆÚ‰†XToTTpDMeN[rDPh>G_:A[:A[>A^>A^?D]?D]?B_?B_BFc=AXZ_my~ˆtx‚ppyˆˆ‘‰‰•““Ÿ‹‹—zz‡””ŸŽ—Ÿž¥–•žŒ••”Ž—¶³À»ºÄš˜²²´ÁÁĸ¸º¿¿ÁÇÇɬ¬¯¡¡£»»¾ÆÆÈ¾¾ÀÁÁÄÀÀÂÅÅÇÌÌÎÇÇÉããåÂÂÅÒÐÕ·¶ºÀ¿Æ¿¾Å«ª³ŽŽ—¢©²áëóåöùéúþåýûáúøâÿúÞý÷ãÿùãýøâû÷âû÷áúöáúöáúöáúößù÷ßù÷ßù÷ßù÷ÞøöÞøöÞøöÞøöÝ÷ôÝ÷ôÝ÷ôÝ÷ôÜöóÜöóÜöóÛôòÚóñÚóñÚóñÚóñÙòðÙòðÙòð×ñïllj––”ÏÏÍ¿¿½¸¸¶~~{……‚¿¿½¡¡žžžœ££¥±°´©¨±«©¶HFTOM]XWjXWjSQb\\ittww‚{{…fhmomt–•œ¯­·¾»È½ºË²¯Â[WmVWpBIcQ[vISmBIe=D_>A^?B_>A^?D]?D]?D]?D]?B_BG^MSasx„xz‡zz‡Œ––£{{‡šš£……Ž‚‚Žzx…˜–£œ¥—–Ÿ—–Ÿ–•žª©°ÇÆÍ°¯³³³¶««­±±³²²´««­¿¿ÁÆÆÈ³³¶ÁÁÄÇÇÉÁÁĹ¹»½½¿ÈÈËÈÈ˽½¿ÇÇɸ·»ÁÀʏ¿ÉÈϹ¸Á‹‹”Œ›ÆÐÙíúÿèùýåùùåÿýßûöáÿùãÿùãýøâû÷âû÷áúöáúöáúöáúößù÷ßù÷ßù÷ßù÷ÞøöÞøöÞøöÞøöÝ÷ôÝ÷ôÝ÷ôÝ÷ôÜöóÜöóÜöóÛôòÚóñÚóñÚóñÚóñÙòðÙòðÙòð×ñïaa^yywÙÙÖËËÈÈÈÆ……‚wwt¡¡žŸ¡œ´´²ŸŸ¢¦¥¬œ›¤VTaLIVNN[UUbPP\EEPaalMMVMNThiokjož¢½»Â£¢«ÄÁÏ»¹Éws‡QPeFJdMTpNUqHLiEHeAEb>A^=A[?D[?D[?D]?D]?B_DHbBHXqvsv‚qq~wv†——¤……Ž‹Œ‘˜””Ÿqo}Œ‰–¥¤­¨¦°›¨›š£–»º¿¸¸º¸¸º»»¾ÄÄÆ»»¾´´·²²´íí𸸺ÅÅÇÂÂÅÅÅǽ½¿´´···¹¹¹»¨¨ªÉÉÌÄÂǺ¹¾±°·¸·¾ÈÇОž¨‚‡‘“š£Üéíâòöæúúãúùãÿùâþøäþùãýøâû÷âû÷áúöáúöáúöáúößù÷ßù÷ßù÷ßù÷ÞøöÞøöÞøöÞøöÝ÷ôÝ÷ôÝ÷ôÝ÷ôÜöóÜöóÜöóÛôòÚóñÚóñÚóñÚóñÙòðÙòðÙòð×ñïVWSopk½¾¹½¾¹Œvwr€}”•‚„²³¯³³±„„„¡¡£Œ‹–•œkjqddmTT]TT]OOXZ[aTU[NOSdeiomrˆ‡Œ¥¤©£¢©ÂÁ˦¤±qo}edtSVk?D]OTmOTmHLiBFc;?\>B\?DX?DX>BZ>B\AEb>B\?EWzsv‚oo{ml}š––Ÿ‚„‰¦““ž›rp}Ž—±°¹°­ºž¦Œ‹‘Ž“±±³ÁÁÄÄÄÆºº½ÆÆÈÆÆÈÉÉÌÌÌθ¸ºÌÌÎÇÇÉÅÅÇÀÀÂÀÀºº½²²´ºº½èèêÜÛß¿¾Â½»Â¸·¾ÍÌÕÈÈÒ‡‹•y€‰©³¹íúÿä÷÷åýûäþùáý÷åÿúäþùãýøãýøâû÷âû÷âû÷âû÷ßù÷ßù÷ßù÷ßù÷ÞøöÞøöÞøöÞøöÜöóÜöóÜöóÜöóÜöóÜöóÜöóÛôòÚóñÚóñÚóñÚóñÙòðÙòðÙòð×ñïTUPbc^}~y«¬¨¢£žbc^‡ˆ„stpklh‹Œ‡‹‹ˆ€€~€€€‡‡‰°°²°¯³ijm]^bXZ]deiZ[^\]aTUXefjooqwwy¹¹»œ›Ÿ¹¸¿Œ‹”°¯¸††“cewLOdPTiPSkOQlIMj?B_>B\?DX@EZ?D[?D]?B_?D]BH[jo}€‚{{ˆddqxx…œœ¨††‘‘›˜˜¤£¡­“xw€Ž—°¯¸±°¹˜—ž†…Œ«ª¯»»¾ÄÄÆÉÉ̾¾ÀÌÌÎÈÈËââäÍÍϸ¸ºËËÍÉÉÌÇÇÉÂÂÅÁÁÄÂÂÅ»»¾ÀÀÂÄÂÇÈÇÌÇÆÍ¨¦­ÒÐÚÅÅΟ£­{€‹†”Ôáååøøåùùãýøãÿùåÿúäþùãýøãýøâû÷âû÷âû÷âû÷ßù÷ßù÷ßù÷ßù÷ÞøöÞøöÞøöÞøöÜöóÜöóÜöóÜöóÜöóÜöóÜöóÛôòÚóñÚóñÚóñÚóñÙòðÙòðÙòð×ñïUVOef_lmf©ª£‰‹„WXQ„…~mohde^stpjkfddbaa^eeeŸŸŸŽŽŽijljkm^_b]^aefi„…‡LMOijlrrtkkkžžž‹‹——šjimfel…„}}ˆfivUWiPQfPSkOTmDGd;B\@EZAGZ@E\?D]?B_@E^BH[SWey}‡yy‚mmwww‚……‘Ž……‘šš¥Œ•Ÿž¥Ÿž¨‚‹”“œ³²»š—¤Œ‹”¤£¨»»¾ÅÅÇÕÕ×ÏÏÒÆÆÈÔÔÖÈÈËßßâ»»¾ÍÍÏÇÇÉÈÈËÌÌÎËËÍÆÆÈÂÂÅÎÎÐÇÆË¬«°¶´»«ª±º¹ÂÎÎ×¾ÁÌ{€‹‚‰Ÿ¬±ãóôæúúæþúåÿúåÿúäþùãýøãýøâû÷âû÷âû÷âû÷ßù÷ßù÷ßù÷ßù÷ÞøöÞøöÞøöÞøöÜöóÜöóÜöóÜöóÜöóÜöóÜöóÛôòÚóñÚóñÚóñÚóñÙòðÙòðÙòð×ñïUVQ[\Wfhclmffha^_Xef_cd][\U^_[^_[Z[ViifccaŽŽŒttrceddfe]_^TVUehf{}bcekmlsssiiilll‘‘‘}}}vvxxxz{z‰ˆ€‡ddpVXhTUjTVoINh@E^AGZAGZ@EZ?D[?B_@E^>BWBFWkmz€€‰llvxx„‡‡”jiytt‚‚މˆ–•œŸž¨¨¦°zy‚ˆ†“ŽŒš…‚”“—¤¤¦··¹ÄÄÆÎÎÐÎÎÐÐÐÓ××ÚÔÔÖÛÛÝÏÏÒÎÎÐÏÏÒÌÌÎËËÍÍÍÏÅÅÇÈÈËÂÁƾ½Ä´³º·¶½²±ºÒÐÚÒÒÝŒš„‰~ˆŽÞïðêýýêÿþãýøåÿúäþùãýøãýøâû÷âû÷âû÷âû÷ßù÷áø÷áø÷áø÷ß÷öß÷öß÷öß÷öÝôóÝôóÝôóÝôóÝôóÝôóÝôóÜóòÛòñÛòñÛòñÛòñÚñðÚñðÚñðÙðïOOM[[Xiif…†klhefbcd]cd]NOJTTQUUSQQOppmppmXXVddbjjhbb_[[XWWUffdjjjjjjffdhheddbaa^^^\iifxxxqqqttrmmmomr__iPO_LMbGIbAD\AEVLOaNQf?AZAD\?AZ?BWBFZacr††‘}}ˆkkx‰‰–ˆˆ•ddq‹ŽŽ—‡‡˜˜˜¢ªª¶‹‹—˜˜¥˜Œžž¡°°²ÀÀÂËËÍÀÀÂÏÏÒÔÔÖÈÈËÛÛÝÅÅÇÒÒÔÆÆÈÇÇÉÆÆÈÍÍÏÆÆÆËËÍÉÈϾ½Ä­¬±¥¤©³²»ÆÄÐÒÐÚ·¶¿‡‹“‘šê÷ùéûùéþúäý÷æÿùåþøäý÷äý÷ãûöãûöãûöãú÷áøôãøôãøôãøôâ÷óâ÷óâ÷óâ÷óáöòáöòáöòáöòßôñßôñßôñÞóðÞóðÝòïÝòïÝòïÝòïÜñíÜñíÜñíSSSNNNkkissqqrm]^Zbc\ijeQQOLLIZZWMMJbb_ŽŽŒ^^\ZZWiifbb_\\Z[[Xbb_hheaa^ddbeecVVTddbaa^__]eeceecmmksrojieiii…„ˆ__kTScTVhQUfLP\UZeUXjEH\AEZ?AZ?BWBDXIHXlly††“}}‰‚‚Ž©©´¤¤°„„__kppyˆ””Ÿ••¢””¡¡¡­ªª³”žž¡´´···¹ËËÍÉÉÌÅÅÇÎÎÐÇÇÉÛÛÝÍÍÏÓÓÕÄÄÆÉÉÌÓÓÕÝÝßÚÚÚÆÆÈÆÅÌÄÂÉËÉΜ¡¯­·¿½ÉËÇÒÖÕÞœ£•šßíìëþûéþùæÿùæÿùåþøäý÷äý÷ãûöãûöãûöãûöãøôãøôãøôãøôâ÷óâ÷óâ÷óâ÷óáöòáöòáöòáöòßôñßôñßôñÞóðÞóðÝòïÝòïÝòïÝòïÜñíÜñíÜñíJJJMMM]][hhefhcbc^_aZfhcTTQOOM__]TTQUUS‚‚€~~{SSPbc^]^Z[\W\]Xbc^efb^_[efbiifPPN]][eechhemmkjjhddbppmbb____Ž{}‚^^hZZeX\dU[_\biZ^jFI[@DW@DXBF[HI^TSeiivzz‡ww‚–£¤ª²³¹ÅÆÌ‰‰•bboZZfŽ““žŽŽ—““œ¶¶¿¶´¹œœž¸¸º¸¸ºÂÂÅÒÒÔÂÂÅÐÐÓÔÔÖÔÔÖÓÓÕÐÐÓÇÇÉÆÆÈÈÈË¥¥¨···»»¾ÄÂÇÉÈÍ¿¾ÂÇÆË›š£²±ºÍÉÔ¾½ÆÀÁÇŽ”˜Üêéåøöéþùäý÷æÿùåþøäý÷äý÷ãûöãûöãûöãûöãøôãøôãøôãøôâ÷óâ÷óâ÷óâ÷óáöòáöòáöòáöòßôñßôñßôñÞóðÞóðÞóðÝòïÝòïÝòïÝòïÜñíÜñíAAALLLUUSccabc^Z[V^_Xab]WWUXXVUUSNNLXXVeec““LLI[\WWXTWXTZ[V_a\\]X\]X_a\^^\ZZW]][eeceecmmkjjhZZWffd[]\^a_vxwˆ‰Œklo]^bZ[]X]\]bcX\dDFS@BTDEZLMbTVhLJ[aam~~‰€€‰…†Œ¡¢¥¶·¹ÆÇËÆÆÒ……‘XWhbbo‹‹”„…‹——¡¤¥«ž¢¥¥¨¨¨ªÀÀ¶¶¸»»¾ËËÍÌÌÎÀÀÂÌÌÎÆÆÈÆÆÈÎÎÐÉÉÌŽŽyy{‹‹‹¨¨ªÂÂÅÀ¿Ä¿¾ÂÕÔÛ«ª±“‘›¹¶ÀÏÎ×Ö×Ý•›ŸÍÛÚèúøêÿúèÿúæÿùåþøäý÷äý÷ãûöãûöãûöãûöãøôãøôãøôãøôâ÷óâ÷óâ÷óâ÷óáöòáöòáöòáöòßôñßôñßôñÞóðÞóðÞóðÝòïÝòïÝòïÝòïÜñíÜñíHHHNNNVVTffd]^ZNOJQSL_a\WWU\\ZPPNPPN^^\cca}}zVVTXZU_aZWXQ_aZab[\]VZ[T_a\bb_]][ZZW^^\eeceecddbUUSX[ZX[Z^a_ceddddiiihheTVSTVQ[]Z^_cQQ[IIVEDTML\^]m]]jaaliir‚ˆ}~‰‹¯±°¾¿ÁÉÉÓÎÎÛ‡†–QQ^qqz˜šŸ˜˜¢–~}ÅÅǬ¬¯¿¿ÁËËÍÀÀž¾ÀÍÍÏÆÆÈ¸¸º½½¿ÎÎÐÍÍÏÓÓÕÎÎÐÌÌί¯±¾¾ÀÉÈ͸·¾½»ÂÐÏÖ“‘˜¹¶ÀÍÌÕÜÝãÍÓ×Õãâéûùæû÷ãûöæÿùåþøäý÷äý÷ãûöãûöãûöãûöäùöäùöäùöäùöãøôãøôãøôãøôâ÷óâ÷óâ÷óâ÷óßôñßôñßôñÞóðßôñßôñÞóðÞóðÝòïÝòïÝòïÝòïOOOGGGQQO]][VWSMNIUVOab]]][__]__][[XVVTaa^aa^]][TUPhibUVObc\bc\]^WWXQ^_[[[X]][VVT]][eecddbddbVXWSWXX]^[\^bdcbbbccalljWXTZ[Vbd_abdTU[JJTFFQJJVWWcaajijp\]c€„z{~}~¥¨¦±²´ÁÁËÐÐÝÍÍÚss€^^j››¤››¤¢¢«š˜¿¿Á³³¶ÅÅdz³¶ÈÈËÂÂÅËËÍÓÓÕÒÒÔªª¬ŸŸ¢¹¹»ËËÍÓÓÕÔÔÖããåééë··¹ÄÂÇËÉв±ºÂÁȯ­´¯«¶ÁÀÉÎÏÕÙÞãÛéèèúøæû÷äý÷æÿùåþøäý÷äý÷ãûöãûöãûöãûöäùöäùöäùöäùöãøôãøôãøôãøôâ÷óâ÷óâ÷óâ÷óßôñßôñßôñÞóðßôñßôñÞóðÞóðÝòïÝòïÝòïÝòïZZZPPPQQOOOMPQMNOJWXQ^_[[[X^^\__]\\ZVVTcca^^\ZZW_a\de^XZSde^ab[_aZbc\TUPZZW]][\\Z__]cca__]aa^VXWUZ[PUWNSUcdfiik]]]cab[ZWVWSccaddd\[_WV]TSZSQVTSW]^bvwycdfqrttwvwyx›œ˜šœ©ª°ÉÉÓ××á¾¾É[[hxx…ˆˆ•””‰ˆ½½¿ÝÝߢ¢¤°°²¾¾ÀÌÌÎÂÂÅËËÍÒÒÔ¦¦©––˜½½¿ÆÆÈÕÕ×ÚÚÜææéææéÛÛÛ¿¿ÁÍÌÕ¿¾ÇÍÌÓÈÇΣŸª·¶¿ÀÁÇÝãèáïíèúøèýøåþøæÿùåþøäý÷äý÷ãûöãûöãûöãûöäùöäùöäùöäùöãøôãøôãøôãøôâ÷óâ÷óâ÷óâ÷óßôñßôñßôñÞóðßôñßôñÞóðÞóðÝòïÝòïÝòïÝòïXXXaa^XXVTTQOPLOPLWXQZ[V[\Weec__]bb_[[X__]XXVUVQbc\de^STMXZSde^cd]]^WUVOWXTSSP]][XXV]][XXV[[XTVSNSTGLMEIJ_acaac]]]b_a_^\VVTcca^^^VVXTTVWWZZZ\WWWZ\[fih_ba_bafihqsrŽ‚…‹Œ‘ÅÆÌÖ×ÝÒÓÙ¥¥±vveeq‡‡“‡†Ž“âá囚ž´´·ÅÅÇÍÍÏÈÈËÈÈËÒÒÔÍÍÏææéÒÒÔÍÍÏÌÌÎßßâååèññóäääÇÇÉÆÅÌÐÏÖÈÇÎÄÂǽ¹Á­¬³ÅÆÉÎÔÖßëëé÷ôêûøêýùéþùåþøäý÷äý÷ãûöãûöãûöåúöäùöäùöäùöäùöãøôãøôãøôãøôâ÷óâ÷óâ÷óâ÷óßôñßóóßóóÞòòßôñßôñÞóðÞóðÝòïÝññÝññÝññUUS\]X_a\UVQQSNIJFOPL\]XZ[V]^Z^_[]^Z]^ZWXTZ[VXZUab[de^[\UMNG^_XWXQZ[TZ[TVWSWXT_a\XZUab]QSNXZU\\ZNPMVXWGIHXXXeee^^\aa^ccaUUSeecddbZZZSSS___[[[OOO[[[hhhXXVddbjjhyyw‡‡‡€€‚Œ‹¿¾ÅÒÒÔÈÈ˶´¹£¢¦~}„^]fvs€ˆ†“Ÿž¨“‘˜ž¢ÞÞáÒÒÔÌÌÌÇÇÉÅÅÇßßâÉÉÌÖÖÙÐÐÓÒÒÔÙÙÛÞÞÞêêêêêêÕÕÕÅÅÇÈÈË××ÚÀÀÂÀÀ··¹½¾ÀÉÎÏËÒÒÙßÝìöòìøôêýùéþùèýöåúóéþ÷åúóäùòäùôãööä÷÷ä÷ôåøöãöòåøôåøôâôñâôñâôñâôòáóñáóóáòöáòöáòöáóñáóðáóñáóñßòòßñôßñôßñôOPLUVQ]^ZZ[VHIEEFAMNIXZUTUP]^Z^_[WXT^_[XZUTUP]^Z\]V]^WXZSEF?WXQUVOZ[TZ[TXZU]^Z[\WZ[V^_[STOQSN]^ZSSP\\ZPPNVVTZZWQQOWWU\\ZPPNXXViif^^\LLIUUSWWUSSP^^^cca_a\cd_rsowxsttrqqs{z—–›¤¤¦‚‚‚ŸŸŸ¹¹»˜—œ€‰dbp}zˆ‡…‘Œ•–•œ©¨¬ÂÂÅÀÀÀÇÇÉÐÐÓÖÖÙºº½ÏÏÒÛÛÝÈÈËÉÉÌÝÝÝ×××ßßßÖÖÖÄÄÄÍÍÍÌÌÌÅÅÅÁÁÁÇÇǰ²±ÅÇÆÅÉÈÂÇÆìñðïøôìþúêÿúéþ÷éþ÷åúöèýøåúóâ÷òæù÷åøøãöóâôòæùöãöòâöïåøôâôñâôòáóñßòòáóóáòöáòøáòöáóñáóñáóñáóóßòòßñôßñ÷ßñ÷IJFQSN^_[^_[JLGBD?GHDTUPSTO\]X]^ZVWS^_[XZUTUP]^ZZ[T[\U]^WGHAVWPVWP[\UXZSXZS^_XZ[TXZS\]VNOHOPI^_[]^ZZ[VQSNSTO^_[QSNSTOXZUQSNWXTjkfXZUMNIQSNZ[V[[X__]eec_a\de^fhadeappmlllihl~}rrp€€~¥¥¥‰ˆ£¢©ecpb_lljw´³½´³ºœ¡±±³––˜´´·ÕÕ×ÛÛÝÜÜÞÍÍÏÖÖÙÈÈËÐÐÓÓÓÓÐÐÐÜÜÜÓÓÓÍÍÍÔÔÔÆÆÆÈÈÈÆÆÆ¾¾¾‹Œ¹»ºÎÓÒÁÆÅ×ÜÛôþúìþøèûôåøôåøôéûùåøöä÷ôæù÷âôòãöóåøôæùöãöòåøôåøôâôñä÷ôãöóâôôâôôáóóáòöáòöáòöáóñáóñáóóáóóßòòßñôßñôßñôHIETUPbc^^_[MNI>?:EFA[\WXZU\]X]^Z\]X]^ZWXTZ[VXZU^_X^_Xbc\STM[\U[\U]^WVWPZ[T]^WZ[TUVO[\UHIBQSL_aZUVQWXTWXTQSN\]XOPLSTO]^ZPQM\]XijeXZUVWSUVQbc^^_[ccaab]fhacd]bc\de^efb___aacqqsmmmhheqqo{{~ÂÁÆ{z„\[d[Zcdcjjimˆ‡Œ¨¨ª••—««­ËËÍÇÇÉßßâÔÔÖÕÕ×ÕÕ×ÓÓÕÙÙÙÙÙÙßßßáááÔÔÔÍÍÍÕÕÕÌÌ̹¹¹ÉÉÌœŸ²³¶³¸¹ÐÕÖÌÐÒéððíûùëûúìýûéùúéùýéøÿè÷ÿåôûå÷úä÷÷ä÷÷ãöóä÷ôâôòâôñä÷ôä÷ôãööãööâôôáóóáóóáóóáóóáóóáóóáóóáóóßòòßòòßòòßñôIJFIJFZ[V\]XLMH9:6BD?]^ZVWSUVQXZU\]X[\WZ[V^_[WXTab[\]V]^WXZSNOHTUNXZSXZSZ[Q]^UbcZ\]T\]TTULWXOZ[TSTMXZS]^WLMFZ[T[\U_aZbc\OPI]^Wde^bc\^_XWXQab[]^Z[\W^_[hibde\abX_aZ]^Zbb_VVXjjljjh_a\jkfccahhj¦¥ªÌËÏŽ”•”›zy~~‚ªª¬¥¥¨bbd­­°¾¾À¤¤¦¾¾ÀÀÀÂÍÍÏÓÓÕÒÒÔÜÜÜåååßßßâââÜÜÜÔÔÔÈÈÈÁÁÁÆÆÈÅÄÈž¢°±´­²´ÂÇÉÛßââèêêôøéöúÕâé·ÂÌ—£±—¢´š£¹¡«¾·ÅÓ°À˺ÌÓÍÞäâó÷áóóÝðíä÷ôÝððáóóáóóßòòáóóáóóáóóáóóáóóáóóáóóáóóáóóáóóáóóáóóLMHLMH\]X^_[QSN?@;EFA[\WOPLQSNZ[VVWSZ[VZ[VZ[VUVQ\]V[\U]^W\]VJLEPQJUVOUVOWXO\]TabXZ[QQSITULXZP[\SOPIWXQbc\UVOTUNWXQ[\U[\UNOHde^ab[[\U\]VUVO]^WXZS\]Xcd]Z[Q]^Ucd[]^UZ[T__]ZZZfffbb_Z[V_a\bb____‹‹žž¡¶´¹²±¶‰ˆ~~€œœž¸¸ºkkm‚‚…‘œœž¨¨ª´´·²²´½½¿ÍÍÏÐÐÐÚÚÚßßßéééæææÛÛÛÌÌ̸¸ºÎÍÒ¿¾Â¡¢¥©ª­«°²´¹»ÎÓÕáæëÏÖÝÇÎ×­´¿Ÿ¥¶¬±Æ¢»„‡¤„‹¦„¥€Ÿ‹›¨—¨²¨¹ÀÆ×ÝÜíñÞðóäöùâó÷ßñôÞññáóóáóóáóñáóñáòöáòöáòöáóóáóóáóóáóñáóñVWSQSN[\WZ[V[\WGHDHIEXZUNOJSTOZ[VXZUZ[VVWSXZUOPLWXQXZSWXQXZSGHAMNGPQJQSLSTJ[\S_aWUVMMNEQSIUVMZ[Q\]VQSLXZSXZSVWPZ[TXZSUVOOPIde^^_XWXQ\]VTUN[\UUVOZ[VZ[T]^U_bU^aTbcZUVOaa^\\\bbb\\ZXZUbc^iif^^^iiikkk´´·¡¡£‡‡‰œœž¥¥¨jjl‡‡‰ÄÄÆ””–††ˆ••—¹¹»¹¹»„‘‘‘ÒÒÒðððÔÔÔÙÙÙåååÙÙÙÆÆÈÂÁÆÎÍÔš›¡¬­³°³¹¥©¯»¿ÅÞâèëñóÖÜáÇÌÖ¸½Ëßãø±³ÎŽ­„‹¨~‹¢z‰›}ŒŽŸŽž­¡­¢²¿¾ÎÙÙêñãôúáòöÝððáóóáóñáóñáóñáòöáòøáòöáóóáóóáóñáóñáóðWXTTUP]^Z\]Xab]MNIJLGWXTIJFPQMNOJ[\W[\WPQMZ[VIJFUVOVWPOPIPQMDE@IJFNOJNOJPQJZ[Q^_VSTJOPGOPGNOFXZP[\UNOHUVOVWPIJDSTMWXQUVOPQJ\]V_aZZ[T^_XUVO[\UTUP\]XZ[V_aWcd[WXO\]Tab]^^\]][aa^\]X^_[dealmieecbbbTTQddb———¢¢¢}}}«««›››SSUyy{»»¾……‡ppr€€‚¾¾À˜˜›†††ppp¶¶¶äääíííæææâââÝÝÝÏÏÏÄÂÇÄÂÇÁÂÆŽ“±²¶—˜œ¨©¬ÒÖÙèìïÓ×Ú»¿Ç½Á͸»Ïœž·€‚Ÿ…¢}†ž{ˆ{ˆy†›x…š}‰žˆ•ª•£´¡¯½ËÜãáòøáòöáóóáóñáóðáóðáóóáòöáòöáóóáóóáóñáóñáóñSTOVWSWXTUVQUVQVWSPQMXZUGHDJLGOPLab]LMH[\WPQMIJFQSNMNISTOTTQIIGNNLLLLMMJSTOSTMUVOUVOQSLWXQSTMVWPVWPPQJOPISTMGHAQSLPQJSTMUVMUVM\]V^_XXZUUVQUVQMMJTTQZ[V]^W_aZab[[\UXZU^^\[[X\\Zdeade^ab[lmiffd__]UVQZ[Tjkf}~yool‚‚€iifXXXlll¡¡¡ŒŒŒ•••žžž~~~hhhddb““¸¸¶ÎÎÌååãÕÕÓÖÖÔ¯¯¬ÇÇǺº½ÐÐÓ±±³©©«ŸŸ¢Ÿ¥¦©ÍÎÒæèí¯¯¸©«¸›¯Ž¥†‡Ÿ„†¡ˆ¤”˜­Ÿ¤»¤©À“—¯‰Ž¨„t{•…¢¤²ÂÕåðáòøÞòòßôðßôíãøñâôñãóòãóòãóôâòóâòöâòöâòöJLGPQMVWSVWS[\WXZUNOJSTOGHDIJFUVQ_a\LMHWXTNOJEFAQSNLMHNNLUUSLLLLLLGGIJJJOPLPQJTUNTUNSTMMNGZ[T[\UVWPPQJOPISTMNOHLMFSTMOPIUVMUVMXZS]^WVWSTUPOOMHHFPPNXXV]^Zab[cd]^_[XXV]][^^\__]^_[^_XUVO^_[XXVTUPQSLVWNcd]mohbc^xytffd\\Z___qqq‡‡‡†††vvvmmm\\\^^\qrm¦¨£‰‹†×ÙÔ«¬¨ÄÅÀ‹ÌÌÌ···ÎÎÎÐÐÐÛÛÛ½½½ºººªª¬ÝÜãÒÐÚ¾¾É¬«»”–¨‡ˆˆ‰¢‰‹£…‡Ÿ†ˆ¡“«›¶¢¤½–˜±Ž©„ˆŸy‚˜‡•¦£±¿ÕæíÞðóÛðìáöïßôíâôñãóòãóòãóôâòóâòöâñøâñøFGBNOJTUPVWSVWSTUPJLGOPLPQMLMHZ[VTUPJLGVWSVWSNOJOPLMNIMMJSSPPPPGGG@@BGGGIJFQSLMNGUVONOHWXQ]^W^_XVWPPQJOPISTMUVOHIBOPINOHUVMUVMVWN[\UQSLUVQQSNPQMOOMVVTWXTZ[Tef_deaZZW^^\[[Xaa^XZU^_X[\U]^ZPPNJLGUVO\]Tab[bc\TUPefb[[XQQO\\Z__]eeeqqqxxxiiiqqsVVV\\Zffdlljyyw¶¶³{{y——•rrp´´´³³³ÆÆÆÁÁÁÈÈȬ¬¬½½½»»¾âáèÇÅÒÍÌÜ–•¨‘“©€˜{{—„„¢€‚Ÿwy–~€›‘ª£¦»²¶ÉŸ£´–©€ˆœ{†˜‚¡¬»ÆÚëñæùùãøôáöñâôòãóòãóôãóôâòóâòöâòöâòö@@>FFDJJHJJHVVTPPNBB@DE@QSNJLG[\WTUPJLGTUPUVQIJFIJFPQMNNLOOMSSSEEE::=EEEHIEHIEQSNQSNNOJQSNTUPZ[VVWSPQMOPLSTOXZUIJFJLGNOHJLBTULXZP]^WNOHSTOMNIJLGPPNPPNOPLPQJ]^Wbc^XXVVVT\\ZccaPQMVWPWXQWXTJJHGHDVWP]^U^_XXZSPQMcd_bb_]][TTQ\\Z___hhh[[[TTV^^aLLNNNNbb_ddbiif‚‚€eecmmk]][ŸŸŸ³³³ººº¾¾¾………{{{žžžÂÂÅÙ×ÜÆÅÎÆÆÒ°¯¿Ö×ì¿ÀÙ••±††¤wx—xy˜}œ€‚›‹Ž£”—©¢°šŸ­•©t‘w“Œ›¥ÏÞæÜíóßñôä÷÷ãóôãóôãóôãóôâòóâòóâòóâòö>>>AAAMMMFFFHHHJJJAAA@@>PQMPQMXZUMNI@A=HIENOJEFAGHDFGBFFDGGENNNAAA99;>>>DDA@@>LLIMMJLLIJJHNNLOOMUUSMMJIIGPPN]][SSPJJHMNISTJWXO^_X^_XPQMEFAHHFIIGLLIPPNVWSSTM^_X]^ZSSPTTQUUS]][UVQUVOZ[TUVQHHFMNIWXQ_aWab[]^WUVQ\]XZZWPPNUVQXXVQQO[[[UUUMMOONSGGIPPPZZZZZZ\\\TTT[[[\\\iii‹‹‹Â–––°°°sss€€€ˆˆˆžžž½½ºÉÉÇÀÁÅ••žÅÇÖÐÒæ˜š²‡‡¥{}œxy˜xz•}—‚†š˜œ­šžª¨­»¢ª½‹“¦r}Žsލ·ÆÐÜíôÛìòãó÷äôöãóôäôöãóôâòóâòóâòó666;;;GGG>>>DDDAAA>>>AAAMMJJLGPQMNOJBD?HIELMHDE@DE@EFAEEBDDASSSFFF88:::=;;;@@>??=IIGGGELLIGGEFFDOOMLLIFFDQQOXXVSSPNNLHIELMFSTJ\]V^_XWXTGHDFFDDDAGGEJJHQSNMNG[\U]^ZSSPOOMVVTXXVUVQPQJVWPLMHIIGSTO^_Xfh^fhabc\VWSQSNSSPXXVNOJTUPWWUPPPQQTGGIHGLA@ENNP[[[UUU___WWWSSS]]]ZZZbbbœœœ~~~jjjlllooo‚‚‚‹‹‹±²­ÇÈά«xy¦ª´}Ž‚—xy‘rty{–{~–wz…˜¢šž¬£¨¶¢¨º˜¬rzlwˆr}ŽŒšª²ÀÎãóþâñøãó÷äôøâòóãóôãóôâòñâòñ>>@::=FFHFFHJJMHHJBBE999MMJIJFGHDDE@BD?FGBLMHGHDBD?FGBFFDBB@TTTJJJ88:99;888777>>>BBBLLLEEEGGGGGGJJJFFFGGGQQQQQQUUUOOODDAMNGPQHVWPVWPWXTIJFLLILLINNLLLIMNIHIB^_Xfhc\\ZTTQWWU[[XZ[VUVOWXQOPLHHFTUPbc\ijahibab[XZUFGBJJHXXVOPLXZUUUSNNNSSUPPSQPUDBGJJMUUWPPS^^aJJMHHJPPSbbd^^acceXX[VVX[[]ddf~~€‚‚…¯¯¯–––£¤¦mot˜z~ˆoq~qs‚ps‡{”{”rv‹tx„‡œ‚†›Ž‘¦—œ±‘¦iq…fo‚s~ˆ“¥—¥·ÄÒâÜëóâñøâòöâòóãóôãóòãóòâóð???>>>IIIGGI??A;;>AADAAAEEBHIEEFA?@;?@;BD?LMHMNIDE@IJFIIGDDAQQQNNN:::;;;777666===AAAJJJNNNMMMNNNGGG>>>JJJPPPMMMVVVLLLFFDGHDMNGUVOVWP]^ZOPLQQOQQOJJHEEBHIEFGBUVQbc^VVTJJHOOMZ[VVWSXZUQSNXZULLI]][^_Xde\cd]\]Vab]NOJNNLSSP\]XXZUXXVJJHQQQPPSUTXLJOFEIIHMNMQZZ\PPSMMOOOQ[[][[]]]___bWWZTTViikŽŽooq‚‚…yy{ˆ‰fhkz~„kotfjrilwoq~vx‡rt„fizwx„…›~•„†žˆ‹£…‰¡vz‰‘¤qypyˆ‘ª˜¥ºÅÔÞÛêñßðóßðñâòóãóòãóòãóò480794BEALNM>?A236687FHE@@>FFDFFD>>;GGEAA?FFDHHFDDALLIJJHJJHVVT]][TTQFFD442997;;9@@>DDALLIJJHBB@BEAEGFILJEFHFGINPO@BAGIFDDAIIGUVQ[\WOPLLMH997???GGEBB@FFDEEB]][[[XQQONNLLMHSTONOJWWUSSPMMMIIIUUSef_de\ab[ef_cd_TUPMMJNNLWWU\\Z[[XTUPMMJNNLUUUSSUDEJEFLFGMVW[MNQIJNIJMUVX[[[QQQUUUVVVOOO]]]eeeeeeefi^_bijlabdcdhopshilefjdekqqzssjjwrq‹‰œ˜—¬‡ˆž„„ŸoqŒcfzw}{”s{‘t{˜~‡¢›¬ÌÙßßìïâðïäôöáñòãööáóóAE:AE=EGBDFE9:=013687ILHEEBLLIGGE886663@@>GGEEEB??=MMJPPNQQOaa^bb_XXVTTQ??=@@>;;9DDAFFDLLIJJHAA?JMIEGFGHJFGIDEGIJMJMLFHEFFFGGGVVTXZUQSNTTQ???;;;FFD@@>FFDNNLiif__]SSPSSPMNIOPLOOMJJHQQQFFFDDFBBBVWPab[ab[TUP\]XVVTMMJMMJSSSWWWPPNXZUIJFNNLNNNOOQFGMDDMGHNTU[NOSEFIEFHVWZSSSMMMTTTXXXQQQVVV[[[WWW^_bUVX^_b]^a]^abcebce]^abcfdei{}‚ffpvv‚Œœ«ª½Œ‰¡‰‰¥ij‚advsx†£¦º{€—tx–t{—€ˆ›¤ÛèêäòñãóôäôöÛííä÷÷BF;=@8>@;>@?78:-/1243BEAMMJOOMFFD220220??=EEBGGE@@>IIGJJHLLIUUSbb_ccaaa^OOMEEB997BB@DDALLIJJHBB@DFB>@??@B?@B:;>@ADNPOILHLLLNNNZZW\]XUVQOOMPPP@@@LLIMMJIIGJJHbb___]TTQLLIUVQMNIOOMNNLNNN===::=???PQMXZS[\WGHD\\ZLLIFFFIIIQQQWWWLLIXZUJLGOOMOOOJJMGHL@AGEFLNOSOPTFGIFGIWZXMMMHHHNNNTTTVVVUUUSSSWWWTUWUVX\]_VWZbce]^a]^abcebcfdeibci^^hhhsllyzy‰‹‰žˆ‰¢qrˆikzšœ©¬°Á–š¯qsrwr{‹v€ˆÅÒÔâðïáñôãó÷åö÷ßðñTWMNQI?A=@BA@AD347243?A>NNLIIG??=774>>;;;9==:JJHGGEHHFHHFQQOJJHQQOSSPXXV]][HHF774AA???=IIGMMJGGE:=9;>=@AD=>@;=?;=?EGFDFBGGGOOOOOMXZUWXTJJHJJJ???LLIHHFAA?GGEZZWTTQJJHJJHHIEHIEHHFGGE@@@;;;88:AAA\]XXZUXZUUUSLLI???IIIGGGJJJQQQQQO_a\QSNQQOSSSFFH@AE;=BBDGGHLPQTMNPMONX[ZJJJEEEIIINNNIIITTTTTTVVVOPSNOQTUWVWZXZ\_acXZ\[\^^_cefjfhmQSXeeoddpxx…†…•‘“¨z}Ž_bomq{ž—˜­~—txqw…w‰Ÿª­Üéëäñøâñøãó÷áñò[^TOSJ8:68:9@AD124364>@=LLIJJHAA?::8HHF;;9??=QQOBB@??=QQOSSPNNLOOMOOMNNLZZWEEB::8EEBEEBFFDLLIPPN9;80219:=46801389;>@?@B?FFFQQQSSPNOJXZUSSP>>>BBBOOMLLIGGEFFDOOMHHFBB@BB@EFA?@;AA?DDADDD???::=EEEPPNPQM[[XAA?>>>:::FFHPPSFFFMMMNNLXZUSTOMMJSSSIIL?@D:;?GHLSTVIJMMONNPOUWTOOONNNFFFMMMHHHQQQOOOQQQLMONOQOPSMNPXZ\]^aVWZPQTVWZVW[^_c]^b[\b_afffpmmyz}‰acp[^feiqmp}‰ˆ˜{zoq‚lq{ipw‡“ÅÏÕáëóÞëòßìñéöúTWMLOGDFA;>=@AD679132@B?LLIQQOGGE774MMJEEBAA?NNLEEBAA?PPNLLIWWULLIFFDIIGVVTAA?442??=BB@IIGJJHTTQ>@=79889;/02124>?A?A@GIFGGGEEEHHFQSN[\W^^\LLLLLLLLIIIGJJHEEBIIGIIGAA?GGE@A=DE@HHF@@>BBBHHHEEGBBBJJHMMJZZWBBB@@@NNPGGIMMODDDAAA>>;NOJXZUMMJPPPIIIBDFBDGNOQZ[]LNMLNMJMIQTPVVVQQQEEELLLHHHNNNSSSVVVPQTOPSPQTFGITUW[\^UVXTUWQSUTUW\]_^_cOPTVW[cdhklrdhpSV^W\^efjss}€€vt…oo{eiqekpv~¶½ÄÜãì¸ÁÌâìòâïóMPFMPHNPL=?>=>@78:8:9LNJGGENNLHHF>>;PPNNNL>>;JJHBB@@@>MMJFFDUUSTTQNNLHHFWWU@@>331;;9DDAQQOIIGUUSFHE;>=89;34789;@AD:=;>@=HHH>>>HHF]^Zab]\\ZZZZLLLLLIMMJHHF@@>DDAEEB774IIG@A=;=8FFDBB@DDDJJJNNPGGGGGELLI[[[EEENNPQQT@?DBBE;;;>>>??=QSN^_[LLIJJJIIIGHJHILMNPUWVNPOHJGEGDMOLSSSVVVLLLOOOMMMJJJWWWWWWVWZMNPIJMIJMPQTPQTZ[]WX[LMONOQ[\^_acUVXUVX^_bbceX]_TX[dehdehdcjvt~wtjirbfibhjjpt£©°¿ÆÐ”žÌÖÜÙãæIMBSVNPSN=?>=>@1249;:HJGMMJFFD??=@@>AA?UUS>>;TTQFFDGGEUUSMMJLLIOOMOOMLLI\\ZEEB663>>;FFD[[XFFDNNLBEA8:92364682369;:HJGILHDDDFFDIJFJLG[\WPQMJJH??=GGETTQJJH886>>;MMJ;;9HHFFGB?@;NNLIIGFFFSSSUUU???GGGMMM^^^JJMIILEDHDBG;:?88:>>>==:HIE^_[GGEFFFHHJBDFFGIGHJSUTOQPGIF@B?ILHGGEXXXWWWVVVSSSHHHXXXUUUQTSQSUGHJMNPMNPNOQXZ\\]_QSUPQTVXWX[Z[]\UWV^a_abd^cdPUVacbbdcbaehfmmlsbah^cdejkilrv{‚‚‡“}„Ž»ÂÉÙãæGH?PQJWXTMMM@@B//1BBBBB@JMH:=8362798>@?TVSFHDTVQDE@MNIVWSOPLNOJJLGMNIHIEQQOOOM9:6FGBVWSab]GHDLMHJJJ>>@224224DDDIII??=DDALLIHHFMNINOJVWP^_XSTMHIEJJHMMJDDA442::8886886EEBNNL@@>EEBTTQAA?LLIXXVIIIOOOEEETTVPPSVUZFEIBAH:9>88:???@@>JJH]][AA????JJMABFFGJHIMFGIXZ\MONILJMOLIIGTTQ^^\MMJTTQPPNNNLTTQSUTQTSNPOLNMILJILJQTS\^][\^UVXUVXVWZ^_b[\^[\^]^a\]__ac\]_^_babd^_c^_c_ac^_bijlhioeiq_dp^co€‡Ž•œ£@A8MNGOPLIIIDDF113:::;;9PSNAD?3644768:9NPO@B>OSJNOJLMHOPLLMHPQMFGBLMHAB>UUS[[XGHD?@;HIBZ[THIBJLGFFH327224BBELLLPPPAA???=??=??=HHFNOJPQM\]VUVONOHJLGPPNNNL;;9442663774GGEPPNBB@AA?QQOIIGEEBPPNSSPWWWIIIGGI??AFEI@?D=;B98=779??ADDDZZWaa^LLL@@BJJM9:>?@DDEHFGJOPSGHJGIHJMLJJHOPLZ[VUVQXZUVWSQSNVVTPSQX[ZWZXLNMHJIFHGJMLUWV\]_TUWQSUTUWZ[]WX[STVXZ\[\^XZ\[\^Z[]^_bQSUVWZ\]_bbbcce_afadlX\fX]hsy€}„‹GH?LMFTUPFFFQQT113111;;9MOJAD@/10/02468JML=?;JMHNOJIJFOPLMNIGHD?@;IJFEFAFFDUUSWXTPQMNOHWXQJLEQSNLLL99;,,/;;;UUUUUSNNL@@>@@>>>>EEBGGELMHVWSNOHGHABD?MMJPPNHHF886220997@@>SSPDDA==:NNLJJHFFDPPNTTQWWUJJJNNNHHJ@@B;:??>BIHM@@B??AMMMZZWZZWQQQ;;>GGI:;?;=@?@DBDGMNPHILGIHHJIMMJNNLUUSZZWVVTUUSPPNTTQQTSWZXVXWOQPHJIGIHGIHOQPXZ\QSUNOQVWZXZ\Z[]PQTWX[XZ\VWZXZ\WX[]^aPQTQSU]^a_acWX[TU[[^fSV^LOW_ej_ejLMDQSLNOJ@@@SSU>>@777;;9LNJFHE236347679LMO>@=MOLPPNIIGOOMEEBBB@AA?FFDDDAMMJVVTVWSFGBFG@VWPQSLVWSFFF447;;;777LLITTQHIEEFADDDAAAGGGIIGFFDTUPQSNMNIMMJUUSMMJPPN==:++)997??=TTQDDA>>;LLILLIIIGNNLPPN\\ZIIGUUULLLWWZMMOFEI87;668==?HHHQQO\\ZJJJMMOHHJ89=9:>@AEHIMIJMEFHADB?A@OOOQQQSSSVVVNNNQQQNNNPPPSUTLNMMONSUTNPOILJHJIMONWX[TUWJLNMNPTUWTUWIJMTUWTUWWX[TUWVWZUVXSTVJLNXZ\WX[OTVIMSPTZQU]OSXZ^aW\^VWNUVOMNIDDDOOQTTVHHH::8>@==?>*+-&(+67:@AD@BAEGFFFF>>>FFFFFFMMMPPPPPPMMJAA?QQOWXTHIEIJDNOHTUNPQMJJHGGGTTTFFDIIGVWSSTO>?:888668>>>AAA>>;HHFPPNSSPSSPMMJNNLQQOIIG774442??=VVTOOMEEBFFDUUSMMJIIGMMJXZUXXVWWULLLTTTLLN--0336113>>@HHHUUS\\ZOOOLLN??A67::;?=>AGHLDEGFGI=?>EGFLLLTTVLLNOOQLLNNNPGGIQQQSUTOQPQTSOQPWZXPSQOQPZ\[VWZUVXGHJLMOPQTXZ\FGIHILPQTQSUTUWWX[STVZ[]MNPPQTMQSPUWJNTBFLLOUVZ_TXZTUWWXOLMFHIE???DDFGGI>>>11/79878:)*-*+/237469468:=;DDD======AAADDD@@@@@@DDDEEBUUSVWS?@;@A:FG@VWP[\WQQO[[[SSPEEBNOJQSNOPI894AAA>>@>>@======JJHPPNJJHIIGMMJHHFNNLOOM@@>AA?BB@UUSVVTNNLHHFSSPIIGMMJJJHUVQSTOLLIQQONNNOOO;;>IIL88:;;>QQQOOM[[X\\\BBEDDF?@D?@D;=@>?BDEGDEG9;:;>=EEGPPSJJMGGIGGIJJMFFHLLNJMLMONQTSPSQSUTSUTUWVTVUOPSNOQEFHIJMIJMPQTBDFFGILMOPQTSTVTUWMNPVWZTUWOTUFMMPVXPTZEHNIMSTUXQTSQTSUVMPQJEFABBB??AEEGBBB886243236(),/0634:67:78:=?>FFH::=::=??AAAD::=::=AAATTQVVTWXTMNIJLEFG@NOHOPLTTQ^^\]][GHDMNIQSLEF?9:6IILGFJ??A::=999HHHMMJGGEGGEJJHGGENNLSSPGGE??=;;9OOMWWUTTQGGEIIGJJHNNLFFDQSNLMHMNILLINNLNNNFFF@@@GGIMMOUUUGGEXXVNNNAAD88:78;9:>?@D@AE:;>>?A?A@@BAEEGNNPLLNFFHEEGGGIEEGEEGFHGMONOQPSUTTVUQTSVXWOQPTUWNOQEFHEFHBDFMNPHILNOQHILJLNPQTQSUHILPQTWX[MQSAGIMSUQW\IMSMQTTUWTTQVVTJLEIJDHIE??=BBBQQQIII444-/1236+,0/03-/29:>;=??A@JJM447@@B@@B>>@::=::=>>@@@@UUS[\WGHD?@;BD?OPLWXTPPN\\Z\\ZLMHGHDLMHDE@==:LLNMMOAAD==?777AAAJJHLLIHHFBB@>>;@@>@@>BB@>>>999HHHPPPMMJFFDJJHFFDFFDLLIMNINOJJJHIIGMMJ[[[XXXUUULLNPPSQQQDDAUUSPPP99;44778;=>AIJNIJM9:=?@BDEGBDFBBEEEGFFHBBBBBBEEGFFHAADEGFNPONPOSUTPSQILJVXWVXWUVXOPSJLNJLNEFHJLNFGIFGIFGIHILLMOPQTHILMNPWX[GLM=BEJPSOUWJOQLPQPSQNPMTTQNOJOPLPQMGHDDE@GGEBBE87;:;A01778;013124468:;>>?AEEG779779AADIIL99;336::=HHHZZWUUSEEB>>;FFDLLI[[XPPNZZZ\\\PPNBB@MMJBB@BBBDFEILJ;>=FHG=?>8:9MONFHGLNM@B?9;8=?;?A>;>=78:348=>AGHJHJIILHLNIJMIHJGFHGHJINPOFHGFHGFHGLMO?@B:;>ABEIJMEGF?A>TVSOQP@AD89;/039:>FGIUWV=?>;=?:;>?@D=>AEFHSUTOQNEGD=?>@AD?@BLNMNPOPSQQTSQTSJMLNPOX[ZTUWPQTIJMNOQJLNGHJGHJIJMDFEGIHGIHMONFHGLNMVXWMNPINOHMNMQSLPQHMNINOMQPQTSPPNMMJLMHDE>;=8AA?>>@32911:/06;=@6796879;:9:=:;>>>@224779??A==?224//1668===IIGVVTNNL>>;EEBPPNTTQZZZXXX\\\IIIAAAGGGFFF@@@?A@BEDDFEBED:=;8:9JMLEGFILJ>@?362362:=;89;46923967=@AEDFEEGDGIEFHEEGFDFEJLNNOQDEGABEFGIQSUDEG9:=BDFABEDFE@B?OQNTVUIJMABE2379:>EFHVXWEGF;=?78;:;?>?BIJMTVSTVQJMHBEADEG?@DGHJHJILNMQTSMONHJILNMTVUWX[OPSIJMMNPPQTJLNEFHABEGIHHJINPOLNMJMLSUTTVUMONFJLEIJINOHMNEIJGLMINOLPQIIGQQOTUPFG@9:6??===?329,,6-/4?@D?@B243=?>;=?>?A?@D12667:78;-/2+,0126;=?>>>HHFUUSQQOAA?AA?JJHUUSUUUZZZWWWPPP@@@JJJEEEEEEADB@BAHJIADB9;:9;:HJIEGFMONDFE9;8796=?>9:=46912889??@D=?>;>:?A=BEAFHGILJGHJJLN?@B?@B?@BQSUNOQLMO>?AEFHILJ?A>NPMSUTHIL@AD:;?ABFGHJVXWSUT>?A78;89=469GHJQTPWZUOQMILHEFH>?BJLNHILFGIGHJEFHBDFFGILMONOQIJMGHJEFHJLNJLNHILEFHEGFFHGJMLEGFBEDMONQTSNPOHMNGLMLPQJOPBGHDHIGLMINOQQOUUSUVQGHA=>9BB@AAD98?//8+,2>?BEFH687ADB:;>:;>>?B126:;?:;?237014348:;>???MMJLLIDDA>>;FFDHHFQQOWWWUUUZZZPPPEEEIIINNNGGG@BA8:9=?>:=;7989;:FHGDFEHJIDFE=?;9;8DFE>?A469/0667=>?B>@?=?;FHDFHEFHGFHG>?AFGI?@BBDF;=?EFH;=?9:=78:?@B=?>=?>PSQLNM=>@67:67:ABFDEGJML\^]GHJ>?B89=:;?MNPPSOTVQOQMILHGHJABFHILGHJEFHEFH?@B?@BBDFFGIHILMNPNOQ?@BIJMJLNIJMEFHFHGNPOJMLFHGILJMONVXWLNMEIJDHIHMNGLM?DEAFGDHIFJLSSPWWUWXTPQJ=>9??=DDFA@GEEN12878;347798@BA@AD4687;>&*037=14:-17*-3*-3-/2:::NNLQQOIIG??=AA?GGELLINNNUUUWWWNNNAAAHHHQQQGGGEGF?A@9;:ADB8:99;:DFE@BAEGFBED@B?=?;GIH9:=126-/478>;=@ADB>@=BE@?A>:=;798>?A;=?67978:67989;78:3479:>:;?9:=>?AGHJPQTFGJ46989=?@DEFHEGF\^]LMO=>A12667:FGIQTPX[V^a\JMIHIL;=@?@D>?B?@D?@D;=@:;?@AEHIMGHJ?@BJLN9:=ABELMODEG=>@HJIOQPJMLFHGFHGEGFNPOHJIAFG@EFDHIAFG>BD;@ABGHGLMOOMUUSUVQOPI894886==?>=D88A/0689=6799;:ADB>?A12637=$(-,06(+1*-3(+1*-3014;;;LLINNLHHF@@>==:??=HHFJJJUUUTTTQQQ===GGGMMMIII@BA=?>9;:HJI?A@>@?DFEBEDADBBEDEGDGIFILJ;=?46912834:78;>@?>@=GIEEGDBEDADB>?A9:=12434767989;89;67:78>;=B89=89;DEGNOSDEJ12878;=>AABEDFE[]\PQTBDG9:>FGJMNPSUQWZU]_[PSOLMO?@D;=@:;??@D>?B78;9:>ABFIJNMNPGHJPQT@ADGHJIJMGHJGHJPSQOQPNPOEGFGIHEGFMONMONFJLDHIFJLDHI;@A;@ABGHEIJSSPUUSPQMGHA340997;;>218++4,-378;679364>@?>?A469-17&*2/2:,08%)1%)1*-6239PPPQQOBB@442==:??=;;9==:IIIOOOUUUSSS;;;AAAIIIDDD@BA=?>>@?JMLEGF?A@?A@?A@9;:?A@GIFLNJILJ;=?469128/060149;::=9FHDBEA=?>8:99:=67901334746878:78:46934:89?46967:HIMIJN?@F67=34889=?@BDFESUTPQTDEH>?BGHLIJMOQNSUPZ\WUWTOPS?@D9:@9:@>?E:;A78>89?=>D@AEABEABENOQEFHEFHFGIJLNLMOGIHGIHMONJMLGIHADBFHGHJIBGH?DE@EF=AB9>?;@ABGHBGHNNLQSNOPIFG@:;7::8779,+2%&,,-3469124687>?A;=?014),4#&/&*2"%-"%-#&,*-3348DFELLIFFD??=886DDALLIGGEBBBNNNPPNTTQ;;9IIG@@@>>>9;:@BAGIHPSQOQPEGFDFE?A@=?>BEDLNJQTPGIH9:=126-/467=237:=;=?;@B?=?;9;:78:89=67:01434812634834812622;33=12878;IJNNOSDEJ78>12889==>@ABESTVVWZJLNFGJNOSHILILHJMHQTOTVSMON;=?9:>67=:;A9:@12878>>?EABH>?B?@BHILABE89;?@BJLNIJMFHGJMLLNMQTSNPOADBFHGIJMDHI?DE?DE;@A7;=;@ABGH@EFPQMMNGOPISTMMNIBBB=;@43:)*0()/78;3474689:=78;/06**6%%1$$-%%/()/126236013>@?BED@BA9;:;>=ADBFHGLNMPPPHHFQSNQSNHIELMHHHFBBB78:@ADFHEMOLLNJJMIIJM@AD>?ADFEOQNNPMADB78:34:,,612812689;9;::=;89;78;78>14:14=03;/2=-1;69A26>03;009009/0678;GHJJLO@AG34:1289:@?@D=>AFGJVWZEFHEFH@@BLLNFFFIIGUUSUUSNNLGGGEFH89=34:67=11:88A66?88A?@DEFHHILBDF=>@=>@GHJEFHEFHBDFIJMNOQGHJGHJEFHHIL:;?=>A>?B:;?9:>9:>=>A:;?PQJIJDZ[TMNIDDA===76:218*+1,-3:;?236-/1348128((1))4%%2%%1&&0&(--/2468687?A@:=;798798?A@?A@BEDADB???GGGJLGOPI892>?:???;;>89=ABEFHENPLQTOGIFFGIFGJBDFABEGIHNPMJML=>@239,,634:67=9:>236?@B?@D;=B46;37?,0:+-:02?13@79F14?,08--922;017237:;>QSVFGM67=34:78>EFL=>DBDGNOSGHJ>?A??ALLNHHHFFFSSPWWUPQMEEBNOQ?@D34:239//866?11=>>G?@DDEGGHJ@AD:;>=>@DEGDEG>?A=>@HILNOQMNPFGIABEGHJDEH@AE;=@78;=>A=>A>?B=>AQSLGHAWXQOPLBB@III649107+,2128>?B013+,/126/06%%/&&2$$1%%1))2%&,*+/9:=>@?>@?9;:364243:=;BED>@?>@?GGIGGGNNLLMHAB>IIG;;;==?9:>>?A>@=DFASUP@B?;=?@AE@AD9:=:=;GIFNPO?@B017//834:89?=>A89;>?A89=34:34:26>+/9*,9/1>13@79F14?,0822>//8,-3348?@BOPT@AG23923967=DEJ;=BABFMNQHIL;=?JJMIILFFFHHHVVTTTQMNIHHFX[ZWX\89=67=34:66?11:88A=>A@AEABF:;?78;;=@?@DABF?@B>?AHILNOQMNPFGIABEGHJ?@D9:>67:469BDGEFIBDGDEHLMFQSLTUNNOJMMJ@@@327/-4()/128=>A)*,*+-/03,-3$$-%%1$$1&&2**3#$*&(+;=?BEDEGF679/02679679:;>ABE@ADDDFDDFNNLPPNOOMMMJJJMAAD>?BDEG>@=>@;NPL:=9124014@AD>?A:=;BEALNM=>@-/400967=23934812478:78;67=34:/2:-1;,/;+-:-0=68E26@03;11=11:,-3014FGISTWIJP67=-/467==>D9:@ABFQSVIJM=>@>>@@@BEEEFFFTTQVVTOPLFFDZ\[abdABF237/0612899B67=BDIEFIEFI=>A469:;?;=@@AE?@B=>@DEGHILGHJGHJEFHHILGHL=>A469126>?BBDG@AE?@DSTMIJDQSLVWSEEB@@@98=/-4()/128;=@+,/*+-)*-#$*$$-%%1##0$$0&&0&(-)*-BDFILJ236/03,-1348;=@67:78;34898===?GGGLLLAAA???336-,1+,0236AD@HJFTVQGIF124/03=>@>?AADBEGDBED89;,-3++412846;78;01378:89=89?78>,08(+6-0=02?+-:+-:+/9+/7--9,,6,-3469LMOLMPNOU:;A/0646;89?9:@@AEIJN@AD9:=AAD==?:::AAATTQ[[XLMHLLIZ\[TUWMNP=>A126/06*+19:@;=B;=B>?E46;67==>D?@F>?B;=?;=?BDFEFHIJMIJMHILFGIDEGEFH679124?@BHILHILDEG?@9@A:PQJUVQTTQFFF438(&-()/78>BDG/02)*,)*-#$*%%/##/""/$$0**3()/014GHJTUW89=/03+,0-/2/03014:;?237,+0;:?BBEHHHEEE@@B76:0/34699:=:=9?A=OQMLNJ:;>78;89;;=?>@?=?;>@?78:-/4,,646;46;469,-089;67:128-/4+/7),7,/;,/;*,9*,9*-8*-6--9,,6&(-9:>JLNJLOQSXLMS0172399:@46;BDGDEH>?A;=?HHJ99;888>>>MMJOOMIJFMNIPSOTVUUVXNOQ:;?014/0646;89?67=78>34:01789?;=B:;A9:>468=>@EFHGHJGHJEFHBDFDEGABE9:=89;=>@DEGEFH>?A:;4>?8PQJWXTMMJBBB327%$+*+1?@FJLO347,-0,-1)*0++4((3$$1**666?$%+126BDFSTV:;?-/4,-3+,2239-/4017)*00/698=HHJHHHEEE??A98=/-4:;?;=?8:79;7NPLJMI9:=67:89;@AD@BA9;88:9679/06--746;128126,-078:4699:@ABH+/7),7,/;(*7)+8)+8),7),4))4009+,278;BDFFGJFGM:;A9:@01723934:>?B@AE;=?:;>>>@::=>>>===IIGOOMSTOQSNLNJQTSNPOIJM469-/2126;=B:;A66?33=22;11:77@;;E;=B@AE9:=;=?@AD?@BDEGGHJIJMHJI=?>687798=?>ADBFHGADB>?8:;4IJDTUPIIGHHH:9>&%,+,2DEJQSV78:124237/0622;%%1""/**699B()/78;?@BQSU9:>+,2/06,-3,-39:@89?67=43::9>AADHHHBBB::=76:+*189=78:;>::=8QTOEGD-/1+,0236>?A>@?241364468017--7017,-3014/0223678;78>34:*-6*-8+-:$&3(*7(*7(+6(+3++7))2,-39:>GHJIJNOPVQSX@AG017*+146;;=@?@D89;89;??A==?777;;;FFDOOMTUPPQMLNJSUQLNMGHJ/03-/2+,0;=B??H66?22;33=33=22;33=67=78;4689:=9:=@ADEFHHILIJMDFE4763648:9@BA@BAFHGHJI \ No newline at end of file diff --git a/third-party/webp/libwebp/examples/unicode.h b/third-party/webp/libwebp/examples/unicode.h new file mode 100644 index 0000000000..0831e23cbc --- /dev/null +++ b/third-party/webp/libwebp/examples/unicode.h @@ -0,0 +1,116 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Unicode support for Windows. The main idea is to maintain an array of Unicode +// arguments (wargv) and use it only for file paths. The regular argv is used +// for everything else. +// +// Author: Yannis Guyon (yguyon@google.com) + +#ifndef WEBP_EXAMPLES_UNICODE_H_ +#define WEBP_EXAMPLES_UNICODE_H_ + +#include + +#if defined(_WIN32) && defined(_UNICODE) + +// wchar_t is used instead of TCHAR because we only perform additional work when +// Unicode is enabled and because the output of CommandLineToArgvW() is wchar_t. + +#include +#include +#include +#include +#include + +// Create a wchar_t array containing Unicode parameters. +#define INIT_WARGV(ARGC, ARGV) \ + int wargc; \ + const W_CHAR** const wargv = \ + (const W_CHAR**)CommandLineToArgvW(GetCommandLineW(), &wargc); \ + do { \ + if (wargv == NULL || wargc != (ARGC)) { \ + fprintf(stderr, "Error: Unable to get Unicode arguments.\n"); \ + FREE_WARGV_AND_RETURN(-1); \ + } \ + } while (0) + +// Use this to get a Unicode argument (e.g. file path). +#define GET_WARGV(UNUSED, C) wargv[C] +// For cases where argv is shifted by one compared to wargv. +#define GET_WARGV_SHIFTED(UNUSED, C) wargv[(C) + 1] +#define GET_WARGV_OR_NULL() wargv + +// Release resources. LocalFree() is needed after CommandLineToArgvW(). +#define FREE_WARGV() LOCAL_FREE((W_CHAR** const)wargv) +#define LOCAL_FREE(WARGV) \ + do { \ + if ((WARGV) != NULL) LocalFree(WARGV); \ + } while (0) + +#define W_CHAR wchar_t // WCHAR without underscore might already be defined. +#define TO_W_CHAR(STR) (L##STR) + +#define WFOPEN(ARG, OPT) _wfopen((const W_CHAR*)ARG, TO_W_CHAR(OPT)) + +#define WFPRINTF(STREAM, STR, ...) \ + do { \ + int prev_mode; \ + fflush(STREAM); \ + prev_mode = _setmode(_fileno(STREAM), _O_U8TEXT); \ + fwprintf(STREAM, TO_W_CHAR(STR), __VA_ARGS__); \ + fflush(STREAM); \ + (void)_setmode(_fileno(STREAM), prev_mode); \ + } while (0) +#define WPRINTF(STR, ...) WFPRINTF(stdout, STR, __VA_ARGS__) + +#define WSTRLEN(FILENAME) wcslen((const W_CHAR*)FILENAME) +#define WSTRCMP(FILENAME, STR) wcscmp((const W_CHAR*)FILENAME, TO_W_CHAR(STR)) +#define WSTRRCHR(FILENAME, STR) wcsrchr((const W_CHAR*)FILENAME, TO_W_CHAR(STR)) +#define WSNPRINTF(A, B, STR, ...) _snwprintf(A, B, TO_W_CHAR(STR), __VA_ARGS__) + +#else + +#include + +// Unicode file paths work as is on Unix platforms, and no extra work is done on +// Windows either if Unicode is disabled. + +#define INIT_WARGV(ARGC, ARGV) + +#define GET_WARGV(ARGV, C) (ARGV)[C] +#define GET_WARGV_SHIFTED(ARGV, C) (ARGV)[C] +#define GET_WARGV_OR_NULL() NULL + +#define FREE_WARGV() +#define LOCAL_FREE(WARGV) + +#define W_CHAR char +#define TO_W_CHAR(STR) (STR) + +#define WFOPEN(ARG, OPT) fopen(ARG, OPT) + +#define WPRINTF(STR, ...) printf(STR, __VA_ARGS__) +#define WFPRINTF(STREAM, STR, ...) fprintf(STREAM, STR, __VA_ARGS__) + +#define WSTRLEN(FILENAME) strlen(FILENAME) +#define WSTRCMP(FILENAME, STR) strcmp(FILENAME, STR) +#define WSTRRCHR(FILENAME, STR) strrchr(FILENAME, STR) +#define WSNPRINTF(A, B, STR, ...) snprintf(A, B, STR, __VA_ARGS__) + +#endif // defined(_WIN32) && defined(_UNICODE) + +// Don't forget to free wargv before returning (e.g. from main). +#define FREE_WARGV_AND_RETURN(VALUE) \ + do { \ + FREE_WARGV(); \ + return (VALUE); \ + } while (0) + +#endif // WEBP_EXAMPLES_UNICODE_H_ diff --git a/third-party/webp/libwebp/examples/unicode_gif.h b/third-party/webp/libwebp/examples/unicode_gif.h new file mode 100644 index 0000000000..626c6e7265 --- /dev/null +++ b/third-party/webp/libwebp/examples/unicode_gif.h @@ -0,0 +1,76 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// giflib doesn't have a Unicode DGifOpenFileName(). Let's make one. +// +// Author: Yannis Guyon (yguyon@google.com) + +#ifndef WEBP_EXAMPLES_UNICODE_GIF_H_ +#define WEBP_EXAMPLES_UNICODE_GIF_H_ + +#include "./unicode.h" +#ifdef HAVE_CONFIG_H +#include "webp/config.h" // For WEBP_HAVE_GIF +#endif + +#if defined(WEBP_HAVE_GIF) + +#ifdef _WIN32 +#include // Not standard, needed for _topen and flags. +#include +#endif + +#include +#include +#include "./gifdec.h" + +#if !defined(STDIN_FILENO) +#define STDIN_FILENO 0 +#endif + +static GifFileType* DGifOpenFileUnicode(const W_CHAR* file_name, int* error) { + if (!WSTRCMP(file_name, "-")) { +#if LOCAL_GIF_PREREQ(5, 0) + return DGifOpenFileHandle(STDIN_FILENO, error); +#else + (void)error; + return DGifOpenFileHandle(STDIN_FILENO); +#endif + } + +#if defined(_WIN32) && defined(_UNICODE) + { + int file_handle = _wopen(file_name, _O_RDONLY | _O_BINARY); + if (file_handle == -1) { + if (error != NULL) *error = D_GIF_ERR_OPEN_FAILED; + return NULL; + } + +#if LOCAL_GIF_PREREQ(5, 0) + return DGifOpenFileHandle(file_handle, error); +#else + return DGifOpenFileHandle(file_handle); +#endif + } + +#else + +#if LOCAL_GIF_PREREQ(5, 0) + return DGifOpenFileName(file_name, error); +#else + return DGifOpenFileName(file_name); +#endif + +#endif // defined(_WIN32) && defined(_UNICODE) + // DGifCloseFile() is called later. +} + +#endif // defined(WEBP_HAVE_GIF) + +#endif // WEBP_EXAMPLES_UNICODE_GIF_H_ diff --git a/third-party/webp/libwebp/examples/vwebp.c b/third-party/webp/libwebp/examples/vwebp.c new file mode 100644 index 0000000000..35f1b18847 --- /dev/null +++ b/third-party/webp/libwebp/examples/vwebp.c @@ -0,0 +1,654 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Simple OpenGL-based WebP file viewer. +// +// Author: Skal (pascal.massimino@gmail.com) +#ifdef HAVE_CONFIG_H +#include "webp/config.h" +#endif + +#if defined(__unix__) || defined(__CYGWIN__) +#define _POSIX_C_SOURCE 200112L // for setenv +#endif + +#include +#include +#include + +#if defined(WEBP_HAVE_GL) + +#if defined(HAVE_GLUT_GLUT_H) +#include +#else +#include +#ifdef FREEGLUT +#include +#endif +#endif + +#ifdef WEBP_HAVE_QCMS +#include +#endif + +#include "webp/decode.h" +#include "webp/demux.h" + +#include "../examples/example_util.h" +#include "../imageio/imageio_util.h" +#include "./unicode.h" + +#if defined(_MSC_VER) && _MSC_VER < 1900 +#define snprintf _snprintf +#endif + +// Unfortunate global variables. Gathered into a struct for comfort. +static struct { + int has_animation; + int has_color_profile; + int done; + int decoding_error; + int print_info; + int only_deltas; + int use_color_profile; + int draw_anim_background_color; + + int canvas_width, canvas_height; + int loop_count; + uint32_t bg_color; + + const char* file_name; + WebPData data; + WebPDecoderConfig config; + const WebPDecBuffer* pic; + WebPDemuxer* dmux; + WebPIterator curr_frame; + WebPIterator prev_frame; + WebPChunkIterator iccp; + int viewport_width, viewport_height; +} kParams; + +static void ClearPreviousPic(void) { + WebPFreeDecBuffer((WebPDecBuffer*)kParams.pic); + kParams.pic = NULL; +} + +static void ClearParams(void) { + ClearPreviousPic(); + WebPDataClear(&kParams.data); + WebPDemuxReleaseIterator(&kParams.curr_frame); + WebPDemuxReleaseIterator(&kParams.prev_frame); + WebPDemuxReleaseChunkIterator(&kParams.iccp); + WebPDemuxDelete(kParams.dmux); + kParams.dmux = NULL; +} + +// Sets the previous frame to the dimensions of the canvas and has it dispose +// to background to cause the canvas to be cleared. +static void ClearPreviousFrame(void) { + WebPIterator* const prev = &kParams.prev_frame; + prev->width = kParams.canvas_width; + prev->height = kParams.canvas_height; + prev->x_offset = prev->y_offset = 0; + prev->dispose_method = WEBP_MUX_DISPOSE_BACKGROUND; +} + +// ----------------------------------------------------------------------------- +// Color profile handling +static int ApplyColorProfile(const WebPData* const profile, + WebPDecBuffer* const rgba) { +#ifdef WEBP_HAVE_QCMS + int i, ok = 0; + uint8_t* line; + uint8_t major_revision; + qcms_profile* input_profile = NULL; + qcms_profile* output_profile = NULL; + qcms_transform* transform = NULL; + const qcms_data_type input_type = QCMS_DATA_RGBA_8; + const qcms_data_type output_type = QCMS_DATA_RGBA_8; + const qcms_intent intent = QCMS_INTENT_DEFAULT; + + if (profile == NULL || rgba == NULL) return 0; + if (profile->bytes == NULL || profile->size < 10) return 1; + major_revision = profile->bytes[8]; + + qcms_enable_iccv4(); + input_profile = qcms_profile_from_memory(profile->bytes, profile->size); + // qcms_profile_is_bogus() is broken with ICCv4. + if (input_profile == NULL || + (major_revision < 4 && qcms_profile_is_bogus(input_profile))) { + fprintf(stderr, "Color profile is bogus!\n"); + goto Error; + } + + output_profile = qcms_profile_sRGB(); + if (output_profile == NULL) { + fprintf(stderr, "Error creating output color profile!\n"); + goto Error; + } + + qcms_profile_precache_output_transform(output_profile); + transform = qcms_transform_create(input_profile, input_type, + output_profile, output_type, + intent); + if (transform == NULL) { + fprintf(stderr, "Error creating color transform!\n"); + goto Error; + } + + line = rgba->u.RGBA.rgba; + for (i = 0; i < rgba->height; ++i, line += rgba->u.RGBA.stride) { + qcms_transform_data(transform, line, line, rgba->width); + } + ok = 1; + + Error: + if (input_profile != NULL) qcms_profile_release(input_profile); + if (output_profile != NULL) qcms_profile_release(output_profile); + if (transform != NULL) qcms_transform_release(transform); + return ok; +#else + (void)profile; + (void)rgba; + return 1; +#endif // WEBP_HAVE_QCMS +} + +//------------------------------------------------------------------------------ +// File decoding + +static int Decode(void) { // Fills kParams.curr_frame + const WebPIterator* const curr = &kParams.curr_frame; + WebPDecoderConfig* const config = &kParams.config; + WebPDecBuffer* const output_buffer = &config->output; + int ok = 0; + + ClearPreviousPic(); + output_buffer->colorspace = MODE_RGBA; + ok = (WebPDecode(curr->fragment.bytes, curr->fragment.size, + config) == VP8_STATUS_OK); + if (!ok) { + fprintf(stderr, "Decoding of frame #%d failed!\n", curr->frame_num); + } else { + kParams.pic = output_buffer; + if (kParams.use_color_profile) { + ok = ApplyColorProfile(&kParams.iccp.chunk, output_buffer); + if (!ok) { + fprintf(stderr, "Applying color profile to frame #%d failed!\n", + curr->frame_num); + } + } + } + return ok; +} + +static void decode_callback(int what) { + if (what == 0 && !kParams.done) { + int duration = 0; + if (kParams.dmux != NULL) { + WebPIterator* const curr = &kParams.curr_frame; + if (!WebPDemuxNextFrame(curr)) { + WebPDemuxReleaseIterator(curr); + if (WebPDemuxGetFrame(kParams.dmux, 1, curr)) { + --kParams.loop_count; + kParams.done = (kParams.loop_count == 0); + if (kParams.done) return; + ClearPreviousFrame(); + } else { + kParams.decoding_error = 1; + kParams.done = 1; + return; + } + } + duration = curr->duration; + // Behavior copied from Chrome, cf: + // https://cs.chromium.org/chromium/src/third_party/WebKit/Source/ + // platform/graphics/DeferredImageDecoder.cpp? + // rcl=b4c33049f096cd283f32be9a58b9a9e768227c26&l=246 + if (duration <= 10) duration = 100; + } + if (!Decode()) { + kParams.decoding_error = 1; + kParams.done = 1; + } else { + glutPostRedisplay(); + glutTimerFunc(duration, decode_callback, what); + } + } +} + +//------------------------------------------------------------------------------ +// Callbacks + +static void HandleKey(unsigned char key, int pos_x, int pos_y) { + // Note: rescaling the window or toggling some features during an animation + // generates visual artifacts. This is not fixed because refreshing the frame + // may require rendering the whole animation from start till current frame. + (void)pos_x; + (void)pos_y; + if (key == 'q' || key == 'Q' || key == 27 /* Esc */) { +#ifdef FREEGLUT + glutLeaveMainLoop(); +#else + ClearParams(); + exit(0); +#endif + } else if (key == 'c') { + if (kParams.has_color_profile && !kParams.decoding_error) { + kParams.use_color_profile = 1 - kParams.use_color_profile; + + if (kParams.has_animation) { + // Restart the completed animation to pickup the color profile change. + if (kParams.done && kParams.loop_count == 0) { + kParams.loop_count = + (int)WebPDemuxGetI(kParams.dmux, WEBP_FF_LOOP_COUNT) + 1; + kParams.done = 0; + // Start the decode loop immediately. + glutTimerFunc(0, decode_callback, 0); + } + } else { + Decode(); + glutPostRedisplay(); + } + } + } else if (key == 'b') { + kParams.draw_anim_background_color = 1 - kParams.draw_anim_background_color; + if (!kParams.has_animation) ClearPreviousFrame(); + glutPostRedisplay(); + } else if (key == 'i') { + kParams.print_info = 1 - kParams.print_info; + if (!kParams.has_animation) ClearPreviousFrame(); + glutPostRedisplay(); + } else if (key == 'd') { + kParams.only_deltas = 1 - kParams.only_deltas; + glutPostRedisplay(); + } +} + +static void HandleReshape(int width, int height) { + // Note: reshape doesn't preserve aspect ratio, and might + // be handling larger-than-screen pictures incorrectly. + glViewport(0, 0, width, height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + kParams.viewport_width = width; + kParams.viewport_height = height; + if (!kParams.has_animation) ClearPreviousFrame(); +} + +static void PrintString(const char* const text) { + void* const font = GLUT_BITMAP_9_BY_15; + int i; + for (i = 0; text[i]; ++i) { + glutBitmapCharacter(font, text[i]); + } +} + +static void PrintStringW(const char* const text) { +#if defined(_WIN32) && defined(_UNICODE) + void* const font = GLUT_BITMAP_9_BY_15; + const W_CHAR* const wtext = (const W_CHAR*)text; + int i; + for (i = 0; wtext[i]; ++i) { + glutBitmapCharacter(font, wtext[i]); + } +#else + PrintString(text); +#endif +} + +static float GetColorf(uint32_t color, int shift) { + return ((color >> shift) & 0xff) / 255.f; +} + +static void DrawCheckerBoard(void) { + const int square_size = 8; // must be a power of 2 + int x, y; + GLint viewport[4]; // x, y, width, height + + glPushMatrix(); + + glGetIntegerv(GL_VIEWPORT, viewport); + // shift to integer coordinates with (0,0) being top-left. + glOrtho(0, viewport[2], viewport[3], 0, -1, 1); + for (y = 0; y < viewport[3]; y += square_size) { + for (x = 0; x < viewport[2]; x += square_size) { + const GLubyte color = 128 + 64 * (!((x + y) & square_size)); + glColor3ub(color, color, color); + glRecti(x, y, x + square_size, y + square_size); + } + } + glPopMatrix(); +} + +static void DrawBackground(void) { + // Whole window cleared with clear color, checkerboard rendered on top of it. + glClear(GL_COLOR_BUFFER_BIT); + DrawCheckerBoard(); + + // ANIM background color rendered (blend) on top. Default is white for still + // images (without ANIM chunk). glClear() can't be used for that (no blend). + if (kParams.draw_anim_background_color) { + glPushMatrix(); + glLoadIdentity(); + glColor4f(GetColorf(kParams.bg_color, 16), // BGRA from spec + GetColorf(kParams.bg_color, 8), + GetColorf(kParams.bg_color, 0), + GetColorf(kParams.bg_color, 24)); + glRecti(-1, -1, +1, +1); + glPopMatrix(); + } +} + +// Draw background in a scissored rectangle. +static void DrawBackgroundScissored(int window_x, int window_y, int frame_w, + int frame_h) { + // Only update the requested area, not the whole canvas. + window_x = window_x * kParams.viewport_width / kParams.canvas_width; + window_y = window_y * kParams.viewport_height / kParams.canvas_height; + frame_w = frame_w * kParams.viewport_width / kParams.canvas_width; + frame_h = frame_h * kParams.viewport_height / kParams.canvas_height; + + // glScissor() takes window coordinates (0,0 at bottom left). + window_y = kParams.viewport_height - window_y - frame_h; + + glEnable(GL_SCISSOR_TEST); + glScissor(window_x, window_y, frame_w, frame_h); + DrawBackground(); + glDisable(GL_SCISSOR_TEST); +} + +static void HandleDisplay(void) { + const WebPDecBuffer* const pic = kParams.pic; + const WebPIterator* const curr = &kParams.curr_frame; + WebPIterator* const prev = &kParams.prev_frame; + GLfloat xoff, yoff; + if (pic == NULL) return; + glPushMatrix(); + glPixelZoom((GLfloat)(+1. / kParams.canvas_width * kParams.viewport_width), + (GLfloat)(-1. / kParams.canvas_height * kParams.viewport_height)); + xoff = (GLfloat)(2. * curr->x_offset / kParams.canvas_width); + yoff = (GLfloat)(2. * curr->y_offset / kParams.canvas_height); + glRasterPos2f(-1.f + xoff, 1.f - yoff); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_UNPACK_ROW_LENGTH, pic->u.RGBA.stride / 4); + + if (kParams.only_deltas) { + DrawBackground(); + } else { + // The rectangle of the previous frame might be different than the current + // frame, so we may need to DrawBackgroundScissored for both. + if (prev->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) { + // Clear the previous frame rectangle. + DrawBackgroundScissored(prev->x_offset, prev->y_offset, prev->width, + prev->height); + } + if (curr->blend_method == WEBP_MUX_NO_BLEND) { + // We simulate no-blending behavior by first clearing the current frame + // rectangle and then alpha-blending against it. + DrawBackgroundScissored(curr->x_offset, curr->y_offset, curr->width, + curr->height); + } + } + + *prev = *curr; + + glDrawPixels(pic->width, pic->height, + GL_RGBA, GL_UNSIGNED_BYTE, + (GLvoid*)pic->u.RGBA.rgba); + if (kParams.print_info) { + char tmp[32]; + + glColor4f(0.90f, 0.0f, 0.90f, 1.0f); + glRasterPos2f(-0.95f, 0.90f); + PrintStringW(kParams.file_name); + + snprintf(tmp, sizeof(tmp), "Dimension:%d x %d", pic->width, pic->height); + glColor4f(0.90f, 0.0f, 0.90f, 1.0f); + glRasterPos2f(-0.95f, 0.80f); + PrintString(tmp); + if (curr->x_offset != 0 || curr->y_offset != 0) { + snprintf(tmp, sizeof(tmp), " (offset:%d,%d)", + curr->x_offset, curr->y_offset); + glRasterPos2f(-0.95f, 0.70f); + PrintString(tmp); + } + } + glPopMatrix(); +#if defined(__APPLE__) || defined(_WIN32) + glFlush(); +#else + glutSwapBuffers(); +#endif +} + +static void StartDisplay(void) { + int width = kParams.canvas_width; + int height = kParams.canvas_height; + int screen_width, screen_height; + // TODO(webp:365) GLUT_DOUBLE results in flickering / old frames to be + // partially displayed with animated webp + alpha. +#if defined(__APPLE__) || defined(_WIN32) + glutInitDisplayMode(GLUT_RGBA); +#else + glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA); +#endif + screen_width = glutGet(GLUT_SCREEN_WIDTH); + screen_height = glutGet(GLUT_SCREEN_HEIGHT); + if (width > screen_width || height > screen_height) { + if (width > screen_width) { + height = (height * screen_width + width - 1) / width; + width = screen_width; + } + if (height > screen_height) { + width = (width * screen_height + height - 1) / height; + height = screen_height; + } + } + glutInitWindowSize(width, height); + glutCreateWindow("WebP viewer"); + glutDisplayFunc(HandleDisplay); + glutReshapeFunc(HandleReshape); + glutIdleFunc(NULL); + glutKeyboardFunc(HandleKey); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + glClearColor(0, 0, 0, 0); // window will be cleared to black (no blend) + DrawBackground(); +} + +//------------------------------------------------------------------------------ +// Main + +static void Help(void) { + printf( + "Usage: vwebp in_file [options]\n\n" + "Decodes the WebP image file and visualize it using OpenGL\n" + "Options are:\n" + " -version ..... print version number and exit\n" + " -noicc ....... don't use the icc profile if present\n" + " -nofancy ..... don't use the fancy YUV420 upscaler\n" + " -nofilter .... disable in-loop filtering\n" + " -dither dithering strength (0..100), default=50\n" + " -noalphadither disable alpha plane dithering\n" + " -usebgcolor .. display background color\n" + " -mt .......... use multi-threading\n" + " -info ........ print info\n" + " -h ........... this help message\n" + "\n" + "Keyboard shortcuts:\n" + " 'c' ................ toggle use of color profile\n" + " 'b' ................ toggle background color display\n" + " 'i' ................ overlay file information\n" + " 'd' ................ disable blending & disposal (debug)\n" + " 'q' / 'Q' / ESC .... quit\n"); +} + +int main(int argc, char* argv[]) { + int c; + WebPDecoderConfig* const config = &kParams.config; + WebPIterator* const curr = &kParams.curr_frame; + + INIT_WARGV(argc, argv); + + if (!WebPInitDecoderConfig(config)) { + fprintf(stderr, "Library version mismatch!\n"); + FREE_WARGV_AND_RETURN(-1); + } + config->options.dithering_strength = 50; + config->options.alpha_dithering_strength = 100; + kParams.use_color_profile = 1; + // Background color hidden by default to see transparent areas. + kParams.draw_anim_background_color = 0; + + for (c = 1; c < argc; ++c) { + int parse_error = 0; + if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) { + Help(); + FREE_WARGV_AND_RETURN(0); + } else if (!strcmp(argv[c], "-noicc")) { + kParams.use_color_profile = 0; + } else if (!strcmp(argv[c], "-nofancy")) { + config->options.no_fancy_upsampling = 1; + } else if (!strcmp(argv[c], "-nofilter")) { + config->options.bypass_filtering = 1; + } else if (!strcmp(argv[c], "-noalphadither")) { + config->options.alpha_dithering_strength = 0; + } else if (!strcmp(argv[c], "-usebgcolor")) { + kParams.draw_anim_background_color = 1; + } else if (!strcmp(argv[c], "-dither") && c + 1 < argc) { + config->options.dithering_strength = + ExUtilGetInt(argv[++c], 0, &parse_error); + } else if (!strcmp(argv[c], "-info")) { + kParams.print_info = 1; + } else if (!strcmp(argv[c], "-version")) { + const int dec_version = WebPGetDecoderVersion(); + const int dmux_version = WebPGetDemuxVersion(); + printf("WebP Decoder version: %d.%d.%d\nWebP Demux version: %d.%d.%d\n", + (dec_version >> 16) & 0xff, (dec_version >> 8) & 0xff, + dec_version & 0xff, (dmux_version >> 16) & 0xff, + (dmux_version >> 8) & 0xff, dmux_version & 0xff); + FREE_WARGV_AND_RETURN(0); + } else if (!strcmp(argv[c], "-mt")) { + config->options.use_threads = 1; + } else if (!strcmp(argv[c], "--")) { + if (c < argc - 1) kParams.file_name = (const char*)GET_WARGV(argv, ++c); + break; + } else if (argv[c][0] == '-') { + printf("Unknown option '%s'\n", argv[c]); + Help(); + FREE_WARGV_AND_RETURN(-1); + } else { + kParams.file_name = (const char*)GET_WARGV(argv, c); + } + + if (parse_error) { + Help(); + FREE_WARGV_AND_RETURN(-1); + } + } + + if (kParams.file_name == NULL) { + printf("missing input file!!\n"); + Help(); + FREE_WARGV_AND_RETURN(0); + } + + if (!ImgIoUtilReadFile(kParams.file_name, + &kParams.data.bytes, &kParams.data.size)) { + goto Error; + } + + if (!WebPGetInfo(kParams.data.bytes, kParams.data.size, NULL, NULL)) { + fprintf(stderr, "Input file doesn't appear to be WebP format.\n"); + goto Error; + } + + kParams.dmux = WebPDemux(&kParams.data); + if (kParams.dmux == NULL) { + fprintf(stderr, "Could not create demuxing object!\n"); + goto Error; + } + + kParams.canvas_width = WebPDemuxGetI(kParams.dmux, WEBP_FF_CANVAS_WIDTH); + kParams.canvas_height = WebPDemuxGetI(kParams.dmux, WEBP_FF_CANVAS_HEIGHT); + if (kParams.print_info) { + printf("Canvas: %d x %d\n", kParams.canvas_width, kParams.canvas_height); + } + + ClearPreviousFrame(); + + memset(&kParams.iccp, 0, sizeof(kParams.iccp)); + kParams.has_color_profile = + !!(WebPDemuxGetI(kParams.dmux, WEBP_FF_FORMAT_FLAGS) & ICCP_FLAG); + if (kParams.has_color_profile) { +#ifdef WEBP_HAVE_QCMS + if (!WebPDemuxGetChunk(kParams.dmux, "ICCP", 1, &kParams.iccp)) goto Error; + printf("VP8X: Found color profile\n"); +#else + fprintf(stderr, "Warning: color profile present, but qcms is unavailable!\n" + "Build libqcms from Mozilla or Chromium and define WEBP_HAVE_QCMS " + "before building.\n"); +#endif + } + + if (!WebPDemuxGetFrame(kParams.dmux, 1, curr)) goto Error; + + kParams.has_animation = (curr->num_frames > 1); + kParams.loop_count = (int)WebPDemuxGetI(kParams.dmux, WEBP_FF_LOOP_COUNT); + kParams.bg_color = WebPDemuxGetI(kParams.dmux, WEBP_FF_BACKGROUND_COLOR); + printf("VP8X: Found %d images in file (loop count = %d)\n", + curr->num_frames, kParams.loop_count); + + // Decode first frame + if (!Decode()) goto Error; + + // Position iterator to last frame. Next call to HandleDisplay will wrap over. + // We take this into account by bumping up loop_count. + WebPDemuxGetFrame(kParams.dmux, 0, curr); + if (kParams.loop_count) ++kParams.loop_count; + +#if defined(__unix__) || defined(__CYGWIN__) + // Work around GLUT compositor bug. + // https://bugs.launchpad.net/ubuntu/+source/freeglut/+bug/369891 + setenv("XLIB_SKIP_ARGB_VISUALS", "1", 1); +#endif + + // Start display (and timer) + glutInit(&argc, argv); +#ifdef FREEGLUT + glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION); +#endif + StartDisplay(); + + if (kParams.has_animation) glutTimerFunc(0, decode_callback, 0); + glutMainLoop(); + + // Should only be reached when using FREEGLUT: + ClearParams(); + FREE_WARGV_AND_RETURN(0); + + Error: + ClearParams(); + FREE_WARGV_AND_RETURN(-1); +} + +#else // !WEBP_HAVE_GL + +int main(int argc, const char* argv[]) { + fprintf(stderr, "OpenGL support not enabled in %s.\n", argv[0]); + (void)argc; + return 0; +} + +#endif + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/examples/webpinfo.c b/third-party/webp/libwebp/examples/webpinfo.c new file mode 100644 index 0000000000..1d2278ee17 --- /dev/null +++ b/third-party/webp/libwebp/examples/webpinfo.c @@ -0,0 +1,1186 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Command-line tool to print out the chunk level structure of WebP files +// along with basic integrity checks. +// +// Author: Hui Su (huisu@google.com) + +#include +#include + +#ifdef HAVE_CONFIG_H +#include "webp/config.h" +#endif + +#include "../imageio/imageio_util.h" +#include "./unicode.h" +#include "webp/decode.h" +#include "webp/format_constants.h" +#include "webp/mux_types.h" + +#if defined(_MSC_VER) && _MSC_VER < 1900 +#define snprintf _snprintf +#endif + +#define LOG_ERROR(MESSAGE) \ + do { \ + if (webp_info->show_diagnosis_) { \ + fprintf(stderr, "Error: %s\n", MESSAGE); \ + } \ + } while (0) + +#define LOG_WARN(MESSAGE) \ + do { \ + if (webp_info->show_diagnosis_) { \ + fprintf(stderr, "Warning: %s\n", MESSAGE); \ + } \ + ++webp_info->num_warnings_; \ + } while (0) + +static const char* const kFormats[3] = { + "Unknown", + "Lossy", + "Lossless" +}; + +static const char* const kLosslessTransforms[4] = { + "Predictor", + "Cross Color", + "Subtract Green", + "Color Indexing" +}; + +static const char* const kAlphaFilterMethods[4] = { + "None", + "Horizontal", + "Vertical", + "Gradient" +}; + +typedef enum { + WEBP_INFO_OK = 0, + WEBP_INFO_TRUNCATED_DATA, + WEBP_INFO_PARSE_ERROR, + WEBP_INFO_INVALID_PARAM, + WEBP_INFO_BITSTREAM_ERROR, + WEBP_INFO_MISSING_DATA, + WEBP_INFO_INVALID_COMMAND +} WebPInfoStatus; + +typedef enum ChunkID { + CHUNK_VP8, + CHUNK_VP8L, + CHUNK_VP8X, + CHUNK_ALPHA, + CHUNK_ANIM, + CHUNK_ANMF, + CHUNK_ICCP, + CHUNK_EXIF, + CHUNK_XMP, + CHUNK_UNKNOWN, + CHUNK_TYPES = CHUNK_UNKNOWN +} ChunkID; + +typedef struct { + size_t start_; + size_t end_; + const uint8_t* buf_; +} MemBuffer; + +typedef struct { + size_t offset_; + size_t size_; + const uint8_t* payload_; + ChunkID id_; +} ChunkData; + +typedef struct WebPInfo { + int canvas_width_; + int canvas_height_; + int loop_count_; + int num_frames_; + int chunk_counts_[CHUNK_TYPES]; + int anmf_subchunk_counts_[3]; // 0 VP8; 1 VP8L; 2 ALPH. + uint32_t bgcolor_; + int feature_flags_; + int has_alpha_; + // Used for parsing ANMF chunks. + int frame_width_, frame_height_; + size_t anim_frame_data_size_; + int is_processing_anim_frame_, seen_alpha_subchunk_, seen_image_subchunk_; + // Print output control. + int quiet_, show_diagnosis_, show_summary_; + int num_warnings_; + int parse_bitstream_; +} WebPInfo; + +static void WebPInfoInit(WebPInfo* const webp_info) { + memset(webp_info, 0, sizeof(*webp_info)); +} + +static const uint32_t kWebPChunkTags[CHUNK_TYPES] = { + MKFOURCC('V', 'P', '8', ' '), + MKFOURCC('V', 'P', '8', 'L'), + MKFOURCC('V', 'P', '8', 'X'), + MKFOURCC('A', 'L', 'P', 'H'), + MKFOURCC('A', 'N', 'I', 'M'), + MKFOURCC('A', 'N', 'M', 'F'), + MKFOURCC('I', 'C', 'C', 'P'), + MKFOURCC('E', 'X', 'I', 'F'), + MKFOURCC('X', 'M', 'P', ' '), +}; + +// ----------------------------------------------------------------------------- +// Data reading. + +static int GetLE16(const uint8_t* const data) { + return (data[0] << 0) | (data[1] << 8); +} + +static int GetLE24(const uint8_t* const data) { + return GetLE16(data) | (data[2] << 16); +} + +static uint32_t GetLE32(const uint8_t* const data) { + return GetLE16(data) | ((uint32_t)GetLE16(data + 2) << 16); +} + +static int ReadLE16(const uint8_t** data) { + const int val = GetLE16(*data); + *data += 2; + return val; +} + +static int ReadLE24(const uint8_t** data) { + const int val = GetLE24(*data); + *data += 3; + return val; +} + +static uint32_t ReadLE32(const uint8_t** data) { + const uint32_t val = GetLE32(*data); + *data += 4; + return val; +} + +static int ReadFileToWebPData(const char* const filename, + WebPData* const webp_data) { + const uint8_t* data; + size_t size; + if (!ImgIoUtilReadFile(filename, &data, &size)) return 0; + webp_data->bytes = data; + webp_data->size = size; + return 1; +} + +// ----------------------------------------------------------------------------- +// MemBuffer object. + +static void InitMemBuffer(MemBuffer* const mem, const WebPData* webp_data) { + mem->buf_ = webp_data->bytes; + mem->start_ = 0; + mem->end_ = webp_data->size; +} + +static size_t MemDataSize(const MemBuffer* const mem) { + return (mem->end_ - mem->start_); +} + +static const uint8_t* GetBuffer(MemBuffer* const mem) { + return mem->buf_ + mem->start_; +} + +static void Skip(MemBuffer* const mem, size_t size) { + mem->start_ += size; +} + +static uint32_t ReadMemBufLE32(MemBuffer* const mem) { + const uint8_t* const data = mem->buf_ + mem->start_; + const uint32_t val = GetLE32(data); + assert(MemDataSize(mem) >= 4); + Skip(mem, 4); + return val; +} + +// ----------------------------------------------------------------------------- +// Lossy bitstream analysis. + +static int GetBits(const uint8_t* const data, size_t data_size, size_t nb, + int* val, uint64_t* const bit_pos) { + *val = 0; + while (nb-- > 0) { + const uint64_t p = (*bit_pos)++; + if ((p >> 3) >= data_size) { + return 0; + } else { + const int bit = !!(data[p >> 3] & (128 >> ((p & 7)))); + *val = (*val << 1) | bit; + } + } + return 1; +} + +static int GetSignedBits(const uint8_t* const data, size_t data_size, size_t nb, + int* val, uint64_t* const bit_pos) { + int sign; + if (!GetBits(data, data_size, nb, val, bit_pos)) return 0; + if (!GetBits(data, data_size, 1, &sign, bit_pos)) return 0; + if (sign) *val = -(*val); + return 1; +} + +#define GET_BITS(v, n) \ + do { \ + if (!GetBits(data, data_size, n, &(v), bit_pos)) { \ + LOG_ERROR("Truncated lossy bitstream."); \ + return WEBP_INFO_TRUNCATED_DATA; \ + } \ + } while (0) + +#define GET_SIGNED_BITS(v, n) \ + do { \ + if (!GetSignedBits(data, data_size, n, &(v), bit_pos)) { \ + LOG_ERROR("Truncated lossy bitstream."); \ + return WEBP_INFO_TRUNCATED_DATA; \ + } \ + } while (0) + +static WebPInfoStatus ParseLossySegmentHeader(const WebPInfo* const webp_info, + const uint8_t* const data, + size_t data_size, + uint64_t* const bit_pos) { + int use_segment; + GET_BITS(use_segment, 1); + printf(" Use segment: %d\n", use_segment); + if (use_segment) { + int update_map, update_data; + GET_BITS(update_map, 1); + GET_BITS(update_data, 1); + printf(" Update map: %d\n" + " Update data: %d\n", + update_map, update_data); + if (update_data) { + int i, a_delta; + int quantizer[4] = {0, 0, 0, 0}; + int filter_strength[4] = {0, 0, 0, 0}; + GET_BITS(a_delta, 1); + printf(" Absolute delta: %d\n", a_delta); + for (i = 0; i < 4; ++i) { + int bit; + GET_BITS(bit, 1); + if (bit) GET_SIGNED_BITS(quantizer[i], 7); + } + for (i = 0; i < 4; ++i) { + int bit; + GET_BITS(bit, 1); + if (bit) GET_SIGNED_BITS(filter_strength[i], 6); + } + printf(" Quantizer: %d %d %d %d\n", quantizer[0], quantizer[1], + quantizer[2], quantizer[3]); + printf(" Filter strength: %d %d %d %d\n", filter_strength[0], + filter_strength[1], filter_strength[2], filter_strength[3]); + } + if (update_map) { + int i; + int prob_segment[3] = {255, 255, 255}; + for (i = 0; i < 3; ++i) { + int bit; + GET_BITS(bit, 1); + if (bit) GET_BITS(prob_segment[i], 8); + } + printf(" Prob segment: %d %d %d\n", + prob_segment[0], prob_segment[1], prob_segment[2]); + } + } + return WEBP_INFO_OK; +} + +static WebPInfoStatus ParseLossyFilterHeader(const WebPInfo* const webp_info, + const uint8_t* const data, + size_t data_size, + uint64_t* const bit_pos) { + int simple_filter, level, sharpness, use_lf_delta; + GET_BITS(simple_filter, 1); + GET_BITS(level, 6); + GET_BITS(sharpness, 3); + GET_BITS(use_lf_delta, 1); + printf(" Simple filter: %d\n", simple_filter); + printf(" Level: %d\n", level); + printf(" Sharpness: %d\n", sharpness); + printf(" Use lf delta: %d\n", use_lf_delta); + if (use_lf_delta) { + int update; + GET_BITS(update, 1); + printf(" Update lf delta: %d\n", update); + if (update) { + int i; + for (i = 0; i < 4 + 4; ++i) { + int temp; + GET_BITS(temp, 1); + if (temp) GET_BITS(temp, 7); + } + } + } + return WEBP_INFO_OK; +} + +static WebPInfoStatus ParseLossyHeader(const ChunkData* const chunk_data, + const WebPInfo* const webp_info) { + const uint8_t* data = chunk_data->payload_; + size_t data_size = chunk_data->size_ - CHUNK_HEADER_SIZE; + const uint32_t bits = (uint32_t)data[0] | (data[1] << 8) | (data[2] << 16); + const int key_frame = !(bits & 1); + const int profile = (bits >> 1) & 7; + const int display = (bits >> 4) & 1; + const uint32_t partition0_length = (bits >> 5); + WebPInfoStatus status = WEBP_INFO_OK; + uint64_t bit_position = 0; + uint64_t* const bit_pos = &bit_position; + int colorspace, clamp_type; + printf(" Parsing lossy bitstream...\n"); + // Calling WebPGetFeatures() in ProcessImageChunk() should ensure this. + assert(chunk_data->size_ >= CHUNK_HEADER_SIZE + 10); + if (profile > 3) { + LOG_ERROR("Unknown profile."); + return WEBP_INFO_BITSTREAM_ERROR; + } + if (!display) { + LOG_ERROR("Frame is not displayable."); + return WEBP_INFO_BITSTREAM_ERROR; + } + data += 3; + data_size -= 3; + printf( + " Key frame: %s\n" + " Profile: %d\n" + " Display: Yes\n" + " Part. 0 length: %d\n", + key_frame ? "Yes" : "No", profile, partition0_length); + if (key_frame) { + if (!(data[0] == 0x9d && data[1] == 0x01 && data[2] == 0x2a)) { + LOG_ERROR("Invalid lossy bitstream signature."); + return WEBP_INFO_BITSTREAM_ERROR; + } + printf(" Width: %d\n" + " X scale: %d\n" + " Height: %d\n" + " Y scale: %d\n", + ((data[4] << 8) | data[3]) & 0x3fff, data[4] >> 6, + ((data[6] << 8) | data[5]) & 0x3fff, data[6] >> 6); + data += 7; + data_size -= 7; + } else { + LOG_ERROR("Non-keyframe detected in lossy bitstream."); + return WEBP_INFO_BITSTREAM_ERROR; + } + if (partition0_length >= data_size) { + LOG_ERROR("Bad partition length."); + return WEBP_INFO_BITSTREAM_ERROR; + } + GET_BITS(colorspace, 1); + GET_BITS(clamp_type, 1); + printf(" Color space: %d\n", colorspace); + printf(" Clamp type: %d\n", clamp_type); + status = ParseLossySegmentHeader(webp_info, data, data_size, bit_pos); + if (status != WEBP_INFO_OK) return status; + status = ParseLossyFilterHeader(webp_info, data, data_size, bit_pos); + if (status != WEBP_INFO_OK) return status; + { // Partition number and size. + const uint8_t* part_size = data + partition0_length; + int num_parts, i; + size_t part_data_size; + GET_BITS(num_parts, 2); + num_parts = 1 << num_parts; + if ((int)(data_size - partition0_length) < (num_parts - 1) * 3) { + LOG_ERROR("Truncated lossy bitstream."); + return WEBP_INFO_TRUNCATED_DATA; + } + part_data_size = data_size - partition0_length - (num_parts - 1) * 3; + printf(" Total partitions: %d\n", num_parts); + for (i = 1; i < num_parts; ++i) { + const size_t psize = + part_size[0] | (part_size[1] << 8) | (part_size[2] << 16); + if (psize > part_data_size) { + LOG_ERROR("Truncated partition."); + return WEBP_INFO_TRUNCATED_DATA; + } + printf(" Part. %d length: %d\n", i, (int)psize); + part_data_size -= psize; + part_size += 3; + } + } + // Quantizer. + { + int base_q, bit; + int dq_y1_dc = 0, dq_y2_dc = 0, dq_y2_ac = 0, dq_uv_dc = 0, dq_uv_ac = 0; + GET_BITS(base_q, 7); + GET_BITS(bit, 1); + if (bit) GET_SIGNED_BITS(dq_y1_dc, 4); + GET_BITS(bit, 1); + if (bit) GET_SIGNED_BITS(dq_y2_dc, 4); + GET_BITS(bit, 1); + if (bit) GET_SIGNED_BITS(dq_y2_ac, 4); + GET_BITS(bit, 1); + if (bit) GET_SIGNED_BITS(dq_uv_dc, 4); + GET_BITS(bit, 1); + if (bit) GET_SIGNED_BITS(dq_uv_ac, 4); + printf(" Base Q: %d\n", base_q); + printf(" DQ Y1 DC: %d\n", dq_y1_dc); + printf(" DQ Y2 DC: %d\n", dq_y2_dc); + printf(" DQ Y2 AC: %d\n", dq_y2_ac); + printf(" DQ UV DC: %d\n", dq_uv_dc); + printf(" DQ UV AC: %d\n", dq_uv_ac); + } + if ((*bit_pos >> 3) >= partition0_length) { + LOG_ERROR("Truncated lossy bitstream."); + return WEBP_INFO_TRUNCATED_DATA; + } + return WEBP_INFO_OK; +} + +// ----------------------------------------------------------------------------- +// Lossless bitstream analysis. + +static int LLGetBits(const uint8_t* const data, size_t data_size, size_t nb, + int* val, uint64_t* const bit_pos) { + uint32_t i = 0; + *val = 0; + while (i < nb) { + const uint64_t p = (*bit_pos)++; + if ((p >> 3) >= data_size) { + return 0; + } else { + const int bit = !!(data[p >> 3] & (1 << ((p & 7)))); + *val = *val | (bit << i); + ++i; + } + } + return 1; +} + +#define LL_GET_BITS(v, n) \ + do { \ + if (!LLGetBits(data, data_size, n, &(v), bit_pos)) { \ + LOG_ERROR("Truncated lossless bitstream."); \ + return WEBP_INFO_TRUNCATED_DATA; \ + } \ + } while (0) + +static WebPInfoStatus ParseLosslessTransform(WebPInfo* const webp_info, + const uint8_t* const data, + size_t data_size, + uint64_t* const bit_pos) { + int use_transform, block_size, n_colors; + LL_GET_BITS(use_transform, 1); + printf(" Use transform: %s\n", use_transform ? "Yes" : "No"); + if (use_transform) { + int type; + LL_GET_BITS(type, 2); + printf(" 1st transform: %s (%d)\n", kLosslessTransforms[type], type); + switch (type) { + case PREDICTOR_TRANSFORM: + case CROSS_COLOR_TRANSFORM: + LL_GET_BITS(block_size, 3); + block_size = 1 << (block_size + 2); + printf(" Tran. block size: %d\n", block_size); + break; + case COLOR_INDEXING_TRANSFORM: + LL_GET_BITS(n_colors, 8); + n_colors += 1; + printf(" No. of colors: %d\n", n_colors); + break; + default: break; + } + } + return WEBP_INFO_OK; +} + +static WebPInfoStatus ParseLosslessHeader(const ChunkData* const chunk_data, + WebPInfo* const webp_info) { + const uint8_t* data = chunk_data->payload_; + size_t data_size = chunk_data->size_ - CHUNK_HEADER_SIZE; + uint64_t bit_position = 0; + uint64_t* const bit_pos = &bit_position; + WebPInfoStatus status; + printf(" Parsing lossless bitstream...\n"); + if (data_size < VP8L_FRAME_HEADER_SIZE) { + LOG_ERROR("Truncated lossless bitstream."); + return WEBP_INFO_TRUNCATED_DATA; + } + if (data[0] != VP8L_MAGIC_BYTE) { + LOG_ERROR("Invalid lossless bitstream signature."); + return WEBP_INFO_BITSTREAM_ERROR; + } + data += 1; + data_size -= 1; + { + int width, height, has_alpha, version; + LL_GET_BITS(width, 14); + LL_GET_BITS(height, 14); + LL_GET_BITS(has_alpha, 1); + LL_GET_BITS(version, 3); + width += 1; + height += 1; + printf(" Width: %d\n", width); + printf(" Height: %d\n", height); + printf(" Alpha: %d\n", has_alpha); + printf(" Version: %d\n", version); + } + status = ParseLosslessTransform(webp_info, data, data_size, bit_pos); + if (status != WEBP_INFO_OK) return status; + return WEBP_INFO_OK; +} + +static WebPInfoStatus ParseAlphaHeader(const ChunkData* const chunk_data, + WebPInfo* const webp_info) { + const uint8_t* data = chunk_data->payload_; + size_t data_size = chunk_data->size_ - CHUNK_HEADER_SIZE; + if (data_size <= ALPHA_HEADER_LEN) { + LOG_ERROR("Truncated ALPH chunk."); + return WEBP_INFO_TRUNCATED_DATA; + } + printf(" Parsing ALPH chunk...\n"); + { + const int compression_method = (data[0] >> 0) & 0x03; + const int filter = (data[0] >> 2) & 0x03; + const int pre_processing = (data[0] >> 4) & 0x03; + const int reserved_bits = (data[0] >> 6) & 0x03; + printf(" Compression: %d\n", compression_method); + printf(" Filter: %s (%d)\n", + kAlphaFilterMethods[filter], filter); + printf(" Pre-processing: %d\n", pre_processing); + if (compression_method > ALPHA_LOSSLESS_COMPRESSION) { + LOG_ERROR("Invalid Alpha compression method."); + return WEBP_INFO_BITSTREAM_ERROR; + } + if (pre_processing > ALPHA_PREPROCESSED_LEVELS) { + LOG_ERROR("Invalid Alpha pre-processing method."); + return WEBP_INFO_BITSTREAM_ERROR; + } + if (reserved_bits != 0) { + LOG_WARN("Reserved bits in ALPH chunk header are not all 0."); + } + data += ALPHA_HEADER_LEN; + data_size -= ALPHA_HEADER_LEN; + if (compression_method == ALPHA_LOSSLESS_COMPRESSION) { + uint64_t bit_pos = 0; + WebPInfoStatus status = + ParseLosslessTransform(webp_info, data, data_size, &bit_pos); + if (status != WEBP_INFO_OK) return status; + } + } + return WEBP_INFO_OK; +} + +// ----------------------------------------------------------------------------- +// Chunk parsing. + +static WebPInfoStatus ParseRIFFHeader(WebPInfo* const webp_info, + MemBuffer* const mem) { + const size_t min_size = RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE; + size_t riff_size; + + if (MemDataSize(mem) < min_size) { + LOG_ERROR("Truncated data detected when parsing RIFF header."); + return WEBP_INFO_TRUNCATED_DATA; + } + if (memcmp(GetBuffer(mem), "RIFF", CHUNK_SIZE_BYTES) || + memcmp(GetBuffer(mem) + CHUNK_HEADER_SIZE, "WEBP", CHUNK_SIZE_BYTES)) { + LOG_ERROR("Corrupted RIFF header."); + return WEBP_INFO_PARSE_ERROR; + } + riff_size = GetLE32(GetBuffer(mem) + TAG_SIZE); + if (riff_size < CHUNK_HEADER_SIZE) { + LOG_ERROR("RIFF size is too small."); + return WEBP_INFO_PARSE_ERROR; + } + if (riff_size > MAX_CHUNK_PAYLOAD) { + LOG_ERROR("RIFF size is over limit."); + return WEBP_INFO_PARSE_ERROR; + } + riff_size += CHUNK_HEADER_SIZE; + if (!webp_info->quiet_) { + printf("RIFF HEADER:\n"); + printf(" File size: %6d\n", (int)riff_size); + } + if (riff_size < mem->end_) { + LOG_WARN("RIFF size is smaller than the file size."); + mem->end_ = riff_size; + } else if (riff_size > mem->end_) { + LOG_ERROR("Truncated data detected when parsing RIFF payload."); + return WEBP_INFO_TRUNCATED_DATA; + } + Skip(mem, RIFF_HEADER_SIZE); + return WEBP_INFO_OK; +} + +static WebPInfoStatus ParseChunk(const WebPInfo* const webp_info, + MemBuffer* const mem, + ChunkData* const chunk_data) { + memset(chunk_data, 0, sizeof(*chunk_data)); + if (MemDataSize(mem) < CHUNK_HEADER_SIZE) { + LOG_ERROR("Truncated data detected when parsing chunk header."); + return WEBP_INFO_TRUNCATED_DATA; + } else { + const size_t chunk_start_offset = mem->start_; + const uint32_t fourcc = ReadMemBufLE32(mem); + const uint32_t payload_size = ReadMemBufLE32(mem); + const uint32_t payload_size_padded = payload_size + (payload_size & 1); + const size_t chunk_size = CHUNK_HEADER_SIZE + payload_size_padded; + int i; + if (payload_size > MAX_CHUNK_PAYLOAD) { + LOG_ERROR("Size of chunk payload is over limit."); + return WEBP_INFO_INVALID_PARAM; + } + if (payload_size_padded > MemDataSize(mem)){ + LOG_ERROR("Truncated data detected when parsing chunk payload."); + return WEBP_INFO_TRUNCATED_DATA; + } + for (i = 0; i < CHUNK_TYPES; ++i) { + if (kWebPChunkTags[i] == fourcc) break; + } + chunk_data->offset_ = chunk_start_offset; + chunk_data->size_ = chunk_size; + chunk_data->id_ = (ChunkID)i; + chunk_data->payload_ = GetBuffer(mem); + if (chunk_data->id_ == CHUNK_ANMF) { + if (payload_size != payload_size_padded) { + LOG_ERROR("ANMF chunk size should always be even."); + return WEBP_INFO_PARSE_ERROR; + } + // There are sub-chunks to be parsed in an ANMF chunk. + Skip(mem, ANMF_CHUNK_SIZE); + } else { + Skip(mem, payload_size_padded); + } + return WEBP_INFO_OK; + } +} + +// ----------------------------------------------------------------------------- +// Chunk analysis. + +static WebPInfoStatus ProcessVP8XChunk(const ChunkData* const chunk_data, + WebPInfo* const webp_info) { + const uint8_t* data = chunk_data->payload_; + if (webp_info->chunk_counts_[CHUNK_VP8] || + webp_info->chunk_counts_[CHUNK_VP8L] || + webp_info->chunk_counts_[CHUNK_VP8X]) { + LOG_ERROR("Already seen a VP8/VP8L/VP8X chunk when parsing VP8X chunk."); + return WEBP_INFO_PARSE_ERROR; + } + if (chunk_data->size_ != VP8X_CHUNK_SIZE + CHUNK_HEADER_SIZE) { + LOG_ERROR("Corrupted VP8X chunk."); + return WEBP_INFO_PARSE_ERROR; + } + ++webp_info->chunk_counts_[CHUNK_VP8X]; + webp_info->feature_flags_ = *data; + data += 4; + webp_info->canvas_width_ = 1 + ReadLE24(&data); + webp_info->canvas_height_ = 1 + ReadLE24(&data); + if (!webp_info->quiet_) { + printf(" ICCP: %d\n Alpha: %d\n EXIF: %d\n XMP: %d\n Animation: %d\n", + (webp_info->feature_flags_ & ICCP_FLAG) != 0, + (webp_info->feature_flags_ & ALPHA_FLAG) != 0, + (webp_info->feature_flags_ & EXIF_FLAG) != 0, + (webp_info->feature_flags_ & XMP_FLAG) != 0, + (webp_info->feature_flags_ & ANIMATION_FLAG) != 0); + printf(" Canvas size %d x %d\n", + webp_info->canvas_width_, webp_info->canvas_height_); + } + if (webp_info->canvas_width_ > MAX_CANVAS_SIZE) { + LOG_WARN("Canvas width is out of range in VP8X chunk."); + } + if (webp_info->canvas_height_ > MAX_CANVAS_SIZE) { + LOG_WARN("Canvas height is out of range in VP8X chunk."); + } + if ((uint64_t)webp_info->canvas_width_ * webp_info->canvas_height_ > + MAX_IMAGE_AREA) { + LOG_WARN("Canvas area is out of range in VP8X chunk."); + } + return WEBP_INFO_OK; +} + +static WebPInfoStatus ProcessANIMChunk(const ChunkData* const chunk_data, + WebPInfo* const webp_info) { + const uint8_t* data = chunk_data->payload_; + if (!webp_info->chunk_counts_[CHUNK_VP8X]) { + LOG_ERROR("ANIM chunk detected before VP8X chunk."); + return WEBP_INFO_PARSE_ERROR; + } + if (chunk_data->size_ != ANIM_CHUNK_SIZE + CHUNK_HEADER_SIZE) { + LOG_ERROR("Corrupted ANIM chunk."); + return WEBP_INFO_PARSE_ERROR; + } + webp_info->bgcolor_ = ReadLE32(&data); + webp_info->loop_count_ = ReadLE16(&data); + ++webp_info->chunk_counts_[CHUNK_ANIM]; + if (!webp_info->quiet_) { + printf(" Background color:(ARGB) %02x %02x %02x %02x\n", + (webp_info->bgcolor_ >> 24) & 0xff, + (webp_info->bgcolor_ >> 16) & 0xff, + (webp_info->bgcolor_ >> 8) & 0xff, + webp_info->bgcolor_ & 0xff); + printf(" Loop count : %d\n", webp_info->loop_count_); + } + if (webp_info->loop_count_ > MAX_LOOP_COUNT) { + LOG_WARN("Loop count is out of range in ANIM chunk."); + } + return WEBP_INFO_OK; +} + +static WebPInfoStatus ProcessANMFChunk(const ChunkData* const chunk_data, + WebPInfo* const webp_info) { + const uint8_t* data = chunk_data->payload_; + int offset_x, offset_y, width, height, duration, blend, dispose, temp; + if (webp_info->is_processing_anim_frame_) { + LOG_ERROR("ANMF chunk detected within another ANMF chunk."); + return WEBP_INFO_PARSE_ERROR; + } + if (!webp_info->chunk_counts_[CHUNK_ANIM]) { + LOG_ERROR("ANMF chunk detected before ANIM chunk."); + return WEBP_INFO_PARSE_ERROR; + } + if (chunk_data->size_ <= CHUNK_HEADER_SIZE + ANMF_CHUNK_SIZE) { + LOG_ERROR("Truncated data detected when parsing ANMF chunk."); + return WEBP_INFO_TRUNCATED_DATA; + } + offset_x = 2 * ReadLE24(&data); + offset_y = 2 * ReadLE24(&data); + width = 1 + ReadLE24(&data); + height = 1 + ReadLE24(&data); + duration = ReadLE24(&data); + temp = *data; + dispose = temp & 1; + blend = (temp >> 1) & 1; + ++webp_info->chunk_counts_[CHUNK_ANMF]; + if (!webp_info->quiet_) { + printf(" Offset_X: %d\n Offset_Y: %d\n Width: %d\n Height: %d\n" + " Duration: %d\n Dispose: %d\n Blend: %d\n", + offset_x, offset_y, width, height, duration, dispose, blend); + } + if (duration > MAX_DURATION) { + LOG_ERROR("Invalid duration parameter in ANMF chunk."); + return WEBP_INFO_INVALID_PARAM; + } + if (offset_x > MAX_POSITION_OFFSET || offset_y > MAX_POSITION_OFFSET) { + LOG_ERROR("Invalid offset parameters in ANMF chunk."); + return WEBP_INFO_INVALID_PARAM; + } + if ((uint64_t)offset_x + width > (uint64_t)webp_info->canvas_width_ || + (uint64_t)offset_y + height > (uint64_t)webp_info->canvas_height_) { + LOG_ERROR("Frame exceeds canvas in ANMF chunk."); + return WEBP_INFO_INVALID_PARAM; + } + webp_info->is_processing_anim_frame_ = 1; + webp_info->seen_alpha_subchunk_ = 0; + webp_info->seen_image_subchunk_ = 0; + webp_info->frame_width_ = width; + webp_info->frame_height_ = height; + webp_info->anim_frame_data_size_ = + chunk_data->size_ - CHUNK_HEADER_SIZE - ANMF_CHUNK_SIZE; + return WEBP_INFO_OK; +} + +static WebPInfoStatus ProcessImageChunk(const ChunkData* const chunk_data, + WebPInfo* const webp_info) { + const uint8_t* data = chunk_data->payload_ - CHUNK_HEADER_SIZE; + WebPBitstreamFeatures features; + const VP8StatusCode vp8_status = + WebPGetFeatures(data, chunk_data->size_, &features); + if (vp8_status != VP8_STATUS_OK) { + LOG_ERROR("VP8/VP8L bitstream error."); + return WEBP_INFO_BITSTREAM_ERROR; + } + if (!webp_info->quiet_) { + assert(features.format >= 0 && features.format <= 2); + printf(" Width: %d\n Height: %d\n Alpha: %d\n Animation: %d\n" + " Format: %s (%d)\n", + features.width, features.height, features.has_alpha, + features.has_animation, kFormats[features.format], features.format); + } + if (webp_info->is_processing_anim_frame_) { + ++webp_info->anmf_subchunk_counts_[chunk_data->id_ == CHUNK_VP8 ? 0 : 1]; + if (chunk_data->id_ == CHUNK_VP8L && webp_info->seen_alpha_subchunk_) { + LOG_ERROR("Both VP8L and ALPH sub-chunks are present in an ANMF chunk."); + return WEBP_INFO_PARSE_ERROR; + } + if (webp_info->frame_width_ != features.width || + webp_info->frame_height_ != features.height) { + LOG_ERROR("Frame size in VP8/VP8L sub-chunk differs from ANMF header."); + return WEBP_INFO_PARSE_ERROR; + } + if (webp_info->seen_image_subchunk_) { + LOG_ERROR("Consecutive VP8/VP8L sub-chunks in an ANMF chunk."); + return WEBP_INFO_PARSE_ERROR; + } + webp_info->seen_image_subchunk_ = 1; + } else { + if (webp_info->chunk_counts_[CHUNK_VP8] || + webp_info->chunk_counts_[CHUNK_VP8L]) { + LOG_ERROR("Multiple VP8/VP8L chunks detected."); + return WEBP_INFO_PARSE_ERROR; + } + if (chunk_data->id_ == CHUNK_VP8L && + webp_info->chunk_counts_[CHUNK_ALPHA]) { + LOG_WARN("Both VP8L and ALPH chunks are detected."); + } + if (webp_info->chunk_counts_[CHUNK_ANIM] || + webp_info->chunk_counts_[CHUNK_ANMF]) { + LOG_ERROR("VP8/VP8L chunk and ANIM/ANMF chunk are both detected."); + return WEBP_INFO_PARSE_ERROR; + } + if (webp_info->chunk_counts_[CHUNK_VP8X]) { + if (webp_info->canvas_width_ != features.width || + webp_info->canvas_height_ != features.height) { + LOG_ERROR("Image size in VP8/VP8L chunk differs from VP8X chunk."); + return WEBP_INFO_PARSE_ERROR; + } + } else { + webp_info->canvas_width_ = features.width; + webp_info->canvas_height_ = features.height; + if (webp_info->canvas_width_ < 1 || webp_info->canvas_height_ < 1 || + webp_info->canvas_width_ > MAX_CANVAS_SIZE || + webp_info->canvas_height_ > MAX_CANVAS_SIZE || + (uint64_t)webp_info->canvas_width_ * webp_info->canvas_height_ > + MAX_IMAGE_AREA) { + LOG_WARN("Invalid parameters in VP8/VP8L chunk."); + } + } + ++webp_info->chunk_counts_[chunk_data->id_]; + } + ++webp_info->num_frames_; + webp_info->has_alpha_ |= features.has_alpha; + if (webp_info->parse_bitstream_) { + const int is_lossy = (chunk_data->id_ == CHUNK_VP8); + const WebPInfoStatus status = + is_lossy ? ParseLossyHeader(chunk_data, webp_info) + : ParseLosslessHeader(chunk_data, webp_info); + if (status != WEBP_INFO_OK) return status; + } + return WEBP_INFO_OK; +} + +static WebPInfoStatus ProcessALPHChunk(const ChunkData* const chunk_data, + WebPInfo* const webp_info) { + if (webp_info->is_processing_anim_frame_) { + ++webp_info->anmf_subchunk_counts_[2]; + if (webp_info->seen_alpha_subchunk_) { + LOG_ERROR("Consecutive ALPH sub-chunks in an ANMF chunk."); + return WEBP_INFO_PARSE_ERROR; + } + webp_info->seen_alpha_subchunk_ = 1; + + if (webp_info->seen_image_subchunk_) { + LOG_ERROR("ALPHA sub-chunk detected after VP8 sub-chunk " + "in an ANMF chunk."); + return WEBP_INFO_PARSE_ERROR; + } + } else { + if (webp_info->chunk_counts_[CHUNK_ANIM] || + webp_info->chunk_counts_[CHUNK_ANMF]) { + LOG_ERROR("ALPHA chunk and ANIM/ANMF chunk are both detected."); + return WEBP_INFO_PARSE_ERROR; + } + if (!webp_info->chunk_counts_[CHUNK_VP8X]) { + LOG_ERROR("ALPHA chunk detected before VP8X chunk."); + return WEBP_INFO_PARSE_ERROR; + } + if (webp_info->chunk_counts_[CHUNK_VP8]) { + LOG_ERROR("ALPHA chunk detected after VP8 chunk."); + return WEBP_INFO_PARSE_ERROR; + } + if (webp_info->chunk_counts_[CHUNK_ALPHA]) { + LOG_ERROR("Multiple ALPHA chunks detected."); + return WEBP_INFO_PARSE_ERROR; + } + ++webp_info->chunk_counts_[CHUNK_ALPHA]; + } + webp_info->has_alpha_ = 1; + if (webp_info->parse_bitstream_) { + const WebPInfoStatus status = ParseAlphaHeader(chunk_data, webp_info); + if (status != WEBP_INFO_OK) return status; + } + return WEBP_INFO_OK; +} + +static WebPInfoStatus ProcessICCPChunk(const ChunkData* const chunk_data, + WebPInfo* const webp_info) { + (void)chunk_data; + if (!webp_info->chunk_counts_[CHUNK_VP8X]) { + LOG_ERROR("ICCP chunk detected before VP8X chunk."); + return WEBP_INFO_PARSE_ERROR; + } + if (webp_info->chunk_counts_[CHUNK_VP8] || + webp_info->chunk_counts_[CHUNK_VP8L] || + webp_info->chunk_counts_[CHUNK_ANIM]) { + LOG_ERROR("ICCP chunk detected after image data."); + return WEBP_INFO_PARSE_ERROR; + } + ++webp_info->chunk_counts_[CHUNK_ICCP]; + return WEBP_INFO_OK; +} + +static WebPInfoStatus ProcessChunk(const ChunkData* const chunk_data, + WebPInfo* const webp_info) { + WebPInfoStatus status = WEBP_INFO_OK; + ChunkID id = chunk_data->id_; + if (chunk_data->id_ == CHUNK_UNKNOWN) { + char error_message[50]; + snprintf(error_message, 50, "Unknown chunk at offset %6d, length %6d", + (int)chunk_data->offset_, (int)chunk_data->size_); + LOG_WARN(error_message); + } else { + if (!webp_info->quiet_) { + char tag[4]; + uint32_t fourcc = kWebPChunkTags[chunk_data->id_]; +#ifdef WORDS_BIGENDIAN + fourcc = (fourcc >> 24) | ((fourcc >> 8) & 0xff00) | + ((fourcc << 8) & 0xff0000) | (fourcc << 24); +#endif + memcpy(tag, &fourcc, sizeof(tag)); + printf("Chunk %c%c%c%c at offset %6d, length %6d\n", + tag[0], tag[1], tag[2], tag[3], (int)chunk_data->offset_, + (int)chunk_data->size_); + } + } + switch (id) { + case CHUNK_VP8: + case CHUNK_VP8L: + status = ProcessImageChunk(chunk_data, webp_info); + break; + case CHUNK_VP8X: + status = ProcessVP8XChunk(chunk_data, webp_info); + break; + case CHUNK_ALPHA: + status = ProcessALPHChunk(chunk_data, webp_info); + break; + case CHUNK_ANIM: + status = ProcessANIMChunk(chunk_data, webp_info); + break; + case CHUNK_ANMF: + status = ProcessANMFChunk(chunk_data, webp_info); + break; + case CHUNK_ICCP: + status = ProcessICCPChunk(chunk_data, webp_info); + break; + case CHUNK_EXIF: + case CHUNK_XMP: + ++webp_info->chunk_counts_[id]; + break; + case CHUNK_UNKNOWN: + default: + break; + } + if (webp_info->is_processing_anim_frame_ && id != CHUNK_ANMF) { + if (webp_info->anim_frame_data_size_ == chunk_data->size_) { + if (!webp_info->seen_image_subchunk_) { + LOG_ERROR("No VP8/VP8L chunk detected in an ANMF chunk."); + return WEBP_INFO_PARSE_ERROR; + } + webp_info->is_processing_anim_frame_ = 0; + } else if (webp_info->anim_frame_data_size_ > chunk_data->size_) { + webp_info->anim_frame_data_size_ -= chunk_data->size_; + } else { + LOG_ERROR("Truncated data detected when parsing ANMF chunk."); + return WEBP_INFO_TRUNCATED_DATA; + } + } + return status; +} + +static WebPInfoStatus Validate(WebPInfo* const webp_info) { + if (webp_info->num_frames_ < 1) { + LOG_ERROR("No image/frame detected."); + return WEBP_INFO_MISSING_DATA; + } + if (webp_info->chunk_counts_[CHUNK_VP8X]) { + const int iccp = !!(webp_info->feature_flags_ & ICCP_FLAG); + const int exif = !!(webp_info->feature_flags_ & EXIF_FLAG); + const int xmp = !!(webp_info->feature_flags_ & XMP_FLAG); + const int animation = !!(webp_info->feature_flags_ & ANIMATION_FLAG); + const int alpha = !!(webp_info->feature_flags_ & ALPHA_FLAG); + if (!alpha && webp_info->has_alpha_) { + LOG_ERROR("Unexpected alpha data detected."); + return WEBP_INFO_PARSE_ERROR; + } + if (alpha && !webp_info->has_alpha_) { + LOG_WARN("Alpha flag is set with no alpha data present."); + } + if (iccp && !webp_info->chunk_counts_[CHUNK_ICCP]) { + LOG_ERROR("Missing ICCP chunk."); + return WEBP_INFO_MISSING_DATA; + } + if (exif && !webp_info->chunk_counts_[CHUNK_EXIF]) { + LOG_ERROR("Missing EXIF chunk."); + return WEBP_INFO_MISSING_DATA; + } + if (xmp && !webp_info->chunk_counts_[CHUNK_XMP]) { + LOG_ERROR("Missing XMP chunk."); + return WEBP_INFO_MISSING_DATA; + } + if (!iccp && webp_info->chunk_counts_[CHUNK_ICCP]) { + LOG_ERROR("Unexpected ICCP chunk detected."); + return WEBP_INFO_PARSE_ERROR; + } + if (!exif && webp_info->chunk_counts_[CHUNK_EXIF]) { + LOG_ERROR("Unexpected EXIF chunk detected."); + return WEBP_INFO_PARSE_ERROR; + } + if (!xmp && webp_info->chunk_counts_[CHUNK_XMP]) { + LOG_ERROR("Unexpected XMP chunk detected."); + return WEBP_INFO_PARSE_ERROR; + } + // Incomplete animation frame. + if (webp_info->is_processing_anim_frame_) return WEBP_INFO_MISSING_DATA; + if (!animation && webp_info->num_frames_ > 1) { + LOG_ERROR("More than 1 frame detected in non-animation file."); + return WEBP_INFO_PARSE_ERROR; + } + if (animation && (!webp_info->chunk_counts_[CHUNK_ANIM] || + !webp_info->chunk_counts_[CHUNK_ANMF])) { + LOG_ERROR("No ANIM/ANMF chunk detected in animation file."); + return WEBP_INFO_PARSE_ERROR; + } + } + return WEBP_INFO_OK; +} + +static void ShowSummary(const WebPInfo* const webp_info) { + int i; + printf("Summary:\n"); + printf("Number of frames: %d\n", webp_info->num_frames_); + printf("Chunk type : VP8 VP8L VP8X ALPH ANIM ANMF(VP8 /VP8L/ALPH) ICCP " + "EXIF XMP\n"); + printf("Chunk counts: "); + for (i = 0; i < CHUNK_TYPES; ++i) { + printf("%4d ", webp_info->chunk_counts_[i]); + if (i == CHUNK_ANMF) { + printf("%4d %4d %4d ", + webp_info->anmf_subchunk_counts_[0], + webp_info->anmf_subchunk_counts_[1], + webp_info->anmf_subchunk_counts_[2]); + } + } + printf("\n"); +} + +static WebPInfoStatus AnalyzeWebP(WebPInfo* const webp_info, + const WebPData* webp_data) { + ChunkData chunk_data; + MemBuffer mem_buffer; + WebPInfoStatus webp_info_status = WEBP_INFO_OK; + + InitMemBuffer(&mem_buffer, webp_data); + webp_info_status = ParseRIFFHeader(webp_info, &mem_buffer); + if (webp_info_status != WEBP_INFO_OK) goto Error; + + // Loop through all the chunks. Terminate immediately in case of error. + while (webp_info_status == WEBP_INFO_OK && MemDataSize(&mem_buffer) > 0) { + webp_info_status = ParseChunk(webp_info, &mem_buffer, &chunk_data); + if (webp_info_status != WEBP_INFO_OK) goto Error; + webp_info_status = ProcessChunk(&chunk_data, webp_info); + } + if (webp_info_status != WEBP_INFO_OK) goto Error; + if (webp_info->show_summary_) ShowSummary(webp_info); + + // Final check. + webp_info_status = Validate(webp_info); + + Error: + if (!webp_info->quiet_) { + if (webp_info_status == WEBP_INFO_OK) { + printf("No error detected.\n"); + } else { + printf("Errors detected.\n"); + } + if (webp_info->num_warnings_ > 0) { + printf("There were %d warning(s).\n", webp_info->num_warnings_); + } + } + return webp_info_status; +} + +static void Help(void) { + printf("Usage: webpinfo [options] in_files\n" + "Note: there could be multiple input files;\n" + " options must come before input files.\n" + "Options:\n" + " -version ........... Print version number and exit.\n" + " -quiet ............. Do not show chunk parsing information.\n" + " -diag .............. Show parsing error diagnosis.\n" + " -summary ........... Show chunk stats summary.\n" + " -bitstream_info .... Parse bitstream header.\n"); +} + +int main(int argc, const char* argv[]) { + int c, quiet = 0, show_diag = 0, show_summary = 0; + int parse_bitstream = 0; + WebPInfoStatus webp_info_status = WEBP_INFO_OK; + WebPInfo webp_info; + + INIT_WARGV(argc, argv); + + if (argc == 1) { + Help(); + FREE_WARGV_AND_RETURN(WEBP_INFO_OK); + } + + // Parse command-line input. + for (c = 1; c < argc; ++c) { + if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help") || + !strcmp(argv[c], "-H") || !strcmp(argv[c], "-longhelp")) { + Help(); + FREE_WARGV_AND_RETURN(WEBP_INFO_OK); + } else if (!strcmp(argv[c], "-quiet")) { + quiet = 1; + } else if (!strcmp(argv[c], "-diag")) { + show_diag = 1; + } else if (!strcmp(argv[c], "-summary")) { + show_summary = 1; + } else if (!strcmp(argv[c], "-bitstream_info")) { + parse_bitstream = 1; + } else if (!strcmp(argv[c], "-version")) { + const int version = WebPGetDecoderVersion(); + printf("WebP Decoder version: %d.%d.%d\n", + (version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff); + FREE_WARGV_AND_RETURN(0); + } else { // Assume the remaining are all input files. + break; + } + } + + if (c == argc) { + Help(); + FREE_WARGV_AND_RETURN(WEBP_INFO_INVALID_COMMAND); + } + + // Process input files one by one. + for (; c < argc; ++c) { + WebPData webp_data; + const W_CHAR* in_file = NULL; + WebPInfoInit(&webp_info); + webp_info.quiet_ = quiet; + webp_info.show_diagnosis_ = show_diag; + webp_info.show_summary_ = show_summary; + webp_info.parse_bitstream_ = parse_bitstream; + in_file = GET_WARGV(argv, c); + if (in_file == NULL || + !ReadFileToWebPData((const char*)in_file, &webp_data)) { + webp_info_status = WEBP_INFO_INVALID_COMMAND; + WFPRINTF(stderr, "Failed to open input file %s.\n", in_file); + continue; + } + if (!webp_info.quiet_) WPRINTF("File: %s\n", in_file); + webp_info_status = AnalyzeWebP(&webp_info, &webp_data); + WebPDataClear(&webp_data); + } + FREE_WARGV_AND_RETURN(webp_info_status); +} diff --git a/third-party/webp/libwebp/examples/webpmux.c b/third-party/webp/libwebp/examples/webpmux.c new file mode 100644 index 0000000000..b61eed6e03 --- /dev/null +++ b/third-party/webp/libwebp/examples/webpmux.c @@ -0,0 +1,1234 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Simple command-line to create a WebP container file and to extract or strip +// relevant data from the container file. +// +// Authors: Vikas (vikaas.arora@gmail.com), +// Urvang (urvang@google.com) + +/* Usage examples: + + Create container WebP file: + webpmux -frame anim_1.webp +100+10+10 \ + -frame anim_2.webp +100+25+25+1 \ + -frame anim_3.webp +100+50+50+1 \ + -frame anim_4.webp +100 \ + -loop 10 -bgcolor 128,255,255,255 \ + -o out_animation_container.webp + + webpmux -set icc image_profile.icc in.webp -o out_icc_container.webp + webpmux -set exif image_metadata.exif in.webp -o out_exif_container.webp + webpmux -set xmp image_metadata.xmp in.webp -o out_xmp_container.webp + webpmux -set loop 1 in.webp -o out_looped.webp + + Extract relevant data from WebP container file: + webpmux -get frame n in.webp -o out_frame.webp + webpmux -get icc in.webp -o image_profile.icc + webpmux -get exif in.webp -o image_metadata.exif + webpmux -get xmp in.webp -o image_metadata.xmp + + Strip data from WebP Container file: + webpmux -strip icc in.webp -o out.webp + webpmux -strip exif in.webp -o out.webp + webpmux -strip xmp in.webp -o out.webp + + Change duration of frame intervals: + webpmux -duration 150 in.webp -o out.webp + webpmux -duration 33,2 in.webp -o out.webp + webpmux -duration 200,10,0 -duration 150,6,50 in.webp -o out.webp + + Misc: + webpmux -info in.webp + webpmux [ -h | -help ] + webpmux -version + webpmux argument_file_name +*/ + +#ifdef HAVE_CONFIG_H +#include "webp/config.h" +#endif + +#include +#include +#include +#include +#include "webp/decode.h" +#include "webp/mux.h" +#include "../examples/example_util.h" +#include "../imageio/imageio_util.h" +#include "./unicode.h" + +//------------------------------------------------------------------------------ +// Config object to parse command-line arguments. + +typedef enum { + NIL_ACTION = 0, + ACTION_GET, + ACTION_SET, + ACTION_STRIP, + ACTION_INFO, + ACTION_HELP, + ACTION_DURATION +} ActionType; + +typedef enum { + NIL_SUBTYPE = 0, + SUBTYPE_ANMF, + SUBTYPE_LOOP, + SUBTYPE_BGCOLOR +} FeatureSubType; + +typedef struct { + FeatureSubType subtype_; + const char* filename_; + const char* params_; +} FeatureArg; + +typedef enum { + NIL_FEATURE = 0, + FEATURE_EXIF, + FEATURE_XMP, + FEATURE_ICCP, + FEATURE_ANMF, + FEATURE_DURATION, + FEATURE_LOOP, + FEATURE_BGCOLOR, + LAST_FEATURE +} FeatureType; + +static const char* const kFourccList[LAST_FEATURE] = { + NULL, "EXIF", "XMP ", "ICCP", "ANMF" +}; + +static const char* const kDescriptions[LAST_FEATURE] = { + NULL, "EXIF metadata", "XMP metadata", "ICC profile", + "Animation frame" +}; + +typedef struct { + CommandLineArguments cmd_args_; + + ActionType action_type_; + const char* input_; + const char* output_; + FeatureType type_; + FeatureArg* args_; + int arg_count_; +} Config; + +//------------------------------------------------------------------------------ +// Helper functions. + +static int CountOccurrences(const CommandLineArguments* const args, + const char* const arg) { + int i; + int num_occurences = 0; + + for (i = 0; i < args->argc_; ++i) { + if (!strcmp(args->argv_[i], arg)) { + ++num_occurences; + } + } + return num_occurences; +} + +static const char* const kErrorMessages[-WEBP_MUX_NOT_ENOUGH_DATA + 1] = { + "WEBP_MUX_NOT_FOUND", "WEBP_MUX_INVALID_ARGUMENT", "WEBP_MUX_BAD_DATA", + "WEBP_MUX_MEMORY_ERROR", "WEBP_MUX_NOT_ENOUGH_DATA" +}; + +static const char* ErrorString(WebPMuxError err) { + assert(err <= WEBP_MUX_NOT_FOUND && err >= WEBP_MUX_NOT_ENOUGH_DATA); + return kErrorMessages[-err]; +} + +#define RETURN_IF_ERROR(ERR_MSG) \ + if (err != WEBP_MUX_OK) { \ + fprintf(stderr, ERR_MSG); \ + return err; \ + } + +#define RETURN_IF_ERROR3(ERR_MSG, FORMAT_STR1, FORMAT_STR2) \ + if (err != WEBP_MUX_OK) { \ + fprintf(stderr, ERR_MSG, FORMAT_STR1, FORMAT_STR2); \ + return err; \ + } + +#define ERROR_GOTO1(ERR_MSG, LABEL) \ + do { \ + fprintf(stderr, ERR_MSG); \ + ok = 0; \ + goto LABEL; \ + } while (0) + +#define ERROR_GOTO2(ERR_MSG, FORMAT_STR, LABEL) \ + do { \ + fprintf(stderr, ERR_MSG, FORMAT_STR); \ + ok = 0; \ + goto LABEL; \ + } while (0) + +#define ERROR_GOTO3(ERR_MSG, FORMAT_STR1, FORMAT_STR2, LABEL) \ + do { \ + fprintf(stderr, ERR_MSG, FORMAT_STR1, FORMAT_STR2); \ + ok = 0; \ + goto LABEL; \ + } while (0) + +static WebPMuxError DisplayInfo(const WebPMux* mux) { + int width, height; + uint32_t flag; + + WebPMuxError err = WebPMuxGetCanvasSize(mux, &width, &height); + assert(err == WEBP_MUX_OK); // As WebPMuxCreate() was successful earlier. + printf("Canvas size: %d x %d\n", width, height); + + err = WebPMuxGetFeatures(mux, &flag); + RETURN_IF_ERROR("Failed to retrieve features\n"); + + if (flag == 0) { + printf("No features present.\n"); + return err; + } + + // Print the features present. + printf("Features present:"); + if (flag & ANIMATION_FLAG) printf(" animation"); + if (flag & ICCP_FLAG) printf(" ICC profile"); + if (flag & EXIF_FLAG) printf(" EXIF metadata"); + if (flag & XMP_FLAG) printf(" XMP metadata"); + if (flag & ALPHA_FLAG) printf(" transparency"); + printf("\n"); + + if (flag & ANIMATION_FLAG) { + const WebPChunkId id = WEBP_CHUNK_ANMF; + const char* const type_str = "frame"; + int nFrames; + + WebPMuxAnimParams params; + err = WebPMuxGetAnimationParams(mux, ¶ms); + assert(err == WEBP_MUX_OK); + printf("Background color : 0x%.8X Loop Count : %d\n", + params.bgcolor, params.loop_count); + + err = WebPMuxNumChunks(mux, id, &nFrames); + assert(err == WEBP_MUX_OK); + + printf("Number of %ss: %d\n", type_str, nFrames); + if (nFrames > 0) { + int i; + printf("No.: width height alpha x_offset y_offset "); + printf("duration dispose blend "); + printf("image_size compression\n"); + for (i = 1; i <= nFrames; i++) { + WebPMuxFrameInfo frame; + err = WebPMuxGetFrame(mux, i, &frame); + if (err == WEBP_MUX_OK) { + WebPBitstreamFeatures features; + const VP8StatusCode status = WebPGetFeatures( + frame.bitstream.bytes, frame.bitstream.size, &features); + assert(status == VP8_STATUS_OK); // Checked by WebPMuxCreate(). + (void)status; + printf("%3d: %5d %5d %5s %8d %8d ", i, features.width, + features.height, features.has_alpha ? "yes" : "no", + frame.x_offset, frame.y_offset); + { + const char* const dispose = + (frame.dispose_method == WEBP_MUX_DISPOSE_NONE) ? "none" + : "background"; + const char* const blend = + (frame.blend_method == WEBP_MUX_BLEND) ? "yes" : "no"; + printf("%8d %10s %5s ", frame.duration, dispose, blend); + } + printf("%10d %11s\n", (int)frame.bitstream.size, + (features.format == 1) ? "lossy" : + (features.format == 2) ? "lossless" : + "undefined"); + } + WebPDataClear(&frame.bitstream); + RETURN_IF_ERROR3("Failed to retrieve %s#%d\n", type_str, i); + } + } + } + + if (flag & ICCP_FLAG) { + WebPData icc_profile; + err = WebPMuxGetChunk(mux, "ICCP", &icc_profile); + assert(err == WEBP_MUX_OK); + printf("Size of the ICC profile data: %d\n", (int)icc_profile.size); + } + + if (flag & EXIF_FLAG) { + WebPData exif; + err = WebPMuxGetChunk(mux, "EXIF", &exif); + assert(err == WEBP_MUX_OK); + printf("Size of the EXIF metadata: %d\n", (int)exif.size); + } + + if (flag & XMP_FLAG) { + WebPData xmp; + err = WebPMuxGetChunk(mux, "XMP ", &xmp); + assert(err == WEBP_MUX_OK); + printf("Size of the XMP metadata: %d\n", (int)xmp.size); + } + + if ((flag & ALPHA_FLAG) && !(flag & ANIMATION_FLAG)) { + WebPMuxFrameInfo image; + err = WebPMuxGetFrame(mux, 1, &image); + if (err == WEBP_MUX_OK) { + printf("Size of the image (with alpha): %d\n", (int)image.bitstream.size); + } + WebPDataClear(&image.bitstream); + RETURN_IF_ERROR("Failed to retrieve the image\n"); + } + + return WEBP_MUX_OK; +} + +static void PrintHelp(void) { + printf("Usage: webpmux -get GET_OPTIONS INPUT -o OUTPUT\n"); + printf(" webpmux -set SET_OPTIONS INPUT -o OUTPUT\n"); + printf(" webpmux -duration DURATION_OPTIONS [-duration ...]\n"); + printf(" INPUT -o OUTPUT\n"); + printf(" webpmux -strip STRIP_OPTIONS INPUT -o OUTPUT\n"); + printf(" webpmux -frame FRAME_OPTIONS [-frame...] [-loop LOOP_COUNT]" + "\n"); + printf(" [-bgcolor BACKGROUND_COLOR] -o OUTPUT\n"); + printf(" webpmux -info INPUT\n"); + printf(" webpmux [-h|-help]\n"); + printf(" webpmux -version\n"); + printf(" webpmux argument_file_name\n"); + + printf("\n"); + printf("GET_OPTIONS:\n"); + printf(" Extract relevant data:\n"); + printf(" icc get ICC profile\n"); + printf(" exif get EXIF metadata\n"); + printf(" xmp get XMP metadata\n"); + printf(" frame n get nth frame\n"); + + printf("\n"); + printf("SET_OPTIONS:\n"); + printf(" Set color profile/metadata/parameters:\n"); + printf(" loop LOOP_COUNT set the loop count\n"); + printf(" bgcolor BACKGROUND_COLOR set the animation background color\n"); + printf(" icc file.icc set ICC profile\n"); + printf(" exif file.exif set EXIF metadata\n"); + printf(" xmp file.xmp set XMP metadata\n"); + printf(" where: 'file.icc' contains the ICC profile to be set,\n"); + printf(" 'file.exif' contains the EXIF metadata to be set\n"); + printf(" 'file.xmp' contains the XMP metadata to be set\n"); + + printf("\n"); + printf("DURATION_OPTIONS:\n"); + printf(" Set duration of selected frames:\n"); + printf(" duration set duration for all frames\n"); + printf(" duration,frame set duration of a particular frame\n"); + printf(" duration,start,end set duration of frames in the\n"); + printf(" interval [start,end])\n"); + printf(" where: 'duration' is the duration in milliseconds\n"); + printf(" 'start' is the start frame index\n"); + printf(" 'end' is the inclusive end frame index\n"); + printf(" The special 'end' value '0' means: last frame.\n"); + + printf("\n"); + printf("STRIP_OPTIONS:\n"); + printf(" Strip color profile/metadata:\n"); + printf(" icc strip ICC profile\n"); + printf(" exif strip EXIF metadata\n"); + printf(" xmp strip XMP metadata\n"); + + printf("\n"); + printf("FRAME_OPTIONS(i):\n"); + printf(" Create animation:\n"); + printf(" file_i +di[+xi+yi[+mi[bi]]]\n"); + printf(" where: 'file_i' is the i'th animation frame (WebP format),\n"); + printf(" 'di' is the pause duration before next frame,\n"); + printf(" 'xi','yi' specify the image offset for this frame,\n"); + printf(" 'mi' is the dispose method for this frame (0 or 1),\n"); + printf(" 'bi' is the blending method for this frame (+b or -b)" + "\n"); + + printf("\n"); + printf("LOOP_COUNT:\n"); + printf(" Number of times to repeat the animation.\n"); + printf(" Valid range is 0 to 65535 [Default: 0 (infinite)].\n"); + + printf("\n"); + printf("BACKGROUND_COLOR:\n"); + printf(" Background color of the canvas.\n"); + printf(" A,R,G,B\n"); + printf(" where: 'A', 'R', 'G' and 'B' are integers in the range 0 to 255 " + "specifying\n"); + printf(" the Alpha, Red, Green and Blue component values " + "respectively\n"); + printf(" [Default: 255,255,255,255]\n"); + + printf("\nINPUT & OUTPUT are in WebP format.\n"); + + printf("\nNote: The nature of EXIF, XMP and ICC data is not checked"); + printf(" and is assumed to be\nvalid.\n"); + printf("\nNote: if a single file name is passed as the argument, the " + "arguments will be\n"); + printf("tokenized from this file. The file name must not start with " + "the character '-'.\n"); +} + +static void WarnAboutOddOffset(const WebPMuxFrameInfo* const info) { + if ((info->x_offset | info->y_offset) & 1) { + fprintf(stderr, "Warning: odd offsets will be snapped to even values" + " (%d, %d) -> (%d, %d)\n", info->x_offset, info->y_offset, + info->x_offset & ~1, info->y_offset & ~1); + } +} + +static int CreateMux(const char* const filename, WebPMux** mux) { + WebPData bitstream; + assert(mux != NULL); + if (!ExUtilReadFileToWebPData(filename, &bitstream)) return 0; + *mux = WebPMuxCreate(&bitstream, 1); + WebPDataClear(&bitstream); + if (*mux != NULL) return 1; + WFPRINTF(stderr, "Failed to create mux object from file %s.\n", + (const W_CHAR*)filename); + return 0; +} + +static int WriteData(const char* filename, const WebPData* const webpdata) { + int ok = 0; + FILE* fout = WSTRCMP(filename, "-") ? WFOPEN(filename, "wb") + : ImgIoUtilSetBinaryMode(stdout); + if (fout == NULL) { + WFPRINTF(stderr, "Error opening output WebP file %s!\n", + (const W_CHAR*)filename); + return 0; + } + if (fwrite(webpdata->bytes, webpdata->size, 1, fout) != 1) { + WFPRINTF(stderr, "Error writing file %s!\n", (const W_CHAR*)filename); + } else { + WFPRINTF(stderr, "Saved file %s (%d bytes)\n", + (const W_CHAR*)filename, (int)webpdata->size); + ok = 1; + } + if (fout != stdout) fclose(fout); + return ok; +} + +static int WriteWebP(WebPMux* const mux, const char* filename) { + int ok; + WebPData webp_data; + const WebPMuxError err = WebPMuxAssemble(mux, &webp_data); + if (err != WEBP_MUX_OK) { + fprintf(stderr, "Error (%s) assembling the WebP file.\n", ErrorString(err)); + return 0; + } + ok = WriteData(filename, &webp_data); + WebPDataClear(&webp_data); + return ok; +} + +static WebPMux* DuplicateMuxHeader(const WebPMux* const mux) { + WebPMux* new_mux = WebPMuxNew(); + WebPMuxAnimParams p; + WebPMuxError err; + int i; + int ok = 1; + + if (new_mux == NULL) return NULL; + + err = WebPMuxGetAnimationParams(mux, &p); + if (err == WEBP_MUX_OK) { + err = WebPMuxSetAnimationParams(new_mux, &p); + if (err != WEBP_MUX_OK) { + ERROR_GOTO2("Error (%s) handling animation params.\n", + ErrorString(err), End); + } + } else { + /* it might not be an animation. Just keep moving. */ + } + + for (i = 1; i <= 3; ++i) { + WebPData metadata; + err = WebPMuxGetChunk(mux, kFourccList[i], &metadata); + if (err == WEBP_MUX_OK && metadata.size > 0) { + err = WebPMuxSetChunk(new_mux, kFourccList[i], &metadata, 1); + if (err != WEBP_MUX_OK) { + ERROR_GOTO1("Error transferring metadata in DuplicateMuxHeader().", + End); + } + } + } + + End: + if (!ok) { + WebPMuxDelete(new_mux); + new_mux = NULL; + } + return new_mux; +} + +static int ParseFrameArgs(const char* args, WebPMuxFrameInfo* const info) { + int dispose_method, unused; + char plus_minus, blend_method; + const int num_args = sscanf(args, "+%d+%d+%d+%d%c%c+%d", &info->duration, + &info->x_offset, &info->y_offset, &dispose_method, + &plus_minus, &blend_method, &unused); + switch (num_args) { + case 1: + info->x_offset = info->y_offset = 0; // fall through + case 3: + dispose_method = 0; // fall through + case 4: + plus_minus = '+'; + blend_method = 'b'; // fall through + case 6: + break; + case 2: + case 5: + default: + return 0; + } + + WarnAboutOddOffset(info); + + // Note: The validity of the following conversion is checked by + // WebPMuxPushFrame(). + info->dispose_method = (WebPMuxAnimDispose)dispose_method; + + if (blend_method != 'b') return 0; + if (plus_minus != '-' && plus_minus != '+') return 0; + info->blend_method = + (plus_minus == '+') ? WEBP_MUX_BLEND : WEBP_MUX_NO_BLEND; + return 1; +} + +static int ParseBgcolorArgs(const char* args, uint32_t* const bgcolor) { + uint32_t a, r, g, b; + if (sscanf(args, "%u,%u,%u,%u", &a, &r, &g, &b) != 4) return 0; + if (a >= 256 || r >= 256 || g >= 256 || b >= 256) return 0; + *bgcolor = (a << 24) | (r << 16) | (g << 8) | (b << 0); + return 1; +} + +//------------------------------------------------------------------------------ +// Clean-up. + +static void DeleteConfig(Config* const config) { + if (config != NULL) { + free(config->args_); + ExUtilDeleteCommandLineArguments(&config->cmd_args_); + memset(config, 0, sizeof(*config)); + } +} + +//------------------------------------------------------------------------------ +// Parsing. + +// Basic syntactic checks on the command-line arguments. +// Returns 1 on valid, 0 otherwise. +// Also fills up num_feature_args to be number of feature arguments given. +// (e.g. if there are 4 '-frame's and 1 '-loop', then num_feature_args = 5). +static int ValidateCommandLine(const CommandLineArguments* const cmd_args, + int* num_feature_args) { + int num_frame_args; + int num_loop_args; + int num_bgcolor_args; + int num_durations_args; + int ok = 1; + + assert(num_feature_args != NULL); + *num_feature_args = 0; + + // Simple checks. + if (CountOccurrences(cmd_args, "-get") > 1) { + ERROR_GOTO1("ERROR: Multiple '-get' arguments specified.\n", ErrValidate); + } + if (CountOccurrences(cmd_args, "-set") > 1) { + ERROR_GOTO1("ERROR: Multiple '-set' arguments specified.\n", ErrValidate); + } + if (CountOccurrences(cmd_args, "-strip") > 1) { + ERROR_GOTO1("ERROR: Multiple '-strip' arguments specified.\n", ErrValidate); + } + if (CountOccurrences(cmd_args, "-info") > 1) { + ERROR_GOTO1("ERROR: Multiple '-info' arguments specified.\n", ErrValidate); + } + if (CountOccurrences(cmd_args, "-o") > 1) { + ERROR_GOTO1("ERROR: Multiple output files specified.\n", ErrValidate); + } + + // Compound checks. + num_frame_args = CountOccurrences(cmd_args, "-frame"); + num_loop_args = CountOccurrences(cmd_args, "-loop"); + num_bgcolor_args = CountOccurrences(cmd_args, "-bgcolor"); + num_durations_args = CountOccurrences(cmd_args, "-duration"); + + if (num_loop_args > 1) { + ERROR_GOTO1("ERROR: Multiple loop counts specified.\n", ErrValidate); + } + if (num_bgcolor_args > 1) { + ERROR_GOTO1("ERROR: Multiple background colors specified.\n", ErrValidate); + } + + if ((num_frame_args == 0) && (num_loop_args + num_bgcolor_args > 0)) { + ERROR_GOTO1("ERROR: Loop count and background color are relevant only in " + "case of animation.\n", ErrValidate); + } + if (num_durations_args > 0 && num_frame_args != 0) { + ERROR_GOTO1("ERROR: Can not combine -duration and -frame commands.\n", + ErrValidate); + } + + assert(ok == 1); + if (num_durations_args > 0) { + *num_feature_args = num_durations_args; + } else if (num_frame_args == 0) { + // Single argument ('set' action for ICCP/EXIF/XMP, OR a 'get' action). + *num_feature_args = 1; + } else { + // Multiple arguments ('set' action for animation) + *num_feature_args = num_frame_args + num_loop_args + num_bgcolor_args; + } + + ErrValidate: + return ok; +} + +#define ACTION_IS_NIL (config->action_type_ == NIL_ACTION) + +#define FEATURETYPE_IS_NIL (config->type_ == NIL_FEATURE) + +#define CHECK_NUM_ARGS_AT_LEAST(NUM, LABEL) \ + if (argc < i + (NUM)) { \ + fprintf(stderr, "ERROR: Too few arguments for '%s'.\n", argv[i]); \ + goto LABEL; \ + } + +#define CHECK_NUM_ARGS_AT_MOST(NUM, LABEL) \ + if (argc > i + (NUM)) { \ + fprintf(stderr, "ERROR: Too many arguments for '%s'.\n", argv[i]); \ + goto LABEL; \ + } + +#define CHECK_NUM_ARGS_EXACTLY(NUM, LABEL) \ + CHECK_NUM_ARGS_AT_LEAST(NUM, LABEL); \ + CHECK_NUM_ARGS_AT_MOST(NUM, LABEL); + +// Parses command-line arguments to fill up config object. Also performs some +// semantic checks. unicode_argv contains wchar_t arguments or is null. +static int ParseCommandLine(Config* config, const W_CHAR** const unicode_argv) { + int i = 0; + int feature_arg_index = 0; + int ok = 1; + int argc = config->cmd_args_.argc_; + const char* const* argv = config->cmd_args_.argv_; + // Unicode file paths will be used if available. + const char* const* wargv = + (unicode_argv != NULL) ? (const char**)(unicode_argv + 1) : argv; + + while (i < argc) { + FeatureArg* const arg = &config->args_[feature_arg_index]; + if (argv[i][0] == '-') { // One of the action types or output. + if (!strcmp(argv[i], "-set")) { + if (ACTION_IS_NIL) { + config->action_type_ = ACTION_SET; + } else { + ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse); + } + ++i; + } else if (!strcmp(argv[i], "-duration")) { + CHECK_NUM_ARGS_AT_LEAST(2, ErrParse); + if (ACTION_IS_NIL || config->action_type_ == ACTION_DURATION) { + config->action_type_ = ACTION_DURATION; + } else { + ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse); + } + if (FEATURETYPE_IS_NIL || config->type_ == FEATURE_DURATION) { + config->type_ = FEATURE_DURATION; + } else { + ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse); + } + arg->params_ = argv[i + 1]; + ++feature_arg_index; + i += 2; + } else if (!strcmp(argv[i], "-get")) { + if (ACTION_IS_NIL) { + config->action_type_ = ACTION_GET; + } else { + ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse); + } + ++i; + } else if (!strcmp(argv[i], "-strip")) { + if (ACTION_IS_NIL) { + config->action_type_ = ACTION_STRIP; + config->arg_count_ = 0; + } else { + ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse); + } + ++i; + } else if (!strcmp(argv[i], "-frame")) { + CHECK_NUM_ARGS_AT_LEAST(3, ErrParse); + if (ACTION_IS_NIL || config->action_type_ == ACTION_SET) { + config->action_type_ = ACTION_SET; + } else { + ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse); + } + if (FEATURETYPE_IS_NIL || config->type_ == FEATURE_ANMF) { + config->type_ = FEATURE_ANMF; + } else { + ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse); + } + arg->subtype_ = SUBTYPE_ANMF; + arg->filename_ = wargv[i + 1]; + arg->params_ = argv[i + 2]; + ++feature_arg_index; + i += 3; + } else if (!strcmp(argv[i], "-loop") || !strcmp(argv[i], "-bgcolor")) { + CHECK_NUM_ARGS_AT_LEAST(2, ErrParse); + if (ACTION_IS_NIL || config->action_type_ == ACTION_SET) { + config->action_type_ = ACTION_SET; + } else { + ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse); + } + if (FEATURETYPE_IS_NIL || config->type_ == FEATURE_ANMF) { + config->type_ = FEATURE_ANMF; + } else { + ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse); + } + arg->subtype_ = + !strcmp(argv[i], "-loop") ? SUBTYPE_LOOP : SUBTYPE_BGCOLOR; + arg->params_ = argv[i + 1]; + ++feature_arg_index; + i += 2; + } else if (!strcmp(argv[i], "-o")) { + CHECK_NUM_ARGS_AT_LEAST(2, ErrParse); + config->output_ = wargv[i + 1]; + i += 2; + } else if (!strcmp(argv[i], "-info")) { + CHECK_NUM_ARGS_EXACTLY(2, ErrParse); + if (config->action_type_ != NIL_ACTION) { + ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse); + } else { + config->action_type_ = ACTION_INFO; + config->arg_count_ = 0; + config->input_ = wargv[i + 1]; + } + i += 2; + } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "-help")) { + PrintHelp(); + DeleteConfig(config); + LOCAL_FREE((W_CHAR** const)unicode_argv); + exit(0); + } else if (!strcmp(argv[i], "-version")) { + const int version = WebPGetMuxVersion(); + printf("%d.%d.%d\n", + (version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff); + DeleteConfig(config); + LOCAL_FREE((W_CHAR** const)unicode_argv); + exit(0); + } else if (!strcmp(argv[i], "--")) { + if (i < argc - 1) { + ++i; + if (config->input_ == NULL) { + config->input_ = wargv[i]; + } else { + ERROR_GOTO2("ERROR at '%s': Multiple input files specified.\n", + argv[i], ErrParse); + } + } + break; + } else { + ERROR_GOTO2("ERROR: Unknown option: '%s'.\n", argv[i], ErrParse); + } + } else { // One of the feature types or input. + if (ACTION_IS_NIL) { + ERROR_GOTO1("ERROR: Action must be specified before other arguments.\n", + ErrParse); + } + if (!strcmp(argv[i], "icc") || !strcmp(argv[i], "exif") || + !strcmp(argv[i], "xmp")) { + if (FEATURETYPE_IS_NIL) { + config->type_ = (!strcmp(argv[i], "icc")) ? FEATURE_ICCP : + (!strcmp(argv[i], "exif")) ? FEATURE_EXIF : FEATURE_XMP; + } else { + ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse); + } + if (config->action_type_ == ACTION_SET) { + CHECK_NUM_ARGS_AT_LEAST(2, ErrParse); + arg->filename_ = wargv[i + 1]; + ++feature_arg_index; + i += 2; + } else { + ++i; + } + } else if (!strcmp(argv[i], "frame") && + (config->action_type_ == ACTION_GET)) { + CHECK_NUM_ARGS_AT_LEAST(2, ErrParse); + config->type_ = FEATURE_ANMF; + arg->params_ = argv[i + 1]; + ++feature_arg_index; + i += 2; + } else if (!strcmp(argv[i], "loop") && + (config->action_type_ == ACTION_SET)) { + CHECK_NUM_ARGS_AT_LEAST(2, ErrParse); + config->type_ = FEATURE_LOOP; + arg->params_ = argv[i + 1]; + ++feature_arg_index; + i += 2; + } else if (!strcmp(argv[i], "bgcolor") && + (config->action_type_ == ACTION_SET)) { + CHECK_NUM_ARGS_AT_LEAST(2, ErrParse); + config->type_ = FEATURE_BGCOLOR; + arg->params_ = argv[i + 1]; + ++feature_arg_index; + i += 2; + } else { // Assume input file. + if (config->input_ == NULL) { + config->input_ = wargv[i]; + } else { + ERROR_GOTO2("ERROR at '%s': Multiple input files specified.\n", + argv[i], ErrParse); + } + ++i; + } + } + } + ErrParse: + return ok; +} + +// Additional checks after config is filled. +static int ValidateConfig(Config* const config) { + int ok = 1; + + // Action. + if (ACTION_IS_NIL) { + ERROR_GOTO1("ERROR: No action specified.\n", ErrValidate2); + } + + // Feature type. + if (FEATURETYPE_IS_NIL && config->action_type_ != ACTION_INFO) { + ERROR_GOTO1("ERROR: No feature specified.\n", ErrValidate2); + } + + // Input file. + if (config->input_ == NULL) { + if (config->action_type_ != ACTION_SET) { + ERROR_GOTO1("ERROR: No input file specified.\n", ErrValidate2); + } else if (config->type_ != FEATURE_ANMF) { + ERROR_GOTO1("ERROR: No input file specified.\n", ErrValidate2); + } + } + + // Output file. + if (config->output_ == NULL && config->action_type_ != ACTION_INFO) { + ERROR_GOTO1("ERROR: No output file specified.\n", ErrValidate2); + } + + ErrValidate2: + return ok; +} + +// Create config object from command-line arguments. +static int InitializeConfig(int argc, const char* argv[], Config* const config, + const W_CHAR** const unicode_argv) { + int num_feature_args = 0; + int ok; + + memset(config, 0, sizeof(*config)); + + ok = ExUtilInitCommandLineArguments(argc, argv, &config->cmd_args_); + if (!ok) return 0; + + // Validate command-line arguments. + if (!ValidateCommandLine(&config->cmd_args_, &num_feature_args)) { + ERROR_GOTO1("Exiting due to command-line parsing error.\n", Err1); + } + + config->arg_count_ = num_feature_args; + config->args_ = (FeatureArg*)calloc(num_feature_args, sizeof(*config->args_)); + if (config->args_ == NULL) { + ERROR_GOTO1("ERROR: Memory allocation error.\n", Err1); + } + + // Parse command-line. + if (!ParseCommandLine(config, unicode_argv) || !ValidateConfig(config)) { + ERROR_GOTO1("Exiting due to command-line parsing error.\n", Err1); + } + + Err1: + return ok; +} + +#undef ACTION_IS_NIL +#undef FEATURETYPE_IS_NIL +#undef CHECK_NUM_ARGS_AT_LEAST +#undef CHECK_NUM_ARGS_AT_MOST +#undef CHECK_NUM_ARGS_EXACTLY + +//------------------------------------------------------------------------------ +// Processing. + +static int GetFrame(const WebPMux* mux, const Config* config) { + WebPMuxError err = WEBP_MUX_OK; + WebPMux* mux_single = NULL; + int num = 0; + int ok = 1; + int parse_error = 0; + const WebPChunkId id = WEBP_CHUNK_ANMF; + WebPMuxFrameInfo info; + WebPDataInit(&info.bitstream); + + num = ExUtilGetInt(config->args_[0].params_, 10, &parse_error); + if (num < 0) { + ERROR_GOTO1("ERROR: Frame/Fragment index must be non-negative.\n", ErrGet); + } + if (parse_error) goto ErrGet; + + err = WebPMuxGetFrame(mux, num, &info); + if (err == WEBP_MUX_OK && info.id != id) err = WEBP_MUX_NOT_FOUND; + if (err != WEBP_MUX_OK) { + ERROR_GOTO3("ERROR (%s): Could not get frame %d.\n", + ErrorString(err), num, ErrGet); + } + + mux_single = WebPMuxNew(); + if (mux_single == NULL) { + err = WEBP_MUX_MEMORY_ERROR; + ERROR_GOTO2("ERROR (%s): Could not allocate a mux object.\n", + ErrorString(err), ErrGet); + } + err = WebPMuxSetImage(mux_single, &info.bitstream, 1); + if (err != WEBP_MUX_OK) { + ERROR_GOTO2("ERROR (%s): Could not create single image mux object.\n", + ErrorString(err), ErrGet); + } + + ok = WriteWebP(mux_single, config->output_); + + ErrGet: + WebPDataClear(&info.bitstream); + WebPMuxDelete(mux_single); + return ok && !parse_error; +} + +// Read and process config. +static int Process(const Config* config) { + WebPMux* mux = NULL; + WebPData chunk; + WebPMuxError err = WEBP_MUX_OK; + int ok = 1; + + switch (config->action_type_) { + case ACTION_GET: { + ok = CreateMux(config->input_, &mux); + if (!ok) goto Err2; + switch (config->type_) { + case FEATURE_ANMF: + ok = GetFrame(mux, config); + break; + + case FEATURE_ICCP: + case FEATURE_EXIF: + case FEATURE_XMP: + err = WebPMuxGetChunk(mux, kFourccList[config->type_], &chunk); + if (err != WEBP_MUX_OK) { + ERROR_GOTO3("ERROR (%s): Could not get the %s.\n", + ErrorString(err), kDescriptions[config->type_], Err2); + } + ok = WriteData(config->output_, &chunk); + break; + + default: + ERROR_GOTO1("ERROR: Invalid feature for action 'get'.\n", Err2); + break; + } + break; + } + case ACTION_SET: { + switch (config->type_) { + case FEATURE_ANMF: { + int i; + WebPMuxAnimParams params = { 0xFFFFFFFF, 0 }; + mux = WebPMuxNew(); + if (mux == NULL) { + ERROR_GOTO2("ERROR (%s): Could not allocate a mux object.\n", + ErrorString(WEBP_MUX_MEMORY_ERROR), Err2); + } + for (i = 0; i < config->arg_count_; ++i) { + switch (config->args_[i].subtype_) { + case SUBTYPE_BGCOLOR: { + uint32_t bgcolor; + ok = ParseBgcolorArgs(config->args_[i].params_, &bgcolor); + if (!ok) { + ERROR_GOTO1("ERROR: Could not parse the background color \n", + Err2); + } + params.bgcolor = bgcolor; + break; + } + case SUBTYPE_LOOP: { + int parse_error = 0; + const int loop_count = + ExUtilGetInt(config->args_[i].params_, 10, &parse_error); + if (loop_count < 0 || loop_count > 65535) { + // Note: This is only a 'necessary' condition for loop_count + // to be valid. The 'sufficient' conditioned in checked in + // WebPMuxSetAnimationParams() method called later. + ERROR_GOTO1("ERROR: Loop count must be in the range 0 to " + "65535.\n", Err2); + } + ok = !parse_error; + if (!ok) goto Err2; + params.loop_count = loop_count; + break; + } + case SUBTYPE_ANMF: { + WebPMuxFrameInfo frame; + frame.id = WEBP_CHUNK_ANMF; + ok = ExUtilReadFileToWebPData(config->args_[i].filename_, + &frame.bitstream); + if (!ok) goto Err2; + ok = ParseFrameArgs(config->args_[i].params_, &frame); + if (!ok) { + WebPDataClear(&frame.bitstream); + ERROR_GOTO1("ERROR: Could not parse frame properties.\n", + Err2); + } + err = WebPMuxPushFrame(mux, &frame, 1); + WebPDataClear(&frame.bitstream); + if (err != WEBP_MUX_OK) { + ERROR_GOTO3("ERROR (%s): Could not add a frame at index %d." + "\n", ErrorString(err), i, Err2); + } + break; + } + default: { + ERROR_GOTO1("ERROR: Invalid subtype for 'frame'", Err2); + break; + } + } + } + err = WebPMuxSetAnimationParams(mux, ¶ms); + if (err != WEBP_MUX_OK) { + ERROR_GOTO2("ERROR (%s): Could not set animation parameters.\n", + ErrorString(err), Err2); + } + break; + } + + case FEATURE_ICCP: + case FEATURE_EXIF: + case FEATURE_XMP: { + ok = CreateMux(config->input_, &mux); + if (!ok) goto Err2; + ok = ExUtilReadFileToWebPData(config->args_[0].filename_, &chunk); + if (!ok) goto Err2; + err = WebPMuxSetChunk(mux, kFourccList[config->type_], &chunk, 1); + WebPDataClear(&chunk); + if (err != WEBP_MUX_OK) { + ERROR_GOTO3("ERROR (%s): Could not set the %s.\n", + ErrorString(err), kDescriptions[config->type_], Err2); + } + break; + } + case FEATURE_LOOP: { + WebPMuxAnimParams params = { 0xFFFFFFFF, 0 }; + int parse_error = 0; + const int loop_count = + ExUtilGetInt(config->args_[0].params_, 10, &parse_error); + if (loop_count < 0 || loop_count > 65535 || parse_error) { + ERROR_GOTO1("ERROR: Loop count must be in the range 0 to 65535.\n", + Err2); + } + ok = CreateMux(config->input_, &mux); + if (!ok) goto Err2; + ok = (WebPMuxGetAnimationParams(mux, ¶ms) == WEBP_MUX_OK); + if (!ok) { + ERROR_GOTO1("ERROR: input file does not seem to be an animation.\n", + Err2); + } + params.loop_count = loop_count; + err = WebPMuxSetAnimationParams(mux, ¶ms); + ok = (err == WEBP_MUX_OK); + if (!ok) { + ERROR_GOTO2("ERROR (%s): Could not set animation parameters.\n", + ErrorString(err), Err2); + } + break; + } + case FEATURE_BGCOLOR: { + WebPMuxAnimParams params = { 0xFFFFFFFF, 0 }; + uint32_t bgcolor; + ok = ParseBgcolorArgs(config->args_[0].params_, &bgcolor); + if (!ok) { + ERROR_GOTO1("ERROR: Could not parse the background color.\n", + Err2); + } + ok = CreateMux(config->input_, &mux); + if (!ok) goto Err2; + ok = (WebPMuxGetAnimationParams(mux, ¶ms) == WEBP_MUX_OK); + if (!ok) { + ERROR_GOTO1("ERROR: input file does not seem to be an animation.\n", + Err2); + } + params.bgcolor = bgcolor; + err = WebPMuxSetAnimationParams(mux, ¶ms); + ok = (err == WEBP_MUX_OK); + if (!ok) { + ERROR_GOTO2("ERROR (%s): Could not set animation parameters.\n", + ErrorString(err), Err2); + } + break; + } + default: { + ERROR_GOTO1("ERROR: Invalid feature for action 'set'.\n", Err2); + break; + } + } + ok = WriteWebP(mux, config->output_); + break; + } + case ACTION_DURATION: { + int num_frames; + ok = CreateMux(config->input_, &mux); + if (!ok) goto Err2; + err = WebPMuxNumChunks(mux, WEBP_CHUNK_ANMF, &num_frames); + ok = (err == WEBP_MUX_OK); + if (!ok) { + ERROR_GOTO1("ERROR: can not parse the number of frames.\n", Err2); + } + if (num_frames == 0) { + fprintf(stderr, "Doesn't look like the source is animated. " + "Skipping duration setting.\n"); + ok = WriteWebP(mux, config->output_); + if (!ok) goto Err2; + } else { + int i; + int* durations = NULL; + WebPMux* new_mux = DuplicateMuxHeader(mux); + if (new_mux == NULL) goto Err2; + durations = (int*)WebPMalloc((size_t)num_frames * sizeof(*durations)); + if (durations == NULL) goto Err2; + for (i = 0; i < num_frames; ++i) durations[i] = -1; + + // Parse intervals to process. + for (i = 0; i < config->arg_count_; ++i) { + int k; + int args[3]; + int duration, start, end; + const int nb_args = ExUtilGetInts(config->args_[i].params_, + 10, 3, args); + ok = (nb_args >= 1); + if (!ok) goto Err3; + duration = args[0]; + if (duration < 0) { + ERROR_GOTO1("ERROR: duration must be strictly positive.\n", Err3); + } + + if (nb_args == 1) { // only duration is present -> use full interval + start = 1; + end = num_frames; + } else { + start = args[1]; + if (start <= 0) { + start = 1; + } else if (start > num_frames) { + start = num_frames; + } + end = (nb_args >= 3) ? args[2] : start; + if (end == 0 || end > num_frames) end = num_frames; + } + + for (k = start; k <= end; ++k) { + assert(k >= 1 && k <= num_frames); + durations[k - 1] = duration; + } + } + + // Apply non-negative durations to their destination frames. + for (i = 1; i <= num_frames; ++i) { + WebPMuxFrameInfo frame; + err = WebPMuxGetFrame(mux, i, &frame); + if (err != WEBP_MUX_OK || frame.id != WEBP_CHUNK_ANMF) { + ERROR_GOTO2("ERROR: can not retrieve frame #%d.\n", i, Err3); + } + if (durations[i - 1] >= 0) frame.duration = durations[i - 1]; + err = WebPMuxPushFrame(new_mux, &frame, 1); + if (err != WEBP_MUX_OK) { + ERROR_GOTO2("ERROR: error push frame data #%d\n", i, Err3); + } + WebPDataClear(&frame.bitstream); + } + WebPMuxDelete(mux); + ok = WriteWebP(new_mux, config->output_); + mux = new_mux; // transfer for the WebPMuxDelete() call + new_mux = NULL; + + Err3: + WebPFree(durations); + WebPMuxDelete(new_mux); + if (!ok) goto Err2; + } + break; + } + case ACTION_STRIP: { + ok = CreateMux(config->input_, &mux); + if (!ok) goto Err2; + if (config->type_ == FEATURE_ICCP || config->type_ == FEATURE_EXIF || + config->type_ == FEATURE_XMP) { + err = WebPMuxDeleteChunk(mux, kFourccList[config->type_]); + if (err != WEBP_MUX_OK) { + ERROR_GOTO3("ERROR (%s): Could not strip the %s.\n", + ErrorString(err), kDescriptions[config->type_], Err2); + } + } else { + ERROR_GOTO1("ERROR: Invalid feature for action 'strip'.\n", Err2); + break; + } + ok = WriteWebP(mux, config->output_); + break; + } + case ACTION_INFO: { + ok = CreateMux(config->input_, &mux); + if (!ok) goto Err2; + ok = (DisplayInfo(mux) == WEBP_MUX_OK); + break; + } + default: { + assert(0); // Invalid action. + break; + } + } + + Err2: + WebPMuxDelete(mux); + return ok; +} + +//------------------------------------------------------------------------------ +// Main. + +int main(int argc, const char* argv[]) { + Config config; + int ok; + + INIT_WARGV(argc, argv); + + ok = InitializeConfig(argc - 1, argv + 1, &config, GET_WARGV_OR_NULL()); + if (ok) { + ok = Process(&config); + } else { + PrintHelp(); + } + DeleteConfig(&config); + FREE_WARGV_AND_RETURN(!ok); +} + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/extras/Makefile.am b/third-party/webp/libwebp/extras/Makefile.am new file mode 100644 index 0000000000..7e29888be2 --- /dev/null +++ b/third-party/webp/libwebp/extras/Makefile.am @@ -0,0 +1,44 @@ +AM_CPPFLAGS += -I$(top_builddir) -I$(top_srcdir) +AM_CPPFLAGS += -I$(top_builddir)/src -I$(top_srcdir)/src +noinst_LTLIBRARIES = libwebpextras.la + +noinst_HEADERS = +noinst_HEADERS += ../src/webp/types.h + +libwebpextras_la_SOURCES = +libwebpextras_la_SOURCES += extras.c extras.h quality_estimate.c + +libwebpextras_la_CPPFLAGS = $(AM_CPPFLAGS) +libwebpextras_la_LDFLAGS = -lm +libwebpextras_la_LIBADD = ../src/libwebp.la + +noinst_PROGRAMS = +noinst_PROGRAMS += webp_quality +if BUILD_DEMUX + noinst_PROGRAMS += get_disto +endif +if BUILD_VWEBP_SDL + noinst_PROGRAMS += vwebp_sdl +endif + +get_disto_SOURCES = get_disto.c +get_disto_CPPFLAGS = $(AM_CPPFLAGS) +get_disto_LDADD = +get_disto_LDADD += ../imageio/libimageio_util.la +get_disto_LDADD += ../imageio/libimagedec.la +get_disto_LDADD += ../src/libwebp.la +get_disto_LDADD += $(PNG_LIBS) $(JPEG_LIBS) $(TIFF_LIBS) + +webp_quality_SOURCES = webp_quality.c +webp_quality_CPPFLAGS = $(AM_CPPFLAGS) +webp_quality_LDADD = +webp_quality_LDADD += ../imageio/libimageio_util.la +webp_quality_LDADD += libwebpextras.la +webp_quality_LDADD += ../src/libwebp.la + +vwebp_sdl_SOURCES = vwebp_sdl.c webp_to_sdl.c webp_to_sdl.h +vwebp_sdl_CPPFLAGS = $(AM_CPPFLAGS) $(SDL_INCLUDES) +vwebp_sdl_LDADD = +vwebp_sdl_LDADD += ../imageio/libimageio_util.la +vwebp_sdl_LDADD += ../src/libwebp.la +vwebp_sdl_LDADD += $(SDL_LIBS) diff --git a/third-party/webp/libwebp/extras/extras.c b/third-party/webp/libwebp/extras/extras.c new file mode 100644 index 0000000000..afe5b70456 --- /dev/null +++ b/third-party/webp/libwebp/extras/extras.c @@ -0,0 +1,162 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Additional WebP utilities. +// + +#include "extras/extras.h" +#include "webp/format_constants.h" +#include "src/dsp/dsp.h" + +#include +#include + +#define XTRA_MAJ_VERSION 1 +#define XTRA_MIN_VERSION 3 +#define XTRA_REV_VERSION 2 + +//------------------------------------------------------------------------------ + +int WebPGetExtrasVersion(void) { + return (XTRA_MAJ_VERSION << 16) | (XTRA_MIN_VERSION << 8) | XTRA_REV_VERSION; +} + +//------------------------------------------------------------------------------ + +int WebPImportGray(const uint8_t* gray_data, WebPPicture* pic) { + int y, width, uv_width; + if (pic == NULL || gray_data == NULL) return 0; + pic->colorspace = WEBP_YUV420; + if (!WebPPictureAlloc(pic)) return 0; + width = pic->width; + uv_width = (width + 1) >> 1; + for (y = 0; y < pic->height; ++y) { + memcpy(pic->y + y * pic->y_stride, gray_data, width); + gray_data += width; // <- we could use some 'data_stride' here if needed + if ((y & 1) == 0) { + memset(pic->u + (y >> 1) * pic->uv_stride, 128, uv_width); + memset(pic->v + (y >> 1) * pic->uv_stride, 128, uv_width); + } + } + return 1; +} + +int WebPImportRGB565(const uint8_t* rgb565, WebPPicture* pic) { + int x, y; + uint32_t* dst; + if (pic == NULL || rgb565 == NULL) return 0; + pic->colorspace = WEBP_YUV420; + pic->use_argb = 1; + if (!WebPPictureAlloc(pic)) return 0; + dst = pic->argb; + for (y = 0; y < pic->height; ++y) { + const int width = pic->width; + for (x = 0; x < width; ++x) { +#if defined(WEBP_SWAP_16BIT_CSP) && (WEBP_SWAP_16BIT_CSP == 1) + const uint32_t rg = rgb565[2 * x + 1]; + const uint32_t gb = rgb565[2 * x + 0]; +#else + const uint32_t rg = rgb565[2 * x + 0]; + const uint32_t gb = rgb565[2 * x + 1]; +#endif + uint32_t r = rg & 0xf8; + uint32_t g = ((rg << 5) | (gb >> 3)) & 0xfc; + uint32_t b = (gb << 5); + // dithering + r = r | (r >> 5); + g = g | (g >> 6); + b = b | (b >> 5); + dst[x] = (0xffu << 24) | (r << 16) | (g << 8) | b; + } + rgb565 += 2 * width; + dst += pic->argb_stride; + } + return 1; +} + +int WebPImportRGB4444(const uint8_t* rgb4444, WebPPicture* pic) { + int x, y; + uint32_t* dst; + if (pic == NULL || rgb4444 == NULL) return 0; + pic->colorspace = WEBP_YUV420; + pic->use_argb = 1; + if (!WebPPictureAlloc(pic)) return 0; + dst = pic->argb; + for (y = 0; y < pic->height; ++y) { + const int width = pic->width; + for (x = 0; x < width; ++x) { +#if defined(WEBP_SWAP_16BIT_CSP) && (WEBP_SWAP_16BIT_CSP == 1) + const uint32_t rg = rgb4444[2 * x + 1]; + const uint32_t ba = rgb4444[2 * x + 0]; +#else + const uint32_t rg = rgb4444[2 * x + 0]; + const uint32_t ba = rgb4444[2 * x + 1]; +#endif + uint32_t r = rg & 0xf0; + uint32_t g = (rg << 4); + uint32_t b = (ba & 0xf0); + uint32_t a = (ba << 4); + // dithering + r = r | (r >> 4); + g = g | (g >> 4); + b = b | (b >> 4); + a = a | (a >> 4); + dst[x] = (a << 24) | (r << 16) | (g << 8) | b; + } + rgb4444 += 2 * width; + dst += pic->argb_stride; + } + return 1; +} + +int WebPImportColorMappedARGB(const uint8_t* indexed, int indexed_stride, + const uint32_t palette[], int palette_size, + WebPPicture* pic) { + int x, y; + uint32_t* dst; + // 256 as the input buffer is uint8_t. + assert(MAX_PALETTE_SIZE <= 256); + if (pic == NULL || indexed == NULL || indexed_stride < pic->width || + palette == NULL || palette_size > MAX_PALETTE_SIZE || palette_size <= 0) { + return 0; + } + pic->use_argb = 1; + if (!WebPPictureAlloc(pic)) return 0; + dst = pic->argb; + for (y = 0; y < pic->height; ++y) { + for (x = 0; x < pic->width; ++x) { + // Make sure we are within the palette. + if (indexed[x] >= palette_size) { + WebPPictureFree(pic); + return 0; + } + dst[x] = palette[indexed[x]]; + } + indexed += indexed_stride; + dst += pic->argb_stride; + } + return 1; +} + +//------------------------------------------------------------------------------ + +int WebPUnmultiplyARGB(WebPPicture* pic) { + int y; + uint32_t* dst; + if (pic == NULL || pic->use_argb != 1 || pic->argb == NULL) return 0; + WebPInitAlphaProcessing(); + dst = pic->argb; + for (y = 0; y < pic->height; ++y) { + WebPMultARGBRow(dst, pic->width, /*inverse=*/1); + dst += pic->argb_stride; + } + return 1; +} + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/extras/extras.h b/third-party/webp/libwebp/extras/extras.h new file mode 100644 index 0000000000..c084682ffc --- /dev/null +++ b/third-party/webp/libwebp/extras/extras.h @@ -0,0 +1,77 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// + +#ifndef WEBP_EXTRAS_EXTRAS_H_ +#define WEBP_EXTRAS_EXTRAS_H_ + +#include "webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "webp/encode.h" + +#define WEBP_EXTRAS_ABI_VERSION 0x0002 // MAJOR(8b) + MINOR(8b) + +//------------------------------------------------------------------------------ + +// Returns the version number of the extras library, packed in hexadecimal using +// 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507. +WEBP_EXTERN int WebPGetExtrasVersion(void); + +//------------------------------------------------------------------------------ +// Ad-hoc colorspace importers. + +// Import luma sample (gray scale image) into 'picture'. The 'picture' +// width and height must be set prior to calling this function. +WEBP_EXTERN int WebPImportGray(const uint8_t* gray, WebPPicture* picture); + +// Import rgb sample in RGB565 packed format into 'picture'. The 'picture' +// width and height must be set prior to calling this function. +WEBP_EXTERN int WebPImportRGB565(const uint8_t* rgb565, WebPPicture* pic); + +// Import rgb sample in RGB4444 packed format into 'picture'. The 'picture' +// width and height must be set prior to calling this function. +WEBP_EXTERN int WebPImportRGB4444(const uint8_t* rgb4444, WebPPicture* pic); + +// Import a color mapped image. The number of colors is less or equal to +// MAX_PALETTE_SIZE. 'pic' must have been initialized. Its content, if any, +// will be discarded. Returns 'false' in case of error, or if indexed[] contains +// invalid indices. +WEBP_EXTERN int +WebPImportColorMappedARGB(const uint8_t* indexed, int indexed_stride, + const uint32_t palette[], int palette_size, + WebPPicture* pic); + +// Convert the ARGB content of 'pic' from associated to unassociated. +// 'pic' can be for instance the result of calling of some WebPPictureImportXXX +// functions, with pic->use_argb set to 'true'. It is assumed (and not checked) +// that the pre-multiplied r/g/b values as less or equal than the alpha value. +// Return false in case of error (invalid parameter, ...). +WEBP_EXTERN int WebPUnmultiplyARGB(WebPPicture* pic); + +//------------------------------------------------------------------------------ + +// Parse a bitstream, search for VP8 (lossy) header and report a +// rough estimation of the quality factor used for compressing the bitstream. +// If the bitstream is in lossless format, the special value '101' is returned. +// Otherwise (lossy bitstream), the returned value is in the range [0..100]. +// Any error (invalid bitstream, animated WebP, incomplete header, etc.) +// will return a value of -1. +WEBP_EXTERN int VP8EstimateQuality(const uint8_t* const data, size_t size); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_EXTRAS_EXTRAS_H_ diff --git a/third-party/webp/libwebp/extras/get_disto.c b/third-party/webp/libwebp/extras/get_disto.c new file mode 100644 index 0000000000..3aa345bbbc --- /dev/null +++ b/third-party/webp/libwebp/extras/get_disto.c @@ -0,0 +1,356 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Simple tool to load two webp/png/jpg/tiff files and compute PSNR/SSIM. +// This is mostly a wrapper around WebPPictureDistortion(). +// +/* + gcc -o get_disto get_disto.c -O3 -I../ -L../examples -L../imageio \ + -lexample_util -limageio_util -limagedec -lwebp -L/opt/local/lib \ + -lpng -lz -ljpeg -ltiff -lm -lpthread +*/ +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include +#include +#include + +#include "webp/encode.h" +#include "imageio/image_dec.h" +#include "imageio/imageio_util.h" +#include "../examples/unicode.h" + +static size_t ReadPicture(const char* const filename, WebPPicture* const pic, + int keep_alpha) { + const uint8_t* data = NULL; + size_t data_size = 0; + WebPImageReader reader = NULL; + int ok = ImgIoUtilReadFile(filename, &data, &data_size); + if (!ok) goto End; + + pic->use_argb = 1; // force ARGB + +#ifdef HAVE_WINCODEC_H + // Try to decode the file using WIC falling back to the other readers for + // e.g., WebP. + ok = ReadPictureWithWIC(filename, pic, keep_alpha, NULL); + if (ok) goto End; +#endif + reader = WebPGuessImageReader(data, data_size); + ok = reader(data, data_size, pic, keep_alpha, NULL); + + End: + if (!ok) { + WFPRINTF(stderr, "Error! Could not process file %s\n", + (const W_CHAR*)filename); + } + free((void*)data); + return ok ? data_size : 0; +} + +static void RescalePlane(uint8_t* plane, int width, int height, + int x_stride, int y_stride, int max) { + const uint32_t factor = (max > 0) ? (255u << 16) / max : 0; + int x, y; + for (y = 0; y < height; ++y) { + uint8_t* const ptr = plane + y * y_stride; + for (x = 0; x < width * x_stride; x += x_stride) { + const uint32_t diff = (ptr[x] * factor + (1 << 15)) >> 16; + ptr[x] = diff; + } + } +} + +// Return the max absolute difference. +static int DiffScaleChannel(uint8_t* src1, int stride1, + const uint8_t* src2, int stride2, + int x_stride, int w, int h, int do_scaling) { + int x, y; + int max = 0; + for (y = 0; y < h; ++y) { + uint8_t* const ptr1 = src1 + y * stride1; + const uint8_t* const ptr2 = src2 + y * stride2; + for (x = 0; x < w * x_stride; x += x_stride) { + const int diff = abs(ptr1[x] - ptr2[x]); + if (diff > max) max = diff; + ptr1[x] = diff; + } + } + + if (do_scaling) RescalePlane(src1, w, h, x_stride, stride1, max); + return max; +} + +//------------------------------------------------------------------------------ +// SSIM calculation. We re-implement these functions here, out of dsp/, to avoid +// breaking the library's hidden visibility. This code duplication avoids the +// bigger annoyance of having to open up internal details of libdsp... + +#define SSIM_KERNEL 3 // total size of the kernel: 2 * SSIM_KERNEL + 1 + +// struct for accumulating statistical moments +typedef struct { + uint32_t w; // sum(w_i) : sum of weights + uint32_t xm, ym; // sum(w_i * x_i), sum(w_i * y_i) + uint32_t xxm, xym, yym; // sum(w_i * x_i * x_i), etc. +} DistoStats; + +// hat-shaped filter. Sum of coefficients is equal to 16. +static const uint32_t kWeight[2 * SSIM_KERNEL + 1] = { 1, 2, 3, 4, 3, 2, 1 }; + +static WEBP_INLINE double SSIMCalculation(const DistoStats* const stats) { + const uint32_t N = stats->w; + const uint32_t w2 = N * N; + const uint32_t C1 = 20 * w2; + const uint32_t C2 = 60 * w2; + const uint32_t C3 = 8 * 8 * w2; // 'dark' limit ~= 6 + const uint64_t xmxm = (uint64_t)stats->xm * stats->xm; + const uint64_t ymym = (uint64_t)stats->ym * stats->ym; + if (xmxm + ymym >= C3) { + const int64_t xmym = (int64_t)stats->xm * stats->ym; + const int64_t sxy = (int64_t)stats->xym * N - xmym; // can be negative + const uint64_t sxx = (uint64_t)stats->xxm * N - xmxm; + const uint64_t syy = (uint64_t)stats->yym * N - ymym; + // we descale by 8 to prevent overflow during the fnum/fden multiply. + const uint64_t num_S = (2 * (uint64_t)(sxy < 0 ? 0 : sxy) + C2) >> 8; + const uint64_t den_S = (sxx + syy + C2) >> 8; + const uint64_t fnum = (2 * xmym + C1) * num_S; + const uint64_t fden = (xmxm + ymym + C1) * den_S; + const double r = (double)fnum / fden; + assert(r >= 0. && r <= 1.0); + return r; + } + return 1.; // area is too dark to contribute meaningfully +} + +static double SSIMGetClipped(const uint8_t* src1, int stride1, + const uint8_t* src2, int stride2, + int xo, int yo, int W, int H) { + DistoStats stats = { 0, 0, 0, 0, 0, 0 }; + const int ymin = (yo - SSIM_KERNEL < 0) ? 0 : yo - SSIM_KERNEL; + const int ymax = (yo + SSIM_KERNEL > H - 1) ? H - 1 : yo + SSIM_KERNEL; + const int xmin = (xo - SSIM_KERNEL < 0) ? 0 : xo - SSIM_KERNEL; + const int xmax = (xo + SSIM_KERNEL > W - 1) ? W - 1 : xo + SSIM_KERNEL; + int x, y; + src1 += ymin * stride1; + src2 += ymin * stride2; + for (y = ymin; y <= ymax; ++y, src1 += stride1, src2 += stride2) { + for (x = xmin; x <= xmax; ++x) { + const uint32_t w = kWeight[SSIM_KERNEL + x - xo] + * kWeight[SSIM_KERNEL + y - yo]; + const uint32_t s1 = src1[x]; + const uint32_t s2 = src2[x]; + stats.w += w; + stats.xm += w * s1; + stats.ym += w * s2; + stats.xxm += w * s1 * s1; + stats.xym += w * s1 * s2; + stats.yym += w * s2 * s2; + } + } + return SSIMCalculation(&stats); +} + +// Compute SSIM-score map. Return -1 in case of error, max diff otherwise. +static int SSIMScaleChannel(uint8_t* src1, int stride1, + const uint8_t* src2, int stride2, + int x_stride, int w, int h, int do_scaling) { + int x, y; + int max = 0; + uint8_t* const plane1 = (uint8_t*)malloc(2 * w * h * sizeof(*plane1)); + uint8_t* const plane2 = plane1 + w * h; + if (plane1 == NULL) return -1; + + // extract plane + for (y = 0; y < h; ++y) { + for (x = 0; x < w; ++x) { + plane1[x + y * w] = src1[x * x_stride + y * stride1]; + plane2[x + y * w] = src2[x * x_stride + y * stride2]; + } + } + for (y = 0; y < h; ++y) { + for (x = 0; x < w; ++x) { + const double ssim = SSIMGetClipped(plane1, w, plane2, w, x, y, w, h); + int diff = (int)(255 * (1. - ssim)); + if (diff < 0) { + diff = 0; + } else if (diff > max) { + max = diff; + } + src1[x * x_stride + y * stride1] = (diff > 255) ? 255u : (uint8_t)diff; + } + } + free(plane1); + + if (do_scaling) RescalePlane(src1, w, h, x_stride, stride1, max); + return max; +} + +// Convert an argb picture to luminance. +static void ConvertToGray(WebPPicture* const pic) { + int x, y; + assert(pic != NULL); + assert(pic->use_argb); + for (y = 0; y < pic->height; ++y) { + uint32_t* const row = &pic->argb[y * pic->argb_stride]; + for (x = 0; x < pic->width; ++x) { + const uint32_t argb = row[x]; + const uint32_t r = (argb >> 16) & 0xff; + const uint32_t g = (argb >> 8) & 0xff; + const uint32_t b = (argb >> 0) & 0xff; + // We use BT.709 for converting to luminance. + const uint32_t Y = (uint32_t)(0.2126 * r + 0.7152 * g + 0.0722 * b + .5); + row[x] = (argb & 0xff000000u) | (Y * 0x010101u); + } + } +} + +static void Help(void) { + fprintf(stderr, + "Usage: get_disto [-ssim][-psnr][-alpha] compressed.webp orig.webp\n" + " -ssim ..... print SSIM distortion\n" + " -psnr ..... print PSNR distortion (default)\n" + " -alpha .... preserve alpha plane\n" + " -h ........ this message\n" + " -o . save the diff map as a WebP lossless file\n" + " -scale .... scale the difference map to fit [0..255] range\n" + " -gray ..... use grayscale for difference map (-scale)\n" + "\nSupported input formats:\n %s\n", + WebPGetEnabledInputFileFormats()); +} + +int main(int argc, const char* argv[]) { + WebPPicture pic1, pic2; + size_t size1 = 0, size2 = 0; + int ret = 1; + float disto[5]; + int type = 0; + int c; + int help = 0; + int keep_alpha = 0; + int scale = 0; + int use_gray = 0; + const char* name1 = NULL; + const char* name2 = NULL; + const char* output = NULL; + + INIT_WARGV(argc, argv); + + if (!WebPPictureInit(&pic1) || !WebPPictureInit(&pic2)) { + fprintf(stderr, "Can't init pictures\n"); + FREE_WARGV_AND_RETURN(1); + } + + for (c = 1; c < argc; ++c) { + if (!strcmp(argv[c], "-ssim")) { + type = 1; + } else if (!strcmp(argv[c], "-psnr")) { + type = 0; + } else if (!strcmp(argv[c], "-alpha")) { + keep_alpha = 1; + } else if (!strcmp(argv[c], "-scale")) { + scale = 1; + } else if (!strcmp(argv[c], "-gray")) { + use_gray = 1; + } else if (!strcmp(argv[c], "-h")) { + help = 1; + ret = 0; + } else if (!strcmp(argv[c], "-o")) { + if (++c == argc) { + fprintf(stderr, "missing file name after %s option.\n", argv[c - 1]); + goto End; + } + output = (const char*)GET_WARGV(argv, c); + } else if (name1 == NULL) { + name1 = (const char*)GET_WARGV(argv, c); + } else { + name2 = (const char*)GET_WARGV(argv, c); + } + } + if (help || name1 == NULL || name2 == NULL) { + if (!help) { + fprintf(stderr, "Error: missing arguments.\n"); + } + Help(); + goto End; + } + size1 = ReadPicture(name1, &pic1, 1); + size2 = ReadPicture(name2, &pic2, 1); + if (size1 == 0 || size2 == 0) goto End; + + if (!keep_alpha) { + WebPBlendAlpha(&pic1, 0x00000000); + WebPBlendAlpha(&pic2, 0x00000000); + } + + if (!WebPPictureDistortion(&pic1, &pic2, type, disto)) { + fprintf(stderr, "Error while computing the distortion.\n"); + goto End; + } + printf("%u %.2f %.2f %.2f %.2f %.2f [ %.2f bpp ]\n", + (unsigned int)size1, + disto[4], disto[0], disto[1], disto[2], disto[3], + 8.f * size1 / pic1.width / pic1.height); + + if (output != NULL) { + uint8_t* data = NULL; + size_t data_size = 0; + if (pic1.use_argb != pic2.use_argb) { + fprintf(stderr, "Pictures are not in the same argb format. " + "Can't save the difference map.\n"); + goto End; + } + if (pic1.use_argb) { + int n; + fprintf(stderr, "max differences per channel: "); + for (n = 0; n < 3; ++n) { // skip the alpha channel + const int range = (type == 1) ? + SSIMScaleChannel((uint8_t*)pic1.argb + n, pic1.argb_stride * 4, + (const uint8_t*)pic2.argb + n, pic2.argb_stride * 4, + 4, pic1.width, pic1.height, scale) : + DiffScaleChannel((uint8_t*)pic1.argb + n, pic1.argb_stride * 4, + (const uint8_t*)pic2.argb + n, pic2.argb_stride * 4, + 4, pic1.width, pic1.height, scale); + if (range < 0) fprintf(stderr, "\nError computing diff map\n"); + fprintf(stderr, "[%d]", range); + } + fprintf(stderr, "\n"); + if (use_gray) ConvertToGray(&pic1); + } else { + fprintf(stderr, "Can only compute the difference map in ARGB format.\n"); + goto End; + } +#if !defined(WEBP_REDUCE_CSP) + data_size = WebPEncodeLosslessBGRA((const uint8_t*)pic1.argb, + pic1.width, pic1.height, + pic1.argb_stride * 4, + &data); + if (data_size == 0) { + fprintf(stderr, "Error during lossless encoding.\n"); + goto End; + } + ret = ImgIoUtilWriteFile(output, data, data_size) ? 0 : 1; + WebPFree(data); + if (ret) goto End; +#else + (void)data; + (void)data_size; + fprintf(stderr, "Cannot save the difference map. Please recompile " + "without the WEBP_REDUCE_CSP flag.\n"); +#endif // WEBP_REDUCE_CSP + } + ret = 0; + + End: + WebPPictureFree(&pic1); + WebPPictureFree(&pic2); + FREE_WARGV_AND_RETURN(ret); +} diff --git a/third-party/webp/libwebp/extras/quality_estimate.c b/third-party/webp/libwebp/extras/quality_estimate.c new file mode 100644 index 0000000000..17e98d9626 --- /dev/null +++ b/third-party/webp/libwebp/extras/quality_estimate.c @@ -0,0 +1,129 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// VP8EstimateQuality(): rough encoding quality estimate +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "extras/extras.h" +#include "webp/decode.h" + +#include + +//------------------------------------------------------------------------------ + +#define INVALID_BIT_POS (1ull << 63) + +// In most cases, we don't need to use a full arithmetic decoder, since +// all the header's bits are written using a uniform probability of 128. +// We can just parse the header as if it was bits (works in 99.999% cases). +static WEBP_INLINE uint32_t GetBit(const uint8_t* const data, size_t nb, + uint64_t max_size, uint64_t* const bit_pos) { + uint32_t val = 0; + if (*bit_pos + nb <= 8 * max_size) { + while (nb-- > 0) { + const uint64_t p = (*bit_pos)++; + const int bit = !!(data[p >> 3] & (128 >> ((p & 7)))); + val = (val << 1) | bit; + } + } else { + *bit_pos = INVALID_BIT_POS; + } + return val; +} + +#define GET_BIT(n) GetBit(data, (n), size, &bit_pos) +#define CONDITIONAL_SKIP(n) (GET_BIT(1) ? GET_BIT((n)) : 0) + +int VP8EstimateQuality(const uint8_t* const data, size_t size) { + size_t pos = 0; + uint64_t bit_pos; + uint64_t sig = 0x00; + int ok = 0; + int Q = -1; + WebPBitstreamFeatures features; + + if (data == NULL) return -1; + + if (WebPGetFeatures(data, size, &features) != VP8_STATUS_OK) { + return -1; // invalid file + } + if (features.format == 2) return 101; // lossless + if (features.format == 0 || features.has_animation) return -1; // mixed + + while (pos < size) { + sig = (sig >> 8) | ((uint64_t)data[pos++] << 40); + if ((sig >> 24) == 0x2a019dull) { + ok = 1; + break; + } + } + if (!ok) return -1; + if (pos + 4 > size) return -1; + + // Skip main Header + // width = (data[pos + 0] | (data[pos + 1] << 8)) & 0x3fff; + // height = (data[pos + 2] | (data[pos + 3] << 8)) & 0x3fff; + pos += 4; + bit_pos = pos * 8; + + GET_BIT(2); // colorspace + clamp type + + // Segment header + if (GET_BIT(1)) { // use_segment_ + int s; + const int update_map = GET_BIT(1); + if (GET_BIT(1)) { // update data + const int absolute_delta = GET_BIT(1); + int q[4] = { 0, 0, 0, 0 }; + for (s = 0; s < 4; ++s) { + if (GET_BIT(1)) { + q[s] = GET_BIT(7); + if (GET_BIT(1)) q[s] = -q[s]; // sign + } + } + if (absolute_delta) Q = q[0]; // just use the first segment's quantizer + for (s = 0; s < 4; ++s) CONDITIONAL_SKIP(7); // filter strength + } + if (update_map) { + for (s = 0; s < 3; ++s) CONDITIONAL_SKIP(8); + } + } + // Filter header + GET_BIT(1 + 6 + 3); // simple + level + sharpness + if (GET_BIT(1)) { // use_lf_delta + if (GET_BIT(1)) { // update lf_delta? + int n; + for (n = 0; n < 4 + 4; ++n) CONDITIONAL_SKIP(6); + } + } + // num partitions + GET_BIT(2); + + // ParseQuant + { + const int base_q = GET_BIT(7); + /* dqy1_dc = */ CONDITIONAL_SKIP(5); + /* dqy2_dc = */ CONDITIONAL_SKIP(5); + /* dqy2_ac = */ CONDITIONAL_SKIP(5); + /* dquv_dc = */ CONDITIONAL_SKIP(5); + /* dquv_ac = */ CONDITIONAL_SKIP(5); + + if (Q < 0) Q = base_q; + } + if (bit_pos == INVALID_BIT_POS) return -1; + + // base mapping + Q = (127 - Q) * 100 / 127; + // correction for power-law behavior in low range + if (Q < 80) { + Q = (int)(pow(Q / 80., 1. / 0.38) * 80); + } + return Q; +} diff --git a/third-party/webp/libwebp/extras/vwebp_sdl.c b/third-party/webp/libwebp/extras/vwebp_sdl.c new file mode 100644 index 0000000000..e9554eb1dd --- /dev/null +++ b/third-party/webp/libwebp/extras/vwebp_sdl.c @@ -0,0 +1,101 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Simple SDL-based WebP file viewer. +// Does not support animation, just static images. +// +// Press 'q' to exit. +// +// Author: James Zern (jzern@google.com) + +#include + +#ifdef HAVE_CONFIG_H +#include "webp/config.h" +#endif + +#if defined(WEBP_HAVE_SDL) + +#include "webp_to_sdl.h" +#include "webp/decode.h" +#include "imageio/imageio_util.h" +#include "../examples/unicode.h" + +#if defined(WEBP_HAVE_JUST_SDL_H) +#include +#else +#include +#endif + +static void ProcessEvents(void) { + int done = 0; + SDL_Event event; + while (!done && SDL_WaitEvent(&event)) { + switch (event.type) { + case SDL_KEYUP: + switch (event.key.keysym.sym) { + case SDLK_q: done = 1; break; + default: break; + } + break; + default: break; + } + } +} + +int main(int argc, char* argv[]) { + int c; + int ok = 0; + + INIT_WARGV(argc, argv); + + for (c = 1; c < argc; ++c) { + const char* file = NULL; + const uint8_t* webp = NULL; + size_t webp_size = 0; + if (!strcmp(argv[c], "-h")) { + printf("Usage: %s [-h] image.webp [more_files.webp...]\n", argv[0]); + FREE_WARGV_AND_RETURN(0); + } else { + file = (const char*)GET_WARGV(argv, c); + } + if (file == NULL) continue; + if (!ImgIoUtilReadFile(file, &webp, &webp_size)) { + WFPRINTF(stderr, "Error opening file: %s\n", (const W_CHAR*)file); + goto Error; + } + if (webp_size != (size_t)(int)webp_size) { + free((void*)webp); + fprintf(stderr, "File too large.\n"); + goto Error; + } + ok = WebPToSDL((const char*)webp, (int)webp_size); + free((void*)webp); + if (!ok) { + WFPRINTF(stderr, "Error decoding file %s\n", (const W_CHAR*)file); + goto Error; + } + ProcessEvents(); + } + ok = 1; + + Error: + SDL_Quit(); + FREE_WARGV_AND_RETURN(ok ? 0 : 1); +} + +#else // !WEBP_HAVE_SDL + +int main(int argc, const char* argv[]) { + fprintf(stderr, "SDL support not enabled in %s.\n", argv[0]); + (void)argc; + return 0; +} + +#endif diff --git a/third-party/webp/libwebp/extras/webp_quality.c b/third-party/webp/libwebp/extras/webp_quality.c new file mode 100644 index 0000000000..0a3b25f18e --- /dev/null +++ b/third-party/webp/libwebp/extras/webp_quality.c @@ -0,0 +1,54 @@ +// Simple tool to roughly evaluate the quality encoding of a webp bitstream +// +// Result is a *rough* estimation of the quality. You should just consider +// the bucket it's in (q > 80? > 50? > 20?) and not take it for face value. +/* + gcc -o webp_quality webp_quality.c -O3 -I../ -L. -L../imageio \ + -limageio_util -lwebpextras -lwebp -lm -lpthread +*/ + +#include +#include +#include + +#include "extras/extras.h" +#include "imageio/imageio_util.h" +#include "../examples/unicode.h" + +int main(int argc, const char* argv[]) { + int c; + int quiet = 0; + int ok = 1; + + INIT_WARGV(argc, argv); + + for (c = 1; ok && c < argc; ++c) { + if (!strcmp(argv[c], "-quiet")) { + quiet = 1; + } else if (!strcmp(argv[c], "-help") || !strcmp(argv[c], "-h")) { + printf("webp_quality [-h][-quiet] webp_files...\n"); + FREE_WARGV_AND_RETURN(0); + } else { + const char* const filename = (const char*)GET_WARGV(argv, c); + const uint8_t* data = NULL; + size_t data_size = 0; + int q; + ok = ImgIoUtilReadFile(filename, &data, &data_size); + if (!ok) break; + q = VP8EstimateQuality(data, data_size); + if (!quiet) WPRINTF("[%s] ", (const W_CHAR*)filename); + if (q < 0) { + fprintf(stderr, "Not a WebP file, or not a lossy WebP file.\n"); + ok = 0; + } else { + if (!quiet) { + printf("Estimated quality factor: %d\n", q); + } else { + printf("%d\n", q); // just print the number + } + } + free((void*)data); + } + } + FREE_WARGV_AND_RETURN(ok ? 0 : 1); +} diff --git a/third-party/webp/libwebp/extras/webp_to_sdl.c b/third-party/webp/libwebp/extras/webp_to_sdl.c new file mode 100644 index 0000000000..1e526811c3 --- /dev/null +++ b/third-party/webp/libwebp/extras/webp_to_sdl.c @@ -0,0 +1,110 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Simple WebP-to-SDL wrapper. Useful for emscripten. +// +// Author: James Zern (jzern@google.com) + +#ifdef HAVE_CONFIG_H +#include "src/webp/config.h" +#endif + +#if defined(WEBP_HAVE_SDL) + +#include "webp_to_sdl.h" + +#include +#include "src/webp/decode.h" + +#if defined(WEBP_HAVE_JUST_SDL_H) +#include +#else +#include +#endif + +static int init_ok = 0; +int WebPToSDL(const char* data, unsigned int data_size) { + int ok = 0; + VP8StatusCode status; + WebPDecoderConfig config; + WebPBitstreamFeatures* const input = &config.input; + WebPDecBuffer* const output = &config.output; + SDL_Surface* screen = NULL; + SDL_Surface* surface = NULL; + + if (!WebPInitDecoderConfig(&config)) { + fprintf(stderr, "Library version mismatch!\n"); + return 0; + } + + if (!init_ok) { + SDL_Init(SDL_INIT_VIDEO); + init_ok = 1; + } + + status = WebPGetFeatures((uint8_t*)data, (size_t)data_size, &config.input); + if (status != VP8_STATUS_OK) goto Error; + + screen = SDL_SetVideoMode(input->width, input->height, 32, SDL_SWSURFACE); + if (screen == NULL) { + fprintf(stderr, "Unable to set video mode (32bpp %dx%d)!\n", + input->width, input->height); + goto Error; + } + + surface = SDL_CreateRGBSurface(SDL_SWSURFACE, + input->width, input->height, 32, + 0x000000ffu, // R mask + 0x0000ff00u, // G mask + 0x00ff0000u, // B mask + 0xff000000u); // A mask + + if (surface == NULL) { + fprintf(stderr, "Unable to create %dx%d RGBA surface!\n", + input->width, input->height); + goto Error; + } + if (SDL_MUSTLOCK(surface)) SDL_LockSurface(surface); + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + output->colorspace = MODE_BGRA; +#else + output->colorspace = MODE_RGBA; +#endif + output->width = surface->w; + output->height = surface->h; + output->u.RGBA.rgba = surface->pixels; + output->u.RGBA.stride = surface->pitch; + output->u.RGBA.size = surface->pitch * surface->h; + output->is_external_memory = 1; + + status = WebPDecode((const uint8_t*)data, (size_t)data_size, &config); + if (status != VP8_STATUS_OK) { + fprintf(stderr, "Error decoding image (%d)\n", status); + goto Error; + } + + if (SDL_MUSTLOCK(surface)) SDL_UnlockSurface(surface); + if (SDL_BlitSurface(surface, NULL, screen, NULL) || + SDL_Flip(screen)) { + goto Error; + } + + ok = 1; + + Error: + SDL_FreeSurface(surface); + SDL_FreeSurface(screen); + WebPFreeDecBuffer(output); + return ok; +} + +//------------------------------------------------------------------------------ + +#endif // WEBP_HAVE_SDL diff --git a/third-party/webp/libwebp/extras/webp_to_sdl.h b/third-party/webp/libwebp/extras/webp_to_sdl.h new file mode 100644 index 0000000000..1534f2b429 --- /dev/null +++ b/third-party/webp/libwebp/extras/webp_to_sdl.h @@ -0,0 +1,22 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Simple WebP-to-SDL wrapper. Useful for emscripten. +// +// Author: James Zern (jzern@google.com) + +#ifndef WEBP_EXTRAS_WEBP_TO_SDL_H_ +#define WEBP_EXTRAS_WEBP_TO_SDL_H_ + +// Exports the method WebPToSDL(const char* data, int data_size) which decodes +// a WebP bitstream into an RGBA SDL surface. +// Return false on failure. +extern int WebPToSDL(const char* data, unsigned int data_size); + +#endif // WEBP_EXTRAS_WEBP_TO_SDL_H_ diff --git a/third-party/webp/libwebp/gradle.properties b/third-party/webp/libwebp/gradle.properties new file mode 100644 index 0000000000..28d39f5dfe --- /dev/null +++ b/third-party/webp/libwebp/gradle.properties @@ -0,0 +1,14 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Versions for gradle +BUILD_TOOLS_VERSION=23.0.3 +COMPILE_SDK_VERSION=23 +ANDROID_GRADLE_PLUGIN_VERSION=1.5.0 +GRADLE_DOWNLOAD_TASK_VERSION=2.1.0 diff --git a/third-party/webp/libwebp/gradle/wrapper/gradle-wrapper.jar b/third-party/webp/libwebp/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..f3d88b1c2faf2fc91d853cd5d4242b5547257070 GIT binary patch literal 58695 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 literal 0 HcmV?d00001 diff --git a/third-party/webp/libwebp/gradle/wrapper/gradle-wrapper.properties b/third-party/webp/libwebp/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..1b16c34a71 --- /dev/null +++ b/third-party/webp/libwebp/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/third-party/webp/libwebp/gradlew b/third-party/webp/libwebp/gradlew new file mode 100755 index 0000000000..2fe81a7d95 --- /dev/null +++ b/third-party/webp/libwebp/gradlew @@ -0,0 +1,183 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/third-party/webp/libwebp/gradlew.bat b/third-party/webp/libwebp/gradlew.bat new file mode 100644 index 0000000000..24467a141f --- /dev/null +++ b/third-party/webp/libwebp/gradlew.bat @@ -0,0 +1,100 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/third-party/webp/libwebp/imageio/Android.mk b/third-party/webp/libwebp/imageio/Android.mk new file mode 100644 index 0000000000..1c8b83677e --- /dev/null +++ b/third-party/webp/libwebp/imageio/Android.mk @@ -0,0 +1,57 @@ +# Ignore this file during non-NDK builds. +ifdef NDK_ROOT +LOCAL_PATH := $(call my-dir) + +################################################################################ +# libimageio_util + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + imageio_util.c \ + +LOCAL_CFLAGS := $(WEBP_CFLAGS) +LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src + +LOCAL_MODULE := imageio_util + +include $(BUILD_STATIC_LIBRARY) + +################################################################################ +# libimagedec + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + image_dec.c \ + jpegdec.c \ + metadata.c \ + pngdec.c \ + pnmdec.c \ + tiffdec.c \ + webpdec.c \ + +LOCAL_CFLAGS := $(WEBP_CFLAGS) +LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src +LOCAL_STATIC_LIBRARIES := imageio_util + +LOCAL_MODULE := imagedec + +include $(BUILD_STATIC_LIBRARY) + +################################################################################ +# libimageenc + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + image_enc.c \ + +LOCAL_CFLAGS := $(WEBP_CFLAGS) +LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src +LOCAL_STATIC_LIBRARIES := imageio_util + +LOCAL_MODULE := imageenc + +include $(BUILD_STATIC_LIBRARY) +endif # NDK_ROOT diff --git a/third-party/webp/libwebp/imageio/Makefile.am b/third-party/webp/libwebp/imageio/Makefile.am new file mode 100644 index 0000000000..500ec7e325 --- /dev/null +++ b/third-party/webp/libwebp/imageio/Makefile.am @@ -0,0 +1,32 @@ +AM_CPPFLAGS += -I$(top_builddir)/src -I$(top_srcdir)/src +noinst_LTLIBRARIES = +noinst_LTLIBRARIES += libimageio_util.la +if BUILD_DEMUX + noinst_LTLIBRARIES += libimagedec.la +endif +noinst_LTLIBRARIES += libimageenc.la + +noinst_HEADERS = +noinst_HEADERS += ../src/webp/decode.h +noinst_HEADERS += ../src/webp/types.h + +libimageio_util_la_SOURCES = +libimageio_util_la_SOURCES += imageio_util.c imageio_util.h + +libimagedec_la_SOURCES = +libimagedec_la_SOURCES += image_dec.c image_dec.h +libimagedec_la_SOURCES += jpegdec.c jpegdec.h +libimagedec_la_SOURCES += metadata.c metadata.h +libimagedec_la_SOURCES += pngdec.c pngdec.h +libimagedec_la_SOURCES += pnmdec.c pnmdec.h +libimagedec_la_SOURCES += tiffdec.c tiffdec.h +libimagedec_la_SOURCES += webpdec.c webpdec.h +libimagedec_la_SOURCES += wicdec.c wicdec.h +libimagedec_la_CPPFLAGS = $(JPEG_INCLUDES) $(PNG_INCLUDES) $(TIFF_INCLUDES) +libimagedec_la_CPPFLAGS += $(AM_CPPFLAGS) +libimagedec_la_LIBADD = ../src/demux/libwebpdemux.la + +libimageenc_la_SOURCES = +libimageenc_la_SOURCES += image_enc.c image_enc.h +libimageenc_la_CPPFLAGS = $(JPEG_INCLUDES) $(PNG_INCLUDES) $(TIFF_INCLUDES) +libimageenc_la_CPPFLAGS += $(AM_CPPFLAGS) diff --git a/third-party/webp/libwebp/imageio/image_dec.c b/third-party/webp/libwebp/imageio/image_dec.c new file mode 100644 index 0000000000..5e003fab60 --- /dev/null +++ b/third-party/webp/libwebp/imageio/image_dec.c @@ -0,0 +1,84 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Generic image-type guessing. + +#include "./image_dec.h" + +const char* WebPGetEnabledInputFileFormats(void) { + return "WebP" +#ifdef WEBP_HAVE_JPEG + ", JPEG" +#endif +#ifdef WEBP_HAVE_PNG + ", PNG" +#endif + ", PNM (PGM, PPM, PAM)" +#ifdef WEBP_HAVE_TIFF + ", TIFF" +#endif +#ifdef HAVE_WINCODEC_H + ", Windows Imaging Component (WIC)" +#endif + ""; +} + +static WEBP_INLINE uint32_t GetBE32(const uint8_t buf[]) { + return ((uint32_t)buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; +} + +WebPInputFileFormat WebPGuessImageType(const uint8_t* const data, + size_t data_size) { + WebPInputFileFormat format = WEBP_UNSUPPORTED_FORMAT; + if (data != NULL && data_size >= 12) { + const uint32_t magic1 = GetBE32(data + 0); + const uint32_t magic2 = GetBE32(data + 8); + if (magic1 == 0x89504E47U) { + format = WEBP_PNG_FORMAT; + } else if (magic1 >= 0xFFD8FF00U && magic1 <= 0xFFD8FFFFU) { + format = WEBP_JPEG_FORMAT; + } else if (magic1 == 0x49492A00 || magic1 == 0x4D4D002A) { + format = WEBP_TIFF_FORMAT; + } else if (magic1 == 0x52494646 && magic2 == 0x57454250) { + format = WEBP_WEBP_FORMAT; + } else if (((magic1 >> 24) & 0xff) == 'P') { + const int type = (magic1 >> 16) & 0xff; + // we only support 'P5 -> P7' for now. + if (type >= '5' && type <= '7') format = WEBP_PNM_FORMAT; + } + } + return format; +} + +static int FailReader(const uint8_t* const data, size_t data_size, + struct WebPPicture* const pic, + int keep_alpha, struct Metadata* const metadata) { + (void)data; + (void)data_size; + (void)pic; + (void)keep_alpha; + (void)metadata; + return 0; +} + +WebPImageReader WebPGetImageReader(WebPInputFileFormat format) { + switch (format) { + case WEBP_PNG_FORMAT: return ReadPNG; + case WEBP_JPEG_FORMAT: return ReadJPEG; + case WEBP_TIFF_FORMAT: return ReadTIFF; + case WEBP_WEBP_FORMAT: return ReadWebP; + case WEBP_PNM_FORMAT: return ReadPNM; + default: return FailReader; + } +} + +WebPImageReader WebPGuessImageReader(const uint8_t* const data, + size_t data_size) { + return WebPGetImageReader(WebPGuessImageType(data, data_size)); +} diff --git a/third-party/webp/libwebp/imageio/image_dec.h b/third-party/webp/libwebp/imageio/image_dec.h new file mode 100644 index 0000000000..f09f564b6c --- /dev/null +++ b/third-party/webp/libwebp/imageio/image_dec.h @@ -0,0 +1,70 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// All-in-one library to decode PNG/JPEG/WebP/TIFF/WIC input images. +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_IMAGEIO_IMAGE_DEC_H_ +#define WEBP_IMAGEIO_IMAGE_DEC_H_ + +#include "webp/types.h" + +#ifdef HAVE_CONFIG_H +#include "webp/config.h" +#endif + +#include "./metadata.h" +#include "./jpegdec.h" +#include "./pngdec.h" +#include "./pnmdec.h" +#include "./tiffdec.h" +#include "./webpdec.h" +#include "./wicdec.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + WEBP_PNG_FORMAT = 0, + WEBP_JPEG_FORMAT, + WEBP_TIFF_FORMAT, + WEBP_WEBP_FORMAT, + WEBP_PNM_FORMAT, + WEBP_UNSUPPORTED_FORMAT +} WebPInputFileFormat; + +// Returns a comma separated list of enabled input formats. +const char* WebPGetEnabledInputFileFormats(void); + +// Try to infer the image format. 'data_size' should be larger than 12. +// Returns WEBP_UNSUPPORTED_FORMAT if format can't be guess safely. +WebPInputFileFormat WebPGuessImageType(const uint8_t* const data, + size_t data_size); + +// Signature for common image-reading functions (ReadPNG, ReadJPEG, ...) +typedef int (*WebPImageReader)(const uint8_t* const data, size_t data_size, + struct WebPPicture* const pic, + int keep_alpha, struct Metadata* const metadata); + +// Return the reader associated to a given file format. +WebPImageReader WebPGetImageReader(WebPInputFileFormat format); + +// This function is similar to WebPGuessImageType(), but returns a +// suitable reader function. The returned reader is never NULL, but +// unknown formats will return an always-failing valid reader. +WebPImageReader WebPGuessImageReader(const uint8_t* const data, + size_t data_size); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_IMAGEIO_IMAGE_DEC_H_ diff --git a/third-party/webp/libwebp/imageio/image_enc.c b/third-party/webp/libwebp/imageio/image_enc.c new file mode 100644 index 0000000000..d58477f376 --- /dev/null +++ b/third-party/webp/libwebp/imageio/image_enc.c @@ -0,0 +1,638 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Save image + +#include "./image_enc.h" + +#include +#include + +#ifdef WEBP_HAVE_PNG +#include +#include // note: this must be included *after* png.h +#endif + +#ifdef HAVE_WINCODEC_H +#ifdef __MINGW32__ +#define INITGUID // Without this GUIDs are declared extern and fail to link +#endif +#define CINTERFACE +#define COBJMACROS +#define _WIN32_IE 0x500 // Workaround bug in shlwapi.h when compiling C++ + // code with COBJMACROS. +#include // CreateStreamOnHGlobal() +#include +#include +#include +#include +#endif + +#include "./imageio_util.h" +#include "../examples/unicode.h" + +//------------------------------------------------------------------------------ +// PNG + +#ifdef HAVE_WINCODEC_H + +#define IFS(fn) \ + do { \ + if (SUCCEEDED(hr)) { \ + hr = (fn); \ + if (FAILED(hr)) fprintf(stderr, #fn " failed %08lx\n", hr); \ + } \ + } while (0) + +#ifdef __cplusplus +#define MAKE_REFGUID(x) (x) +#else +#define MAKE_REFGUID(x) &(x) +#endif + +static HRESULT CreateOutputStream(const char* out_file_name, + int write_to_mem, IStream** stream) { + HRESULT hr = S_OK; + if (write_to_mem) { + // Output to a memory buffer. This is freed when 'stream' is released. + IFS(CreateStreamOnHGlobal(NULL, TRUE, stream)); + } else { + IFS(SHCreateStreamOnFile((const LPTSTR)out_file_name, + STGM_WRITE | STGM_CREATE, stream)); + } + if (FAILED(hr)) { + _ftprintf(stderr, _T("Error opening output file %s (%08lx)\n"), + (const LPTSTR)out_file_name, hr); + } + return hr; +} + +static HRESULT WriteUsingWIC(const char* out_file_name, int use_stdout, + REFGUID container_guid, + uint8_t* rgb, int stride, + uint32_t width, uint32_t height, int has_alpha) { + HRESULT hr = S_OK; + IWICImagingFactory* factory = NULL; + IWICBitmapFrameEncode* frame = NULL; + IWICBitmapEncoder* encoder = NULL; + IStream* stream = NULL; + WICPixelFormatGUID pixel_format = has_alpha ? GUID_WICPixelFormat32bppBGRA + : GUID_WICPixelFormat24bppBGR; + + if (out_file_name == NULL || rgb == NULL) return E_INVALIDARG; + + IFS(CoInitialize(NULL)); + IFS(CoCreateInstance(MAKE_REFGUID(CLSID_WICImagingFactory), NULL, + CLSCTX_INPROC_SERVER, + MAKE_REFGUID(IID_IWICImagingFactory), + (LPVOID*)&factory)); + if (hr == REGDB_E_CLASSNOTREG) { + fprintf(stderr, + "Couldn't access Windows Imaging Component (are you running " + "Windows XP SP3 or newer?). PNG support not available. " + "Use -ppm or -pgm for available PPM and PGM formats.\n"); + } + IFS(CreateOutputStream(out_file_name, use_stdout, &stream)); + IFS(IWICImagingFactory_CreateEncoder(factory, container_guid, NULL, + &encoder)); + IFS(IWICBitmapEncoder_Initialize(encoder, stream, + WICBitmapEncoderNoCache)); + IFS(IWICBitmapEncoder_CreateNewFrame(encoder, &frame, NULL)); + IFS(IWICBitmapFrameEncode_Initialize(frame, NULL)); + IFS(IWICBitmapFrameEncode_SetSize(frame, width, height)); + IFS(IWICBitmapFrameEncode_SetPixelFormat(frame, &pixel_format)); + IFS(IWICBitmapFrameEncode_WritePixels(frame, height, stride, + height * stride, rgb)); + IFS(IWICBitmapFrameEncode_Commit(frame)); + IFS(IWICBitmapEncoder_Commit(encoder)); + + if (SUCCEEDED(hr) && use_stdout) { + HGLOBAL image; + IFS(GetHGlobalFromStream(stream, &image)); + if (SUCCEEDED(hr)) { + HANDLE std_output = GetStdHandle(STD_OUTPUT_HANDLE); + DWORD mode; + const BOOL update_mode = GetConsoleMode(std_output, &mode); + const void* const image_mem = GlobalLock(image); + DWORD bytes_written = 0; + + // Clear output processing if necessary, then output the image. + if (update_mode) SetConsoleMode(std_output, 0); + if (!WriteFile(std_output, image_mem, (DWORD)GlobalSize(image), + &bytes_written, NULL) || + bytes_written != GlobalSize(image)) { + hr = E_FAIL; + } + if (update_mode) SetConsoleMode(std_output, mode); + GlobalUnlock(image); + } + } + + if (frame != NULL) IUnknown_Release(frame); + if (encoder != NULL) IUnknown_Release(encoder); + if (factory != NULL) IUnknown_Release(factory); + if (stream != NULL) IUnknown_Release(stream); + return hr; +} + +int WebPWritePNG(const char* out_file_name, int use_stdout, + const WebPDecBuffer* const buffer) { + const uint32_t width = buffer->width; + const uint32_t height = buffer->height; + uint8_t* const rgb = buffer->u.RGBA.rgba; + const int stride = buffer->u.RGBA.stride; + const int has_alpha = WebPIsAlphaMode(buffer->colorspace); + + return SUCCEEDED(WriteUsingWIC(out_file_name, use_stdout, + MAKE_REFGUID(GUID_ContainerFormatPng), + rgb, stride, width, height, has_alpha)); +} + +#elif defined(WEBP_HAVE_PNG) // !HAVE_WINCODEC_H +static void PNGAPI PNGErrorFunction(png_structp png, png_const_charp unused) { + (void)unused; // remove variable-unused warning + longjmp(png_jmpbuf(png), 1); +} + +int WebPWritePNG(FILE* out_file, const WebPDecBuffer* const buffer) { + volatile png_structp png; + volatile png_infop info; + + if (out_file == NULL || buffer == NULL) return 0; + + png = png_create_write_struct(PNG_LIBPNG_VER_STRING, + NULL, PNGErrorFunction, NULL); + if (png == NULL) { + return 0; + } + info = png_create_info_struct(png); + if (info == NULL) { + png_destroy_write_struct((png_structpp)&png, NULL); + return 0; + } + if (setjmp(png_jmpbuf(png))) { + png_destroy_write_struct((png_structpp)&png, (png_infopp)&info); + return 0; + } + png_init_io(png, out_file); + { + const uint32_t width = buffer->width; + const uint32_t height = buffer->height; + png_bytep row = buffer->u.RGBA.rgba; + const int stride = buffer->u.RGBA.stride; + const int has_alpha = WebPIsAlphaMode(buffer->colorspace); + uint32_t y; + + png_set_IHDR(png, info, width, height, 8, + has_alpha ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB, + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + png_write_info(png, info); + for (y = 0; y < height; ++y) { + png_write_rows(png, &row, 1); + row += stride; + } + } + png_write_end(png, info); + png_destroy_write_struct((png_structpp)&png, (png_infopp)&info); + return 1; +} +#else // !HAVE_WINCODEC_H && !WEBP_HAVE_PNG +int WebPWritePNG(FILE* fout, const WebPDecBuffer* const buffer) { + if (fout == NULL || buffer == NULL) return 0; + + fprintf(stderr, "PNG support not compiled. Please install the libpng " + "development package before building.\n"); + fprintf(stderr, "You can run with -ppm flag to decode in PPM format.\n"); + return 0; +} +#endif + +//------------------------------------------------------------------------------ +// PPM / PAM + +static int WritePPMPAM(FILE* fout, const WebPDecBuffer* const buffer, + int alpha) { + if (fout == NULL || buffer == NULL) { + return 0; + } else { + const uint32_t width = buffer->width; + const uint32_t height = buffer->height; + const uint8_t* row = buffer->u.RGBA.rgba; + const int stride = buffer->u.RGBA.stride; + const size_t bytes_per_px = alpha ? 4 : 3; + uint32_t y; + + if (row == NULL) return 0; + + if (alpha) { + fprintf(fout, "P7\nWIDTH %u\nHEIGHT %u\nDEPTH 4\nMAXVAL 255\n" + "TUPLTYPE RGB_ALPHA\nENDHDR\n", width, height); + } else { + fprintf(fout, "P6\n%u %u\n255\n", width, height); + } + for (y = 0; y < height; ++y) { + if (fwrite(row, width, bytes_per_px, fout) != bytes_per_px) { + return 0; + } + row += stride; + } + } + return 1; +} + +int WebPWritePPM(FILE* fout, const WebPDecBuffer* const buffer) { + return WritePPMPAM(fout, buffer, 0); +} + +int WebPWritePAM(FILE* fout, const WebPDecBuffer* const buffer) { + return WritePPMPAM(fout, buffer, 1); +} + +//------------------------------------------------------------------------------ +// Raw PGM + +// Save 16b mode (RGBA4444, RGB565, ...) for debugging purpose. +int WebPWrite16bAsPGM(FILE* fout, const WebPDecBuffer* const buffer) { + uint32_t width, height; + uint8_t* rgba; + int stride; + const uint32_t bytes_per_px = 2; + uint32_t y; + + if (fout == NULL || buffer == NULL) return 0; + + width = buffer->width; + height = buffer->height; + rgba = buffer->u.RGBA.rgba; + stride = buffer->u.RGBA.stride; + + if (rgba == NULL) return 0; + + fprintf(fout, "P5\n%u %u\n255\n", width * bytes_per_px, height); + for (y = 0; y < height; ++y) { + if (fwrite(rgba, width, bytes_per_px, fout) != bytes_per_px) { + return 0; + } + rgba += stride; + } + return 1; +} + +//------------------------------------------------------------------------------ +// BMP (see https://en.wikipedia.org/wiki/BMP_file_format#Pixel_storage) + +static void PutLE16(uint8_t* const dst, uint32_t value) { + dst[0] = (value >> 0) & 0xff; + dst[1] = (value >> 8) & 0xff; +} + +static void PutLE32(uint8_t* const dst, uint32_t value) { + PutLE16(dst + 0, (value >> 0) & 0xffff); + PutLE16(dst + 2, (value >> 16) & 0xffff); +} + +#define BMP_HEADER_SIZE 54 +#define BMP_HEADER_ALPHA_EXTRA_SIZE 16 // for alpha info +int WebPWriteBMP(FILE* fout, const WebPDecBuffer* const buffer) { + int has_alpha, header_size; + uint32_t width, height; + uint8_t* rgba; + int stride; + uint32_t y; + uint32_t bytes_per_px, line_size, image_size, bmp_stride, total_size; + uint8_t bmp_header[BMP_HEADER_SIZE + BMP_HEADER_ALPHA_EXTRA_SIZE] = { 0 }; + + if (fout == NULL || buffer == NULL) return 0; + + has_alpha = WebPIsAlphaMode(buffer->colorspace); + header_size = BMP_HEADER_SIZE + (has_alpha ? BMP_HEADER_ALPHA_EXTRA_SIZE : 0); + width = buffer->width; + height = buffer->height; + rgba = buffer->u.RGBA.rgba; + stride = buffer->u.RGBA.stride; + bytes_per_px = has_alpha ? 4 : 3; + line_size = bytes_per_px * width; + bmp_stride = (line_size + 3) & ~3; // pad to 4 + image_size = bmp_stride * height; + total_size = image_size + header_size; + + if (rgba == NULL) return 0; + + // bitmap file header + PutLE16(bmp_header + 0, 0x4d42); // signature 'BM' + PutLE32(bmp_header + 2, total_size); // size including header + PutLE32(bmp_header + 6, 0); // reserved + PutLE32(bmp_header + 10, header_size); // offset to pixel array + // bitmap info header + PutLE32(bmp_header + 14, header_size - 14); // DIB header size + PutLE32(bmp_header + 18, width); // dimensions + PutLE32(bmp_header + 22, height); // no vertical flip + PutLE16(bmp_header + 26, 1); // number of planes + PutLE16(bmp_header + 28, bytes_per_px * 8); // bits per pixel + PutLE32(bmp_header + 30, has_alpha ? 3 : 0); // BI_BITFIELDS or BI_RGB + PutLE32(bmp_header + 34, image_size); + PutLE32(bmp_header + 38, 2400); // x pixels/meter + PutLE32(bmp_header + 42, 2400); // y pixels/meter + PutLE32(bmp_header + 46, 0); // number of palette colors + PutLE32(bmp_header + 50, 0); // important color count + if (has_alpha) { // BITMAPV3INFOHEADER complement + PutLE32(bmp_header + 54, 0x00ff0000); // red mask + PutLE32(bmp_header + 58, 0x0000ff00); // green mask + PutLE32(bmp_header + 62, 0x000000ff); // blue mask + PutLE32(bmp_header + 66, 0xff000000); // alpha mask + } + + // TODO(skal): color profile + + // write header + if (fwrite(bmp_header, header_size, 1, fout) != 1) { + return 0; + } + + // write pixel array, bottom to top + for (y = 0; y < height; ++y) { + const uint8_t* const src = &rgba[(uint64_t)(height - 1 - y) * stride]; + if (fwrite(src, line_size, 1, fout) != 1) { + return 0; + } + // write padding zeroes + if (bmp_stride != line_size) { + const uint8_t zeroes[3] = { 0 }; + if (fwrite(zeroes, bmp_stride - line_size, 1, fout) != 1) { + return 0; + } + } + } + return 1; +} +#undef BMP_HEADER_SIZE +#undef BMP_HEADER_ALPHA_EXTRA_SIZE + +//------------------------------------------------------------------------------ +// TIFF + +#define NUM_IFD_ENTRIES 15 +#define EXTRA_DATA_SIZE 16 +// 10b for signature/header + n * 12b entries + 4b for IFD terminator: +#define EXTRA_DATA_OFFSET (10 + 12 * NUM_IFD_ENTRIES + 4) +#define TIFF_HEADER_SIZE (EXTRA_DATA_OFFSET + EXTRA_DATA_SIZE) + +int WebPWriteTIFF(FILE* fout, const WebPDecBuffer* const buffer) { + int has_alpha; + uint32_t width, height; + uint8_t* rgba; + int stride; + uint8_t bytes_per_px = 0; + const uint8_t assoc_alpha = 0; + // For non-alpha case, we omit tag 0x152 (ExtraSamples). + const uint8_t num_ifd_entries = 0; + uint8_t tiff_header[TIFF_HEADER_SIZE] = { + 0x49, 0x49, 0x2a, 0x00, // little endian signature + 8, 0, 0, 0, // offset to the unique IFD that follows + // IFD (offset = 8). Entries must be written in increasing tag order. + num_ifd_entries, 0, // Number of entries in the IFD (12 bytes each). + 0x00, 0x01, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 10: Width (TBD) + 0x01, 0x01, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 22: Height (TBD) + 0x02, 0x01, 3, 0, bytes_per_px, 0, 0, 0, // 34: BitsPerSample: 8888 + EXTRA_DATA_OFFSET + 0, 0, 0, 0, + 0x03, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 46: Compression: none + 0x06, 0x01, 3, 0, 1, 0, 0, 0, 2, 0, 0, 0, // 58: Photometric: RGB + 0x11, 0x01, 4, 0, 1, 0, 0, 0, // 70: Strips offset: + TIFF_HEADER_SIZE, 0, 0, 0, // data follows header + 0x12, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 82: Orientation: topleft + 0x15, 0x01, 3, 0, 1, 0, 0, 0, // 94: SamplesPerPixels + bytes_per_px, 0, 0, 0, + 0x16, 0x01, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 106: Rows per strip (TBD) + 0x17, 0x01, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 118: StripByteCount (TBD) + 0x1a, 0x01, 5, 0, 1, 0, 0, 0, // 130: X-resolution + EXTRA_DATA_OFFSET + 8, 0, 0, 0, + 0x1b, 0x01, 5, 0, 1, 0, 0, 0, // 142: Y-resolution + EXTRA_DATA_OFFSET + 8, 0, 0, 0, + 0x1c, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 154: PlanarConfiguration + 0x28, 0x01, 3, 0, 1, 0, 0, 0, 2, 0, 0, 0, // 166: ResolutionUnit (inch) + 0x52, 0x01, 3, 0, 1, 0, 0, 0, + assoc_alpha, 0, 0, 0, // 178: ExtraSamples: rgbA/RGBA + 0, 0, 0, 0, // 190: IFD terminator + // EXTRA_DATA_OFFSET: + 8, 0, 8, 0, 8, 0, 8, 0, // BitsPerSample + 72, 0, 0, 0, 1, 0, 0, 0 // 72 pixels/inch, for X/Y-resolution + }; + uint32_t y; + + if (fout == NULL || buffer == NULL) return 0; + + has_alpha = WebPIsAlphaMode(buffer->colorspace); + width = buffer->width; + height = buffer->height; + rgba = buffer->u.RGBA.rgba; + stride = buffer->u.RGBA.stride; + + if (rgba == NULL) return 0; + + // Update bytes_per_px, num_ifd_entries and assoc_alpha. + tiff_header[38] = tiff_header[102] = bytes_per_px = has_alpha ? 4 : 3; + tiff_header[8] = has_alpha ? NUM_IFD_ENTRIES : NUM_IFD_ENTRIES - 1; + tiff_header[186] = WebPIsPremultipliedMode(buffer->colorspace) ? 1 : 2; + + // Fill placeholders in IFD: + PutLE32(tiff_header + 10 + 8, width); + PutLE32(tiff_header + 22 + 8, height); + PutLE32(tiff_header + 106 + 8, height); + PutLE32(tiff_header + 118 + 8, width * bytes_per_px * height); + if (!has_alpha) PutLE32(tiff_header + 178, 0); // IFD terminator + + // write header + if (fwrite(tiff_header, sizeof(tiff_header), 1, fout) != 1) { + return 0; + } + // write pixel values + for (y = 0; y < height; ++y) { + if (fwrite(rgba, bytes_per_px, width, fout) != width) { + return 0; + } + rgba += stride; + } + + return 1; +} + +#undef TIFF_HEADER_SIZE +#undef EXTRA_DATA_OFFSET +#undef EXTRA_DATA_SIZE +#undef NUM_IFD_ENTRIES + +//------------------------------------------------------------------------------ +// Raw Alpha + +int WebPWriteAlphaPlane(FILE* fout, const WebPDecBuffer* const buffer) { + if (fout == NULL || buffer == NULL) { + return 0; + } else { + const uint32_t width = buffer->width; + const uint32_t height = buffer->height; + const uint8_t* a = buffer->u.YUVA.a; + const int a_stride = buffer->u.YUVA.a_stride; + uint32_t y; + + if (a == NULL) return 0; + + fprintf(fout, "P5\n%u %u\n255\n", width, height); + for (y = 0; y < height; ++y) { + if (fwrite(a, width, 1, fout) != 1) return 0; + a += a_stride; + } + return 1; + } +} + +//------------------------------------------------------------------------------ +// PGM with IMC4 layout + +int WebPWritePGM(FILE* fout, const WebPDecBuffer* const buffer) { + if (fout == NULL || buffer == NULL) { + return 0; + } else { + const int width = buffer->width; + const int height = buffer->height; + const WebPYUVABuffer* const yuv = &buffer->u.YUVA; + const uint8_t* src_y = yuv->y; + const uint8_t* src_u = yuv->u; + const uint8_t* src_v = yuv->v; + const uint8_t* src_a = yuv->a; + const int uv_width = (width + 1) / 2; + const int uv_height = (height + 1) / 2; + const int a_height = (src_a != NULL) ? height : 0; + int ok = 1; + int y; + + if (src_y == NULL || src_u == NULL || src_v == NULL) return 0; + + fprintf(fout, "P5\n%d %d\n255\n", + (width + 1) & ~1, height + uv_height + a_height); + for (y = 0; ok && y < height; ++y) { + ok &= (fwrite(src_y, width, 1, fout) == 1); + if (width & 1) fputc(0, fout); // padding byte + src_y += yuv->y_stride; + } + for (y = 0; ok && y < uv_height; ++y) { + ok &= (fwrite(src_u, uv_width, 1, fout) == 1); + ok &= (fwrite(src_v, uv_width, 1, fout) == 1); + src_u += yuv->u_stride; + src_v += yuv->v_stride; + } + for (y = 0; ok && y < a_height; ++y) { + ok &= (fwrite(src_a, width, 1, fout) == 1); + if (width & 1) fputc(0, fout); // padding byte + src_a += yuv->a_stride; + } + return ok; + } +} + +//------------------------------------------------------------------------------ +// Raw YUV(A) planes + +int WebPWriteYUV(FILE* fout, const WebPDecBuffer* const buffer) { + if (fout == NULL || buffer == NULL) { + return 0; + } else { + const int width = buffer->width; + const int height = buffer->height; + const WebPYUVABuffer* const yuv = &buffer->u.YUVA; + const uint8_t* src_y = yuv->y; + const uint8_t* src_u = yuv->u; + const uint8_t* src_v = yuv->v; + const uint8_t* src_a = yuv->a; + const int uv_width = (width + 1) / 2; + const int uv_height = (height + 1) / 2; + const int a_height = (src_a != NULL) ? height : 0; + int ok = 1; + int y; + + if (src_y == NULL || src_u == NULL || src_v == NULL) return 0; + + for (y = 0; ok && y < height; ++y) { + ok &= (fwrite(src_y, width, 1, fout) == 1); + src_y += yuv->y_stride; + } + for (y = 0; ok && y < uv_height; ++y) { + ok &= (fwrite(src_u, uv_width, 1, fout) == 1); + src_u += yuv->u_stride; + } + for (y = 0; ok && y < uv_height; ++y) { + ok &= (fwrite(src_v, uv_width, 1, fout) == 1); + src_v += yuv->v_stride; + } + for (y = 0; ok && y < a_height; ++y) { + ok &= (fwrite(src_a, width, 1, fout) == 1); + src_a += yuv->a_stride; + } + return ok; + } +} + +//------------------------------------------------------------------------------ +// Generic top-level call + +int WebPSaveImage(const WebPDecBuffer* const buffer, + WebPOutputFileFormat format, + const char* const out_file_name) { + FILE* fout = NULL; + int needs_open_file = 1; + const int use_stdout = + (out_file_name != NULL) && !WSTRCMP(out_file_name, "-"); + int ok = 1; + + if (buffer == NULL || out_file_name == NULL) return 0; + +#ifdef HAVE_WINCODEC_H + needs_open_file = (format != PNG); +#endif + + if (needs_open_file) { + fout = use_stdout ? ImgIoUtilSetBinaryMode(stdout) + : WFOPEN(out_file_name, "wb"); + if (fout == NULL) { + WFPRINTF(stderr, "Error opening output file %s\n", + (const W_CHAR*)out_file_name); + return 0; + } + } + + if (format == PNG || + format == RGBA || format == BGRA || format == ARGB || + format == rgbA || format == bgrA || format == Argb) { +#ifdef HAVE_WINCODEC_H + ok &= WebPWritePNG(out_file_name, use_stdout, buffer); +#else + ok &= WebPWritePNG(fout, buffer); +#endif + } else if (format == PAM) { + ok &= WebPWritePAM(fout, buffer); + } else if (format == PPM || format == RGB || format == BGR) { + ok &= WebPWritePPM(fout, buffer); + } else if (format == RGBA_4444 || format == RGB_565 || format == rgbA_4444) { + ok &= WebPWrite16bAsPGM(fout, buffer); + } else if (format == BMP) { + ok &= WebPWriteBMP(fout, buffer); + } else if (format == TIFF) { + ok &= WebPWriteTIFF(fout, buffer); + } else if (format == RAW_YUV) { + ok &= WebPWriteYUV(fout, buffer); + } else if (format == PGM || format == YUV || format == YUVA) { + ok &= WebPWritePGM(fout, buffer); + } else if (format == ALPHA_PLANE_ONLY) { + ok &= WebPWriteAlphaPlane(fout, buffer); + } + if (fout != NULL && fout != stdout) { + fclose(fout); + } + return ok; +} diff --git a/third-party/webp/libwebp/imageio/image_enc.h b/third-party/webp/libwebp/imageio/image_enc.h new file mode 100644 index 0000000000..d31e4bd3d2 --- /dev/null +++ b/third-party/webp/libwebp/imageio/image_enc.h @@ -0,0 +1,96 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// All-in-one library to save PNG/JPEG/WebP/TIFF/WIC images. +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_IMAGEIO_IMAGE_ENC_H_ +#define WEBP_IMAGEIO_IMAGE_ENC_H_ + +#include + +#ifdef HAVE_CONFIG_H +#include "webp/config.h" +#endif + +#include "webp/types.h" +#include "webp/decode.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Output types +typedef enum { + PNG = 0, + PAM, + PPM, + PGM, + BMP, + TIFF, + RAW_YUV, + ALPHA_PLANE_ONLY, // this is for experimenting only + // forced colorspace output (for testing, mostly) + RGB, RGBA, BGR, BGRA, ARGB, + RGBA_4444, RGB_565, + rgbA, bgrA, Argb, rgbA_4444, + YUV, YUVA +} WebPOutputFileFormat; + +// General all-purpose call. +// Most formats expect a 'buffer' containing RGBA-like samples, except +// RAW_YUV, YUV and YUVA formats. +// If 'out_file_name' is "-", data is saved to stdout. +// Returns false if an error occurred, true otherwise. +int WebPSaveImage(const WebPDecBuffer* const buffer, + WebPOutputFileFormat format, const char* const out_file_name); + +// Save to PNG. +#ifdef HAVE_WINCODEC_H +int WebPWritePNG(const char* out_file_name, int use_stdout, + const struct WebPDecBuffer* const buffer); +#else +int WebPWritePNG(FILE* out_file, const WebPDecBuffer* const buffer); +#endif + +// Save to PPM format (RGB, no alpha) +int WebPWritePPM(FILE* fout, const struct WebPDecBuffer* const buffer); + +// Save to PAM format (= PPM + alpha) +int WebPWritePAM(FILE* fout, const struct WebPDecBuffer* const buffer); + +// Save 16b mode (RGBA4444, RGB565, ...) for debugging purposes. +int WebPWrite16bAsPGM(FILE* fout, const struct WebPDecBuffer* const buffer); + +// Save as BMP +int WebPWriteBMP(FILE* fout, const struct WebPDecBuffer* const buffer); + +// Save as TIFF +int WebPWriteTIFF(FILE* fout, const struct WebPDecBuffer* const buffer); + +// Save the ALPHA plane (only) as a PGM +int WebPWriteAlphaPlane(FILE* fout, const struct WebPDecBuffer* const buffer); + +// Save as YUV samples as PGM format (using IMC4 layout). +// See: https://www.fourcc.org/yuv.php#IMC4. +// (very convenient format for viewing the samples, esp. for odd dimensions). +int WebPWritePGM(FILE* fout, const struct WebPDecBuffer* const buffer); + +// Save YUV(A) planes sequentially (raw dump) +int WebPWriteYUV(FILE* fout, const struct WebPDecBuffer* const buffer); + +// Save 16b mode (RGBA4444, RGB565, ...) as PGM format, for debugging purposes. +int WebPWrite16bAsPGM(FILE* fout, const struct WebPDecBuffer* const buffer); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_IMAGEIO_IMAGE_ENC_H_ diff --git a/third-party/webp/libwebp/imageio/imageio_util.c b/third-party/webp/libwebp/imageio/imageio_util.c new file mode 100644 index 0000000000..df37137e82 --- /dev/null +++ b/third-party/webp/libwebp/imageio/imageio_util.c @@ -0,0 +1,162 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Utility functions used by the image decoders. +// + +#include "./imageio_util.h" + +#if defined(_WIN32) +#include // for _O_BINARY +#include // for _setmode() +#endif +#include +#include +#include "../examples/unicode.h" + +// ----------------------------------------------------------------------------- +// File I/O + +FILE* ImgIoUtilSetBinaryMode(FILE* file) { +#if defined(_WIN32) + if (_setmode(_fileno(file), _O_BINARY) == -1) { + fprintf(stderr, "Failed to reopen file in O_BINARY mode.\n"); + return NULL; + } +#endif + return file; +} + +int ImgIoUtilReadFromStdin(const uint8_t** data, size_t* data_size) { + static const size_t kBlockSize = 16384; // default initial size + size_t max_size = 0; + size_t size = 0; + uint8_t* input = NULL; + + if (data == NULL || data_size == NULL) return 0; + *data = NULL; + *data_size = 0; + + if (!ImgIoUtilSetBinaryMode(stdin)) return 0; + + while (!feof(stdin)) { + // We double the buffer size each time and read as much as possible. + const size_t extra_size = (max_size == 0) ? kBlockSize : max_size; + // we allocate one extra byte for the \0 terminator + void* const new_data = realloc(input, max_size + extra_size + 1); + if (new_data == NULL) goto Error; + input = (uint8_t*)new_data; + max_size += extra_size; + size += fread(input + size, 1, extra_size, stdin); + if (size < max_size) break; + } + if (ferror(stdin)) goto Error; + if (input != NULL) input[size] = '\0'; // convenient 0-terminator + *data = input; + *data_size = size; + return 1; + + Error: + free(input); + fprintf(stderr, "Could not read from stdin\n"); + return 0; +} + +int ImgIoUtilReadFile(const char* const file_name, + const uint8_t** data, size_t* data_size) { + int ok; + uint8_t* file_data; + size_t file_size; + FILE* in; + const int from_stdin = (file_name == NULL) || !WSTRCMP(file_name, "-"); + + if (from_stdin) return ImgIoUtilReadFromStdin(data, data_size); + + if (data == NULL || data_size == NULL) return 0; + *data = NULL; + *data_size = 0; + + in = WFOPEN(file_name, "rb"); + if (in == NULL) { + WFPRINTF(stderr, "cannot open input file '%s'\n", (const W_CHAR*)file_name); + return 0; + } + fseek(in, 0, SEEK_END); + file_size = ftell(in); + fseek(in, 0, SEEK_SET); + // we allocate one extra byte for the \0 terminator + file_data = (uint8_t*)WebPMalloc(file_size + 1); + if (file_data == NULL) { + fclose(in); + WFPRINTF(stderr, "memory allocation failure when reading file %s\n", + (const W_CHAR*)file_name); + return 0; + } + ok = (fread(file_data, file_size, 1, in) == 1); + fclose(in); + + if (!ok) { + WFPRINTF(stderr, "Could not read %d bytes of data from file %s\n", + (int)file_size, (const W_CHAR*)file_name); + WebPFree(file_data); + return 0; + } + file_data[file_size] = '\0'; // convenient 0-terminator + *data = file_data; + *data_size = file_size; + return 1; +} + +// ----------------------------------------------------------------------------- + +int ImgIoUtilWriteFile(const char* const file_name, + const uint8_t* data, size_t data_size) { + int ok; + FILE* out; + const int to_stdout = (file_name == NULL) || !WSTRCMP(file_name, "-"); + + if (data == NULL) { + return 0; + } + out = to_stdout ? ImgIoUtilSetBinaryMode(stdout) : WFOPEN(file_name, "wb"); + if (out == NULL) { + WFPRINTF(stderr, "Error! Cannot open output file '%s'\n", + (const W_CHAR*)file_name); + return 0; + } + ok = (fwrite(data, data_size, 1, out) == 1); + if (out != stdout) fclose(out); + return ok; +} + +// ----------------------------------------------------------------------------- + +void ImgIoUtilCopyPlane(const uint8_t* src, int src_stride, + uint8_t* dst, int dst_stride, int width, int height) { + while (height-- > 0) { + memcpy(dst, src, width * sizeof(*dst)); + src += src_stride; + dst += dst_stride; + } +} + +// ----------------------------------------------------------------------------- + +int ImgIoUtilCheckSizeArgumentsOverflow(uint64_t stride, size_t height) { + const uint64_t total_size = stride * height; + int ok = (total_size == (size_t)total_size); + // check that 'stride' is representable as int: + ok = ok && ((uint64_t)(int)stride == stride); +#if defined(WEBP_MAX_IMAGE_SIZE) + ok = ok && (total_size <= (uint64_t)WEBP_MAX_IMAGE_SIZE); +#endif + return ok; +} + +// ----------------------------------------------------------------------------- diff --git a/third-party/webp/libwebp/imageio/imageio_util.h b/third-party/webp/libwebp/imageio/imageio_util.h new file mode 100644 index 0000000000..f135f56625 --- /dev/null +++ b/third-party/webp/libwebp/imageio/imageio_util.h @@ -0,0 +1,64 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Utility functions used by the image decoders. +// + +#ifndef WEBP_IMAGEIO_IMAGEIO_UTIL_H_ +#define WEBP_IMAGEIO_IMAGEIO_UTIL_H_ + +#include +#include "webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//------------------------------------------------------------------------------ +// File I/O + +// Reopen file in binary (O_BINARY) mode. +// Returns 'file' on success, NULL otherwise. +FILE* ImgIoUtilSetBinaryMode(FILE* file); + +// Allocates storage for entire file 'file_name' and returns contents and size +// in 'data' and 'data_size'. Returns 1 on success, 0 otherwise. '*data' should +// be deleted using WebPFree(). +// Note: for convenience, the data will be null-terminated with an extra byte +// (not accounted for in *data_size), in case the file is text and intended +// to be used as a C-string. +// If 'file_name' is NULL or equal to "-", input is read from stdin by calling +// the function ImgIoUtilReadFromStdin(). +int ImgIoUtilReadFile(const char* const file_name, + const uint8_t** data, size_t* data_size); + +// Same as ImgIoUtilReadFile(), but reads until EOF from stdin instead. +int ImgIoUtilReadFromStdin(const uint8_t** data, size_t* data_size); + +// Write a data segment into a file named 'file_name'. Returns true if ok. +// If 'file_name' is NULL or equal to "-", output is written to stdout. +int ImgIoUtilWriteFile(const char* const file_name, + const uint8_t* data, size_t data_size); + +//------------------------------------------------------------------------------ + +// Copy width x height pixels from 'src' to 'dst' honoring the strides. +void ImgIoUtilCopyPlane(const uint8_t* src, int src_stride, + uint8_t* dst, int dst_stride, int width, int height); + +//------------------------------------------------------------------------------ + +// Returns 0 in case of overflow, memory over-allocation or excessive dimension. +int ImgIoUtilCheckSizeArgumentsOverflow(uint64_t stride, size_t height); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_IMAGEIO_IMAGEIO_UTIL_H_ diff --git a/third-party/webp/libwebp/imageio/jpegdec.c b/third-party/webp/libwebp/imageio/jpegdec.c new file mode 100644 index 0000000000..74a4c09ccd --- /dev/null +++ b/third-party/webp/libwebp/imageio/jpegdec.c @@ -0,0 +1,364 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// JPEG decode. + +#include "./jpegdec.h" + +#ifdef HAVE_CONFIG_H +#include "webp/config.h" +#endif + +#include + +#ifdef WEBP_HAVE_JPEG +#include +#include +#include +#include +#include + +#include "webp/encode.h" +#include "./imageio_util.h" +#include "./metadata.h" + +// ----------------------------------------------------------------------------- +// Metadata processing + +#ifndef JPEG_APP1 +# define JPEG_APP1 (JPEG_APP0 + 1) +#endif +#ifndef JPEG_APP2 +# define JPEG_APP2 (JPEG_APP0 + 2) +#endif + +typedef struct { + const uint8_t* data; + size_t data_length; + int seq; // this segment's sequence number [1, 255] for use in reassembly. +} ICCPSegment; + +static void SaveMetadataMarkers(j_decompress_ptr dinfo) { + const unsigned int max_marker_length = 0xffff; + jpeg_save_markers(dinfo, JPEG_APP1, max_marker_length); // Exif/XMP + jpeg_save_markers(dinfo, JPEG_APP2, max_marker_length); // ICC profile +} + +static int CompareICCPSegments(const void* a, const void* b) { + const ICCPSegment* s1 = (const ICCPSegment*)a; + const ICCPSegment* s2 = (const ICCPSegment*)b; + return s1->seq - s2->seq; +} + +// Extract ICC profile segments from the marker list in 'dinfo', reassembling +// and storing them in 'iccp'. +// Returns true on success and false for memory errors and corrupt profiles. +static int StoreICCP(j_decompress_ptr dinfo, MetadataPayload* const iccp) { + // ICC.1:2010-12 (4.3.0.0) Annex B.4 Embedding ICC Profiles in JPEG files + static const char kICCPSignature[] = "ICC_PROFILE"; + static const size_t kICCPSignatureLength = 12; // signature includes '\0' + static const size_t kICCPSkipLength = 14; // signature + seq & count + int expected_count = 0; + int actual_count = 0; + int seq_max = 0; + size_t total_size = 0; + ICCPSegment iccp_segments[255]; + jpeg_saved_marker_ptr marker; + + memset(iccp_segments, 0, sizeof(iccp_segments)); + for (marker = dinfo->marker_list; marker != NULL; marker = marker->next) { + if (marker->marker == JPEG_APP2 && + marker->data_length > kICCPSkipLength && + !memcmp(marker->data, kICCPSignature, kICCPSignatureLength)) { + // ICC_PROFILE\0; 'seq' starts at 1. + const int seq = marker->data[kICCPSignatureLength]; + const int count = marker->data[kICCPSignatureLength + 1]; + const size_t segment_size = marker->data_length - kICCPSkipLength; + ICCPSegment* segment; + + if (segment_size == 0 || count == 0 || seq == 0) { + fprintf(stderr, "[ICCP] size (%d) / count (%d) / sequence number (%d)" + " cannot be 0!\n", + (int)segment_size, seq, count); + return 0; + } + + if (expected_count == 0) { + expected_count = count; + } else if (expected_count != count) { + fprintf(stderr, "[ICCP] Inconsistent segment count (%d / %d)!\n", + expected_count, count); + return 0; + } + + segment = iccp_segments + seq - 1; + if (segment->data_length != 0) { + fprintf(stderr, "[ICCP] Duplicate segment number (%d)!\n" , seq); + return 0; + } + + segment->data = marker->data + kICCPSkipLength; + segment->data_length = segment_size; + segment->seq = seq; + total_size += segment_size; + if (seq > seq_max) seq_max = seq; + ++actual_count; + } + } + + if (actual_count == 0) return 1; + if (seq_max != actual_count) { + fprintf(stderr, "[ICCP] Discontinuous segments, expected: %d actual: %d!\n", + actual_count, seq_max); + return 0; + } + if (expected_count != actual_count) { + fprintf(stderr, "[ICCP] Segment count: %d does not match expected: %d!\n", + actual_count, expected_count); + return 0; + } + + // The segments may appear out of order in the file, sort them based on + // sequence number before assembling the payload. + qsort(iccp_segments, actual_count, sizeof(*iccp_segments), + CompareICCPSegments); + + iccp->bytes = (uint8_t*)malloc(total_size); + if (iccp->bytes == NULL) return 0; + iccp->size = total_size; + + { + int i; + size_t offset = 0; + for (i = 0; i < seq_max; ++i) { + memcpy(iccp->bytes + offset, + iccp_segments[i].data, iccp_segments[i].data_length); + offset += iccp_segments[i].data_length; + } + } + return 1; +} + +// Returns true on success and false for memory errors and corrupt profiles. +// The caller must use MetadataFree() on 'metadata' in all cases. +static int ExtractMetadataFromJPEG(j_decompress_ptr dinfo, + Metadata* const metadata) { + static const struct { + int marker; + const char* signature; + size_t signature_length; + size_t storage_offset; + } kJPEGMetadataMap[] = { + // Exif 2.2 Section 4.7.2 Interoperability Structure of APP1 ... + { JPEG_APP1, "Exif\0", 6, METADATA_OFFSET(exif) }, + // XMP Specification Part 3 Section 3 Embedding XMP Metadata ... #JPEG + // TODO(jzern) Add support for 'ExtendedXMP' + { JPEG_APP1, "http://ns.adobe.com/xap/1.0/", 29, METADATA_OFFSET(xmp) }, + { 0, NULL, 0, 0 }, + }; + jpeg_saved_marker_ptr marker; + // Treat ICC profiles separately as they may be segmented and out of order. + if (!StoreICCP(dinfo, &metadata->iccp)) return 0; + + for (marker = dinfo->marker_list; marker != NULL; marker = marker->next) { + int i; + for (i = 0; kJPEGMetadataMap[i].marker != 0; ++i) { + if (marker->marker == kJPEGMetadataMap[i].marker && + marker->data_length > kJPEGMetadataMap[i].signature_length && + !memcmp(marker->data, kJPEGMetadataMap[i].signature, + kJPEGMetadataMap[i].signature_length)) { + MetadataPayload* const payload = + (MetadataPayload*)((uint8_t*)metadata + + kJPEGMetadataMap[i].storage_offset); + + if (payload->bytes == NULL) { + const char* marker_data = (const char*)marker->data + + kJPEGMetadataMap[i].signature_length; + const size_t marker_data_length = + marker->data_length - kJPEGMetadataMap[i].signature_length; + if (!MetadataCopy(marker_data, marker_data_length, payload)) return 0; + } else { + fprintf(stderr, "Ignoring additional '%s' marker\n", + kJPEGMetadataMap[i].signature); + } + } + } + } + return 1; +} + +#undef JPEG_APP1 +#undef JPEG_APP2 + +// ----------------------------------------------------------------------------- +// JPEG decoding + +struct my_error_mgr { + struct jpeg_error_mgr pub; + jmp_buf setjmp_buffer; +}; + +static void my_error_exit(j_common_ptr dinfo) { + struct my_error_mgr* myerr = (struct my_error_mgr*)dinfo->err; + fprintf(stderr, "libjpeg error: "); + dinfo->err->output_message(dinfo); + longjmp(myerr->setjmp_buffer, 1); +} + +typedef struct { + struct jpeg_source_mgr pub; + const uint8_t* data; + size_t data_size; +} JPEGReadContext; + +static void ContextInit(j_decompress_ptr cinfo) { + JPEGReadContext* const ctx = (JPEGReadContext*)cinfo->src; + ctx->pub.next_input_byte = ctx->data; + ctx->pub.bytes_in_buffer = ctx->data_size; +} + +static boolean ContextFill(j_decompress_ptr cinfo) { + // we shouldn't get here. + ERREXIT(cinfo, JERR_FILE_READ); + return FALSE; +} + +static void ContextSkip(j_decompress_ptr cinfo, long jump_size) { + JPEGReadContext* const ctx = (JPEGReadContext*)cinfo->src; + size_t jump = (size_t)jump_size; + if (jump > ctx->pub.bytes_in_buffer) { // Don't overflow the buffer. + jump = ctx->pub.bytes_in_buffer; + } + ctx->pub.bytes_in_buffer -= jump; + ctx->pub.next_input_byte += jump; +} + +static void ContextTerm(j_decompress_ptr cinfo) { + (void)cinfo; +} + +static void ContextSetup(volatile struct jpeg_decompress_struct* const cinfo, + JPEGReadContext* const ctx) { + cinfo->src = (struct jpeg_source_mgr*)ctx; + ctx->pub.init_source = ContextInit; + ctx->pub.fill_input_buffer = ContextFill; + ctx->pub.skip_input_data = ContextSkip; + ctx->pub.resync_to_restart = jpeg_resync_to_restart; + ctx->pub.term_source = ContextTerm; + ctx->pub.bytes_in_buffer = 0; + ctx->pub.next_input_byte = NULL; +} + +int ReadJPEG(const uint8_t* const data, size_t data_size, + WebPPicture* const pic, int keep_alpha, + Metadata* const metadata) { + volatile int ok = 0; + int width, height; + int64_t stride; + volatile struct jpeg_decompress_struct dinfo; + struct my_error_mgr jerr; + uint8_t* volatile rgb = NULL; + JSAMPROW buffer[1]; + JPEGReadContext ctx; + + if (data == NULL || data_size == 0 || pic == NULL) return 0; + + (void)keep_alpha; + memset(&ctx, 0, sizeof(ctx)); + ctx.data = data; + ctx.data_size = data_size; + + memset((j_decompress_ptr)&dinfo, 0, sizeof(dinfo)); // for setjmp safety + dinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = my_error_exit; + + if (setjmp(jerr.setjmp_buffer)) { + Error: + MetadataFree(metadata); + jpeg_destroy_decompress((j_decompress_ptr)&dinfo); + goto End; + } + + jpeg_create_decompress((j_decompress_ptr)&dinfo); + ContextSetup(&dinfo, &ctx); + if (metadata != NULL) SaveMetadataMarkers((j_decompress_ptr)&dinfo); + jpeg_read_header((j_decompress_ptr)&dinfo, TRUE); + + dinfo.out_color_space = JCS_RGB; + dinfo.do_fancy_upsampling = TRUE; + + jpeg_start_decompress((j_decompress_ptr)&dinfo); + + if (dinfo.output_components != 3) { + goto Error; + } + + width = dinfo.output_width; + height = dinfo.output_height; + stride = (int64_t)dinfo.output_width * dinfo.output_components * sizeof(*rgb); + + if (stride != (int)stride || + !ImgIoUtilCheckSizeArgumentsOverflow(stride, height)) { + goto Error; + } + + rgb = (uint8_t*)malloc((size_t)stride * height); + if (rgb == NULL) { + goto Error; + } + buffer[0] = (JSAMPLE*)rgb; + + while (dinfo.output_scanline < dinfo.output_height) { + if (jpeg_read_scanlines((j_decompress_ptr)&dinfo, buffer, 1) != 1) { + goto Error; + } + buffer[0] += stride; + } + + if (metadata != NULL) { + ok = ExtractMetadataFromJPEG((j_decompress_ptr)&dinfo, metadata); + if (!ok) { + fprintf(stderr, "Error extracting JPEG metadata!\n"); + goto Error; + } + } + + jpeg_finish_decompress((j_decompress_ptr)&dinfo); + jpeg_destroy_decompress((j_decompress_ptr)&dinfo); + + // WebP conversion. + pic->width = width; + pic->height = height; + ok = WebPPictureImportRGB(pic, rgb, (int)stride); + if (!ok) { + pic->width = 0; // WebPPictureImportRGB() barely touches 'pic' on failure. + pic->height = 0; // Just reset dimensions but keep any 'custom_ptr' etc. + MetadataFree(metadata); // In case the caller forgets to free it on error. + } + + End: + free(rgb); + return ok; +} +#else // !WEBP_HAVE_JPEG +int ReadJPEG(const uint8_t* const data, size_t data_size, + struct WebPPicture* const pic, int keep_alpha, + struct Metadata* const metadata) { + (void)data; + (void)data_size; + (void)pic; + (void)keep_alpha; + (void)metadata; + fprintf(stderr, "JPEG support not compiled. Please install the libjpeg " + "development package before building.\n"); + return 0; +} +#endif // WEBP_HAVE_JPEG + +// ----------------------------------------------------------------------------- diff --git a/third-party/webp/libwebp/imageio/jpegdec.h b/third-party/webp/libwebp/imageio/jpegdec.h new file mode 100644 index 0000000000..effc14f8c2 --- /dev/null +++ b/third-party/webp/libwebp/imageio/jpegdec.h @@ -0,0 +1,37 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// JPEG decode. + +#ifndef WEBP_IMAGEIO_JPEGDEC_H_ +#define WEBP_IMAGEIO_JPEGDEC_H_ + +#include "webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct Metadata; +struct WebPPicture; + +// Reads a JPEG from 'data', returning the decoded output in 'pic'. +// The output is RGB or YUV depending on pic->use_argb value. +// Returns true on success. +// 'keep_alpha' has no effect, but is kept for coherence with other signatures +// for image readers. +int ReadJPEG(const uint8_t* const data, size_t data_size, + struct WebPPicture* const pic, int keep_alpha, + struct Metadata* const metadata); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_IMAGEIO_JPEGDEC_H_ diff --git a/third-party/webp/libwebp/imageio/metadata.c b/third-party/webp/libwebp/imageio/metadata.c new file mode 100644 index 0000000000..936f2f4e7e --- /dev/null +++ b/third-party/webp/libwebp/imageio/metadata.c @@ -0,0 +1,49 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Metadata types and functions. +// + +#include "./metadata.h" + +#include +#include + +#include "webp/types.h" + +void MetadataInit(Metadata* const metadata) { + if (metadata == NULL) return; + memset(metadata, 0, sizeof(*metadata)); +} + +void MetadataPayloadDelete(MetadataPayload* const payload) { + if (payload == NULL) return; + free(payload->bytes); + payload->bytes = NULL; + payload->size = 0; +} + +void MetadataFree(Metadata* const metadata) { + if (metadata == NULL) return; + MetadataPayloadDelete(&metadata->exif); + MetadataPayloadDelete(&metadata->iccp); + MetadataPayloadDelete(&metadata->xmp); +} + +int MetadataCopy(const char* metadata, size_t metadata_len, + MetadataPayload* const payload) { + if (metadata == NULL || metadata_len == 0 || payload == NULL) return 0; + payload->bytes = (uint8_t*)malloc(metadata_len); + if (payload->bytes == NULL) return 0; + payload->size = metadata_len; + memcpy(payload->bytes, metadata, metadata_len); + return 1; +} + +// ----------------------------------------------------------------------------- diff --git a/third-party/webp/libwebp/imageio/metadata.h b/third-party/webp/libwebp/imageio/metadata.h new file mode 100644 index 0000000000..1d5be91a98 --- /dev/null +++ b/third-party/webp/libwebp/imageio/metadata.h @@ -0,0 +1,47 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Metadata types and functions. +// + +#ifndef WEBP_IMAGEIO_METADATA_H_ +#define WEBP_IMAGEIO_METADATA_H_ + +#include "webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct MetadataPayload { + uint8_t* bytes; + size_t size; +} MetadataPayload; + +typedef struct Metadata { + MetadataPayload exif; + MetadataPayload iccp; + MetadataPayload xmp; +} Metadata; + +#define METADATA_OFFSET(x) offsetof(Metadata, x) + +void MetadataInit(Metadata* const metadata); +void MetadataPayloadDelete(MetadataPayload* const payload); +void MetadataFree(Metadata* const metadata); + +// Stores 'metadata' to 'payload->bytes', returns false on allocation error. +int MetadataCopy(const char* metadata, size_t metadata_len, + MetadataPayload* const payload); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_IMAGEIO_METADATA_H_ diff --git a/third-party/webp/libwebp/imageio/pngdec.c b/third-party/webp/libwebp/imageio/pngdec.c new file mode 100644 index 0000000000..cdd9988399 --- /dev/null +++ b/third-party/webp/libwebp/imageio/pngdec.c @@ -0,0 +1,374 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// PNG decode. + +#include "./pngdec.h" + +#ifdef HAVE_CONFIG_H +#include "webp/config.h" +#endif + +#include + +#ifdef WEBP_HAVE_PNG +#ifndef PNG_USER_MEM_SUPPORTED +#define PNG_USER_MEM_SUPPORTED // for png_create_read_struct_2 +#endif +#include +#include // note: this must be included *after* png.h +#include +#include + +#include "webp/encode.h" +#include "./imageio_util.h" +#include "./metadata.h" + +#define LOCAL_PNG_VERSION ((PNG_LIBPNG_VER_MAJOR << 8) | PNG_LIBPNG_VER_MINOR) +#define LOCAL_PNG_PREREQ(maj, min) \ + (LOCAL_PNG_VERSION >= (((maj) << 8) | (min))) + +static void PNGAPI error_function(png_structp png, png_const_charp error) { + if (error != NULL) fprintf(stderr, "libpng error: %s\n", error); + longjmp(png_jmpbuf(png), 1); +} + +#if LOCAL_PNG_PREREQ(1,4) +typedef png_alloc_size_t LocalPngAllocSize; +#else +typedef png_size_t LocalPngAllocSize; +#endif + +static png_voidp MallocFunc(png_structp png_ptr, LocalPngAllocSize size) { + (void)png_ptr; + if (size != (size_t)size) return NULL; + if (!ImgIoUtilCheckSizeArgumentsOverflow(size, 1)) return NULL; + return (png_voidp)malloc((size_t)size); +} + +static void FreeFunc(png_structp png_ptr, png_voidp ptr) { + (void)png_ptr; + free(ptr); +} + +// Converts the NULL terminated 'hexstring' which contains 2-byte character +// representations of hex values to raw data. +// 'hexstring' may contain values consisting of [A-F][a-f][0-9] in pairs, +// e.g., 7af2..., separated by any number of newlines. +// 'expected_length' is the anticipated processed size. +// On success the raw buffer is returned with its length equivalent to +// 'expected_length'. NULL is returned if the processed length is less than +// 'expected_length' or any character aside from those above is encountered. +// The returned buffer must be freed by the caller. +static uint8_t* HexStringToBytes(const char* hexstring, + size_t expected_length) { + const char* src = hexstring; + size_t actual_length = 0; + uint8_t* const raw_data = (uint8_t*)malloc(expected_length); + uint8_t* dst; + + if (raw_data == NULL) return NULL; + + for (dst = raw_data; actual_length < expected_length && *src != '\0'; ++src) { + char* end; + char val[3]; + if (*src == '\n') continue; + val[0] = *src++; + val[1] = *src; + val[2] = '\0'; + *dst++ = (uint8_t)strtol(val, &end, 16); + if (end != val + 2) break; + ++actual_length; + } + + if (actual_length != expected_length) { + free(raw_data); + return NULL; + } + return raw_data; +} + +static int ProcessRawProfile(const char* profile, size_t profile_len, + MetadataPayload* const payload) { + const char* src = profile; + char* end; + int expected_length; + + if (profile == NULL || profile_len == 0) return 0; + + // ImageMagick formats 'raw profiles' as + // '\n\n(%8lu)\n\n'. + if (*src != '\n') { + fprintf(stderr, "Malformed raw profile, expected '\\n' got '\\x%.2X'\n", + *src); + return 0; + } + ++src; + // skip the profile name and extract the length. + while (*src != '\0' && *src++ != '\n') {} + expected_length = (int)strtol(src, &end, 10); + if (*end != '\n') { + fprintf(stderr, "Malformed raw profile, expected '\\n' got '\\x%.2X'\n", + *end); + return 0; + } + ++end; + + // 'end' now points to the profile payload. + payload->bytes = HexStringToBytes(end, expected_length); + if (payload->bytes == NULL) return 0; + payload->size = expected_length; + return 1; +} + +static const struct { + const char* name; + int (*process)(const char* profile, size_t profile_len, + MetadataPayload* const payload); + size_t storage_offset; +} kPNGMetadataMap[] = { + // https://exiftool.org/TagNames/PNG.html#TextualData + // See also: ExifTool on CPAN. + { "Raw profile type exif", ProcessRawProfile, METADATA_OFFSET(exif) }, + { "Raw profile type xmp", ProcessRawProfile, METADATA_OFFSET(xmp) }, + // Exiftool puts exif data in APP1 chunk, too. + { "Raw profile type APP1", ProcessRawProfile, METADATA_OFFSET(exif) }, + // XMP Specification Part 3, Section 3 #PNG + { "XML:com.adobe.xmp", MetadataCopy, METADATA_OFFSET(xmp) }, + { NULL, NULL, 0 }, +}; + +// Looks for metadata at both the beginning and end of the PNG file, giving +// preference to the head. +// Returns true on success. The caller must use MetadataFree() on 'metadata' in +// all cases. +static int ExtractMetadataFromPNG(png_structp png, + png_infop const head_info, + png_infop const end_info, + Metadata* const metadata) { + int p; + + for (p = 0; p < 2; ++p) { + png_infop const info = (p == 0) ? head_info : end_info; + png_textp text = NULL; + const png_uint_32 num = png_get_text(png, info, &text, NULL); + png_uint_32 i; + // Look for EXIF / XMP metadata. + for (i = 0; i < num; ++i, ++text) { + int j; + for (j = 0; kPNGMetadataMap[j].name != NULL; ++j) { + if (!strcmp(text->key, kPNGMetadataMap[j].name)) { + MetadataPayload* const payload = + (MetadataPayload*)((uint8_t*)metadata + + kPNGMetadataMap[j].storage_offset); + png_size_t text_length; + switch (text->compression) { +#ifdef PNG_iTXt_SUPPORTED + case PNG_ITXT_COMPRESSION_NONE: + case PNG_ITXT_COMPRESSION_zTXt: + text_length = text->itxt_length; + break; +#endif + case PNG_TEXT_COMPRESSION_NONE: + case PNG_TEXT_COMPRESSION_zTXt: + default: + text_length = text->text_length; + break; + } + if (payload->bytes != NULL) { + fprintf(stderr, "Ignoring additional '%s'\n", text->key); + } else if (!kPNGMetadataMap[j].process(text->text, text_length, + payload)) { + fprintf(stderr, "Failed to process: '%s'\n", text->key); + return 0; + } + break; + } + } + } + // Look for an ICC profile. + { + png_charp name; + int comp_type; +#if LOCAL_PNG_PREREQ(1,5) + png_bytep profile; +#else + png_charp profile; +#endif + png_uint_32 len; + + if (png_get_iCCP(png, info, + &name, &comp_type, &profile, &len) == PNG_INFO_iCCP) { + if (!MetadataCopy((const char*)profile, len, &metadata->iccp)) return 0; + } + } + } + return 1; +} + +typedef struct { + const uint8_t* data; + size_t data_size; + png_size_t offset; +} PNGReadContext; + +static void ReadFunc(png_structp png_ptr, png_bytep data, png_size_t length) { + PNGReadContext* const ctx = (PNGReadContext*)png_get_io_ptr(png_ptr); + if (ctx->data_size - ctx->offset < length) { + png_error(png_ptr, "ReadFunc: invalid read length (overflow)!"); + } + memcpy(data, ctx->data + ctx->offset, length); + ctx->offset += length; +} + +int ReadPNG(const uint8_t* const data, size_t data_size, + struct WebPPicture* const pic, + int keep_alpha, struct Metadata* const metadata) { + volatile png_structp png = NULL; + volatile png_infop info = NULL; + volatile png_infop end_info = NULL; + PNGReadContext context = { NULL, 0, 0 }; + int color_type, bit_depth, interlaced; + int num_channels; + int num_passes; + int p; + volatile int ok = 0; + png_uint_32 width, height, y; + int64_t stride; + uint8_t* volatile rgb = NULL; + + if (data == NULL || data_size == 0 || pic == NULL) return 0; + + context.data = data; + context.data_size = data_size; + + png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL, + NULL, MallocFunc, FreeFunc); + if (png == NULL) goto End; + + png_set_error_fn(png, 0, error_function, NULL); + if (setjmp(png_jmpbuf(png))) { + Error: + MetadataFree(metadata); + goto End; + } + +#if LOCAL_PNG_PREREQ(1,5) || \ + (LOCAL_PNG_PREREQ(1,4) && PNG_LIBPNG_VER_RELEASE >= 1) + // If it looks like the bitstream is going to need more memory than libpng's + // internal limit (default: 8M), try to (reasonably) raise it. + if (data_size > png_get_chunk_malloc_max(png) && data_size < (1u << 24)) { + png_set_chunk_malloc_max(png, data_size); + } +#endif + + info = png_create_info_struct(png); + if (info == NULL) goto Error; + end_info = png_create_info_struct(png); + if (end_info == NULL) goto Error; + + png_set_read_fn(png, &context, ReadFunc); + png_read_info(png, info); + if (!png_get_IHDR(png, info, + &width, &height, &bit_depth, &color_type, &interlaced, + NULL, NULL)) goto Error; + + png_set_strip_16(png); + png_set_packing(png); + if (color_type == PNG_COLOR_TYPE_PALETTE) { + png_set_palette_to_rgb(png); + } + if (color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { + if (bit_depth < 8) { + png_set_expand_gray_1_2_4_to_8(png); + } + png_set_gray_to_rgb(png); + } + if (png_get_valid(png, info, PNG_INFO_tRNS)) { + png_set_tRNS_to_alpha(png); + } + + // Apply gamma correction if needed. + { + double image_gamma = 1 / 2.2, screen_gamma = 2.2; + int srgb_intent; + if (png_get_sRGB(png, info, &srgb_intent) || + png_get_gAMA(png, info, &image_gamma)) { + png_set_gamma(png, screen_gamma, image_gamma); + } + } + + if (!keep_alpha) { + png_set_strip_alpha(png); + } + + num_passes = png_set_interlace_handling(png); + png_read_update_info(png, info); + + num_channels = png_get_channels(png, info); + if (num_channels != 3 && num_channels != 4) { + goto Error; + } + stride = (int64_t)num_channels * width * sizeof(*rgb); + if (stride != (int)stride || + !ImgIoUtilCheckSizeArgumentsOverflow(stride, height)) { + goto Error; + } + + rgb = (uint8_t*)malloc((size_t)stride * height); + if (rgb == NULL) goto Error; + for (p = 0; p < num_passes; ++p) { + png_bytep row = rgb; + for (y = 0; y < height; ++y) { + png_read_rows(png, &row, NULL, 1); + row += stride; + } + } + png_read_end(png, end_info); + + if (metadata != NULL && + !ExtractMetadataFromPNG(png, info, end_info, metadata)) { + fprintf(stderr, "Error extracting PNG metadata!\n"); + goto Error; + } + + pic->width = (int)width; + pic->height = (int)height; + ok = (num_channels == 4) ? WebPPictureImportRGBA(pic, rgb, (int)stride) + : WebPPictureImportRGB(pic, rgb, (int)stride); + + if (!ok) { + goto Error; + } + + End: + if (png != NULL) { + png_destroy_read_struct((png_structpp)&png, + (png_infopp)&info, (png_infopp)&end_info); + } + free(rgb); + return ok; +} +#else // !WEBP_HAVE_PNG +int ReadPNG(const uint8_t* const data, size_t data_size, + struct WebPPicture* const pic, + int keep_alpha, struct Metadata* const metadata) { + (void)data; + (void)data_size; + (void)pic; + (void)keep_alpha; + (void)metadata; + fprintf(stderr, "PNG support not compiled. Please install the libpng " + "development package before building.\n"); + return 0; +} +#endif // WEBP_HAVE_PNG + +// ----------------------------------------------------------------------------- diff --git a/third-party/webp/libwebp/imageio/pngdec.h b/third-party/webp/libwebp/imageio/pngdec.h new file mode 100644 index 0000000000..e0a6122d9d --- /dev/null +++ b/third-party/webp/libwebp/imageio/pngdec.h @@ -0,0 +1,37 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// PNG decode. + +#ifndef WEBP_IMAGEIO_PNGDEC_H_ +#define WEBP_IMAGEIO_PNGDEC_H_ + +#include "webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct Metadata; +struct WebPPicture; + +// Reads a PNG from 'data', returning the decoded output in 'pic'. +// Output is RGBA or YUVA, depending on pic->use_argb value. +// If 'keep_alpha' is true and the PNG has an alpha channel, the output is RGBA +// or YUVA. Otherwise, alpha channel is dropped and output is RGB or YUV. +// Returns true on success. +int ReadPNG(const uint8_t* const data, size_t data_size, + struct WebPPicture* const pic, + int keep_alpha, struct Metadata* const metadata); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_IMAGEIO_PNGDEC_H_ diff --git a/third-party/webp/libwebp/imageio/pnmdec.c b/third-party/webp/libwebp/imageio/pnmdec.c new file mode 100644 index 0000000000..0d592c3297 --- /dev/null +++ b/third-party/webp/libwebp/imageio/pnmdec.c @@ -0,0 +1,301 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// (limited) PNM decoder + +#include "./pnmdec.h" + +#include +#include +#include +#include +#include + +#include "webp/encode.h" +#include "./imageio_util.h" + +#if defined(_MSC_VER) && _MSC_VER < 1900 +#define snprintf _snprintf +#endif + +typedef enum { + WIDTH_FLAG = 1 << 0, + HEIGHT_FLAG = 1 << 1, + DEPTH_FLAG = 1 << 2, + MAXVAL_FLAG = 1 << 3, + TUPLE_FLAG = 1 << 4, + ALL_NEEDED_FLAGS = WIDTH_FLAG | HEIGHT_FLAG | DEPTH_FLAG | MAXVAL_FLAG +} PNMFlags; + +typedef struct { + const uint8_t* data; + size_t data_size; + int width, height; + int bytes_per_px; + int depth; // 1 (grayscale), 2 (grayscale + alpha), 3 (rgb), 4 (rgba) + int max_value; + int type; // 5, 6 or 7 + int seen_flags; +} PNMInfo; + +// ----------------------------------------------------------------------------- +// PNM decoding + +#define MAX_LINE_SIZE 1024 +static const size_t kMinPNMHeaderSize = 3; + +static size_t ReadLine(const uint8_t* const data, size_t off, size_t data_size, + char out[MAX_LINE_SIZE + 1], size_t* const out_size) { + size_t i = 0; + *out_size = 0; + redo: + for (i = 0; i < MAX_LINE_SIZE && off < data_size; ++i) { + out[i] = data[off++]; + if (out[i] == '\n') break; + } + if (off < data_size) { + if (i == 0) goto redo; // empty line + if (out[0] == '#') goto redo; // skip comment + } + out[i] = 0; // safety sentinel + *out_size = i; + return off; +} + +static size_t FlagError(const char flag[]) { + fprintf(stderr, "PAM header error: flags '%s' already seen.\n", flag); + return 0; +} + +// inspired from http://netpbm.sourceforge.net/doc/pam.html +static size_t ReadPAMFields(PNMInfo* const info, size_t off) { + char out[MAX_LINE_SIZE + 1]; + size_t out_size; + int tmp; + int expected_depth = -1; + assert(info != NULL); + while (1) { + off = ReadLine(info->data, off, info->data_size, out, &out_size); + if (off == 0) return 0; + if (sscanf(out, "WIDTH %d", &tmp) == 1) { + if (info->seen_flags & WIDTH_FLAG) return FlagError("WIDTH"); + info->seen_flags |= WIDTH_FLAG; + info->width = tmp; + } else if (sscanf(out, "HEIGHT %d", &tmp) == 1) { + if (info->seen_flags & HEIGHT_FLAG) return FlagError("HEIGHT"); + info->seen_flags |= HEIGHT_FLAG; + info->height = tmp; + } else if (sscanf(out, "DEPTH %d", &tmp) == 1) { + if (info->seen_flags & DEPTH_FLAG) return FlagError("DEPTH"); + info->seen_flags |= DEPTH_FLAG; + info->depth = tmp; + } else if (sscanf(out, "MAXVAL %d", &tmp) == 1) { + if (info->seen_flags & MAXVAL_FLAG) return FlagError("MAXVAL"); + info->seen_flags |= MAXVAL_FLAG; + info->max_value = tmp; + } else if (!strcmp(out, "TUPLTYPE RGB_ALPHA")) { + expected_depth = 4; + info->seen_flags |= TUPLE_FLAG; + } else if (!strcmp(out, "TUPLTYPE RGB")) { + expected_depth = 3; + info->seen_flags |= TUPLE_FLAG; + } else if (!strcmp(out, "TUPLTYPE GRAYSCALE_ALPHA")) { + expected_depth = 2; + info->seen_flags |= TUPLE_FLAG; + } else if (!strcmp(out, "TUPLTYPE GRAYSCALE")) { + expected_depth = 1; + info->seen_flags |= TUPLE_FLAG; + } else if (!strcmp(out, "ENDHDR")) { + break; + } else { + static const char kEllipsis[] = " ..."; + const size_t kLen = strlen(kEllipsis) + 1; // +1 = trailing \0 + int i; + if (out_size > 20) snprintf(out + 20 - kLen, kLen, kEllipsis); + for (i = 0; i < (int)strlen(out); ++i) { + // isprint() might trigger a "char-subscripts" warning if given a char. + if (!isprint((int)out[i])) out[i] = ' '; + } + fprintf(stderr, "PAM header error: unrecognized entry [%s]\n", out); + return 0; + } + } + if (!(info->seen_flags & ALL_NEEDED_FLAGS)) { + fprintf(stderr, "PAM header error: missing tags%s%s%s%s\n", + (info->seen_flags & WIDTH_FLAG) ? "" : " WIDTH", + (info->seen_flags & HEIGHT_FLAG) ? "" : " HEIGHT", + (info->seen_flags & DEPTH_FLAG) ? "" : " DEPTH", + (info->seen_flags & MAXVAL_FLAG) ? "" : " MAXVAL"); + return 0; + } + if (expected_depth != -1 && info->depth != expected_depth) { + fprintf(stderr, "PAM header error: expected DEPTH %d but got DEPTH %d\n", + expected_depth, info->depth); + return 0; + } + return off; +} + +static size_t ReadHeader(PNMInfo* const info) { + size_t off = 0; + char out[MAX_LINE_SIZE + 1]; + size_t out_size; + if (info == NULL) return 0; + if (info->data == NULL || info->data_size < kMinPNMHeaderSize) return 0; + + info->width = info->height = 0; + info->type = -1; + info->seen_flags = 0; + info->bytes_per_px = 0; + info->depth = 0; + info->max_value = 0; + + off = ReadLine(info->data, off, info->data_size, out, &out_size); + if (off == 0 || sscanf(out, "P%d", &info->type) != 1) return 0; + if (info->type == 7) { + off = ReadPAMFields(info, off); + } else { + off = ReadLine(info->data, off, info->data_size, out, &out_size); + if (off == 0 || sscanf(out, "%d %d", &info->width, &info->height) != 2) { + return 0; + } + off = ReadLine(info->data, off, info->data_size, out, &out_size); + if (off == 0 || sscanf(out, "%d", &info->max_value) != 1) return 0; + + // finish initializing missing fields + info->depth = (info->type == 5) ? 1 : 3; + } + // perform some basic numerical validation + if (info->width <= 0 || info->height <= 0 || + info->type <= 0 || info->type >= 9 || + info->depth <= 0 || info->depth > 4 || + info->max_value <= 0 || info->max_value >= 65536) { + return 0; + } + info->bytes_per_px = info->depth * (info->max_value > 255 ? 2 : 1); + return off; +} + +int ReadPNM(const uint8_t* const data, size_t data_size, + WebPPicture* const pic, int keep_alpha, + struct Metadata* const metadata) { + int ok = 0; + int i, j; + uint64_t stride, pixel_bytes, sample_size, depth; + uint8_t* rgb = NULL, *tmp_rgb; + size_t offset; + PNMInfo info; + + info.data = data; + info.data_size = data_size; + offset = ReadHeader(&info); + if (offset == 0) { + fprintf(stderr, "Error parsing PNM header.\n"); + goto End; + } + + if (info.type < 5 || info.type > 7) { + fprintf(stderr, "Unsupported P%d PNM format.\n", info.type); + goto End; + } + + // Some basic validations. + if (pic == NULL) goto End; + if (info.width > WEBP_MAX_DIMENSION || info.height > WEBP_MAX_DIMENSION) { + fprintf(stderr, "Invalid %dx%d dimension for PNM\n", + info.width, info.height); + goto End; + } + + pixel_bytes = (uint64_t)info.width * info.height * info.bytes_per_px; + if (data_size < offset + pixel_bytes) { + fprintf(stderr, "Truncated PNM file (P%d).\n", info.type); + goto End; + } + sample_size = (info.max_value > 255) ? 2 : 1; + // final depth + depth = (info.depth == 1 || info.depth == 3 || !keep_alpha) ? 3 : 4; + stride = depth * info.width; + if (stride != (size_t)stride || + !ImgIoUtilCheckSizeArgumentsOverflow(stride, info.height)) { + goto End; + } + + rgb = (uint8_t*)malloc((size_t)stride * info.height); + if (rgb == NULL) goto End; + + // Convert input. + // We only optimize for the sample_size=1, max_value=255, depth=1 case. + tmp_rgb = rgb; + for (j = 0; j < info.height; ++j) { + const uint8_t* in = data + offset; + offset += info.bytes_per_px * info.width; + assert(offset <= data_size); + if (info.max_value == 255 && info.depth >= 3) { + // RGB or RGBA + if (info.depth == 3 || keep_alpha) { + memcpy(tmp_rgb, in, info.depth * info.width * sizeof(*in)); + } else { + assert(info.depth == 4 && !keep_alpha); + for (i = 0; i < info.width; ++i) { + tmp_rgb[3 * i + 0] = in[4 * i + 0]; + tmp_rgb[3 * i + 1] = in[4 * i + 1]; + tmp_rgb[3 * i + 2] = in[4 * i + 2]; + } + } + } else { + // Unoptimized case, we need to handle non-trivial operations: + // * convert 16b to 8b (if max_value > 255) + // * rescale to [0..255] range (if max_value != 255) + // * drop the alpha channel (if keep_alpha is false) + const uint32_t round = info.max_value / 2; + int k = 0; + for (i = 0; i < info.width * info.depth; ++i) { + uint32_t v = (sample_size == 2) ? 256u * in[2 * i + 0] + in[2 * i + 1] + : in[i]; + if (info.max_value != 255) v = (v * 255u + round) / info.max_value; + if (v > 255u) v = 255u; + if (info.depth > 2) { + if (!keep_alpha && info.depth == 4 && (i % 4) == 3) { + // skip alpha + } else { + tmp_rgb[k] = v; + k += 1; + } + } else if (info.depth == 1 || (i % 2) == 0) { + tmp_rgb[k + 0] = tmp_rgb[k + 1] = tmp_rgb[k + 2] = v; + k += 3; + } else if (keep_alpha && info.depth == 2) { + tmp_rgb[k] = v; + k += 1; + } else { + // skip alpha + } + } + } + tmp_rgb += stride; + } + + // WebP conversion. + pic->width = info.width; + pic->height = info.height; + ok = (depth == 4) ? WebPPictureImportRGBA(pic, rgb, (int)stride) + : WebPPictureImportRGB(pic, rgb, (int)stride); + if (!ok) goto End; + + ok = 1; + End: + free((void*)rgb); + + (void)metadata; + (void)keep_alpha; + return ok; +} + +// ----------------------------------------------------------------------------- diff --git a/third-party/webp/libwebp/imageio/pnmdec.h b/third-party/webp/libwebp/imageio/pnmdec.h new file mode 100644 index 0000000000..c4d5823e7c --- /dev/null +++ b/third-party/webp/libwebp/imageio/pnmdec.h @@ -0,0 +1,37 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// partial PNM format decoder (ppm/pgm) + +#ifndef WEBP_IMAGEIO_PNMDEC_H_ +#define WEBP_IMAGEIO_PNMDEC_H_ + +#include "webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct Metadata; +struct WebPPicture; + +// Reads a PNM file from 'data', returning the decoded output in 'pic'. +// The output is RGB or YUV depending on pic->use_argb value. +// Returns true on success. +// 'metadata' has no effect, but is kept for coherence with other signatures +// for image readers. +int ReadPNM(const uint8_t* const data, size_t data_size, + struct WebPPicture* const pic, int keep_alpha, + struct Metadata* const metadata); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_IMAGEIO_PNMDEC_H_ diff --git a/third-party/webp/libwebp/imageio/tiffdec.c b/third-party/webp/libwebp/imageio/tiffdec.c new file mode 100644 index 0000000000..d711fa4bd2 --- /dev/null +++ b/third-party/webp/libwebp/imageio/tiffdec.c @@ -0,0 +1,293 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// TIFF decode. + +#include "./tiffdec.h" + +#ifdef HAVE_CONFIG_H +#include "webp/config.h" +#endif + +#include +#include +#include + +#ifdef WEBP_HAVE_TIFF +#include + +#include "webp/encode.h" +#include "./imageio_util.h" +#include "./metadata.h" + +static const struct { + ttag_t tag; + size_t storage_offset; +} kTIFFMetadataMap[] = { + { TIFFTAG_ICCPROFILE, METADATA_OFFSET(iccp) }, + { TIFFTAG_XMLPACKET, METADATA_OFFSET(xmp) }, + { 0, 0 }, +}; + +// Returns true on success. The caller must use MetadataFree() on 'metadata' in +// all cases. +static int ExtractMetadataFromTIFF(TIFF* const tif, Metadata* const metadata) { + int i; + toff_t exif_ifd_offset; + + for (i = 0; kTIFFMetadataMap[i].tag != 0; ++i) { + MetadataPayload* const payload = + (MetadataPayload*)((uint8_t*)metadata + + kTIFFMetadataMap[i].storage_offset); + void* tag_data; + uint32_t tag_data_len; + + if (TIFFGetField(tif, kTIFFMetadataMap[i].tag, &tag_data_len, &tag_data) && + !MetadataCopy((const char*)tag_data, tag_data_len, payload)) { + return 0; + } + } + + // TODO(jzern): To extract the raw EXIF directory some parsing of it would be + // necessary to determine the overall size. In addition, value offsets in + // individual directory entries may need to be updated as, depending on the + // type, they are file based. + // Exif 2.2 Section 4.6.2 Tag Structure + // TIFF Revision 6.0 Part 1 Section 2 TIFF Structure #Image File Directory + if (TIFFGetField(tif, TIFFTAG_EXIFIFD, &exif_ifd_offset)) { + fprintf(stderr, "Warning: EXIF extraction from TIFF is unsupported.\n"); + } + return 1; +} + +// Ad-hoc structure to supply read-from-memory functionalities. +typedef struct { + const uint8_t* data; + toff_t size; + toff_t pos; +} MyData; + +static int MyClose(thandle_t opaque) { + (void)opaque; + return 0; +} + +static toff_t MySize(thandle_t opaque) { + const MyData* const my_data = (MyData*)opaque; + return my_data->size; +} + +static toff_t MySeek(thandle_t opaque, toff_t offset, int whence) { + MyData* const my_data = (MyData*)opaque; + offset += (whence == SEEK_CUR) ? my_data->pos + : (whence == SEEK_SET) ? 0 + : my_data->size; + if (offset > my_data->size) return (toff_t)-1; + my_data->pos = offset; + return offset; +} + +static int MyMapFile(thandle_t opaque, void** base, toff_t* size) { + (void)opaque; + (void)base; + (void)size; + return 0; +} +static void MyUnmapFile(thandle_t opaque, void* base, toff_t size) { + (void)opaque; + (void)base; + (void)size; +} + +static tsize_t MyRead(thandle_t opaque, void* dst, tsize_t size) { + MyData* const my_data = (MyData*)opaque; + if (my_data->pos + size > my_data->size) { + size = (tsize_t)(my_data->size - my_data->pos); + } + if (size > 0) { + memcpy(dst, my_data->data + my_data->pos, size); + my_data->pos += size; + } + return size; +} + +// Unmultiply Argb data. Taken from dsp/alpha_processing +// (we don't want to force a dependency to a libdspdec library). +#define MFIX 24 // 24bit fixed-point arithmetic +#define HALF ((1u << MFIX) >> 1) + +static uint32_t Unmult(uint8_t x, uint32_t mult) { + const uint32_t v = (x * mult + HALF) >> MFIX; + return (v > 255u) ? 255u : v; +} + +static WEBP_INLINE uint32_t GetScale(uint32_t a) { + return (255u << MFIX) / a; +} + +#undef MFIX +#undef HALF + +static void MultARGBRow(uint8_t* ptr, int width) { + int x; + for (x = 0; x < width; ++x, ptr += 4) { + const uint32_t alpha = ptr[3]; + if (alpha < 255) { + if (alpha == 0) { // alpha == 0 + ptr[0] = ptr[1] = ptr[2] = 0; + } else { + const uint32_t scale = GetScale(alpha); + ptr[0] = Unmult(ptr[0], scale); + ptr[1] = Unmult(ptr[1], scale); + ptr[2] = Unmult(ptr[2], scale); + } + } + } +} + +int ReadTIFF(const uint8_t* const data, size_t data_size, + WebPPicture* const pic, int keep_alpha, + Metadata* const metadata) { + MyData my_data = { data, (toff_t)data_size, 0 }; + TIFF* tif; + uint32_t image_width, image_height, tile_width, tile_height; + uint64_t stride; + uint16_t samples_per_px = 0; + uint16_t extra_samples = 0; + uint16_t* extra_samples_ptr = NULL; + uint32_t* raster; + int64_t alloc_size; + int ok = 0; + tdir_t dircount; + + if (data == NULL || data_size == 0 || data_size > INT_MAX || pic == NULL) { + return 0; + } + + tif = TIFFClientOpen("Memory", "r", &my_data, + MyRead, MyRead, MySeek, MyClose, + MySize, MyMapFile, MyUnmapFile); + if (tif == NULL) { + fprintf(stderr, "Error! Cannot parse TIFF file\n"); + return 0; + } + + dircount = TIFFNumberOfDirectories(tif); + if (dircount > 1) { + fprintf(stderr, "Warning: multi-directory TIFF files are not supported.\n" + "Only the first will be used, %d will be ignored.\n", + dircount - 1); + } + if (!TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &samples_per_px)) { + fprintf(stderr, "Error! Cannot retrieve TIFF samples-per-pixel info.\n"); + goto End; + } + if (!(samples_per_px == 1 || samples_per_px == 3 || samples_per_px == 4)) { + goto End; // not supported + } + + if (!(TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &image_width) && + TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &image_height))) { + fprintf(stderr, "Error! Cannot retrieve TIFF image dimensions.\n"); + goto End; + } + stride = (uint64_t)image_width * sizeof(*raster); + if (!ImgIoUtilCheckSizeArgumentsOverflow(stride, image_height)) { + fprintf(stderr, "Error! TIFF image dimension (%d x %d) is too large.\n", + image_width, image_height); + goto End; + } + + // According to spec, a tile can be bigger than the image. However it should + // be a multiple of 16 and not way too large, so check that it's not more + // than twice the image size, for dimensions above some arbitrary minimum + // 32. We also check that they respect WebP's dimension and memory limit. + // Note that a tile can be 6byte/px in some cases. Here we assume + // 4byte/px with sizeof(*raster), to be conservative. + if (TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tile_width) && + TIFFGetField(tif, TIFFTAG_TILELENGTH, &tile_height)) { + if ((tile_width > 32 && tile_width / 2 > image_width) || + (tile_height > 32 && tile_height / 2 > image_height) || + !ImgIoUtilCheckSizeArgumentsOverflow( + (uint64_t)tile_width * sizeof(*raster), tile_height)) { + fprintf(stderr, "Error! TIFF tile dimension (%d x %d) is too large.\n", + tile_width, tile_height); + goto End; + } + } + + if (samples_per_px > 3 && !TIFFGetField(tif, TIFFTAG_EXTRASAMPLES, + &extra_samples, &extra_samples_ptr)) { + fprintf(stderr, "Error! Cannot retrieve TIFF ExtraSamples info.\n"); + goto End; + } + + // _Tiffmalloc uses a signed type for size. + alloc_size = (int64_t)(stride * image_height); + if (alloc_size < 0 || alloc_size != (tsize_t)alloc_size) goto End; + + raster = (uint32_t*)_TIFFmalloc((tsize_t)alloc_size); + if (raster != NULL) { + if (TIFFReadRGBAImageOriented(tif, image_width, image_height, raster, + ORIENTATION_TOPLEFT, 1)) { + pic->width = image_width; + pic->height = image_height; + // TIFF data is ABGR +#ifdef WORDS_BIGENDIAN + TIFFSwabArrayOfLong(raster, image_width * image_height); +#endif + // if we have an alpha channel, we must un-multiply from rgbA to RGBA + if (extra_samples == 1 && extra_samples_ptr != NULL && + extra_samples_ptr[0] == EXTRASAMPLE_ASSOCALPHA) { + uint32_t y; + uint8_t* tmp = (uint8_t*)raster; + for (y = 0; y < image_height; ++y) { + MultARGBRow(tmp, image_width); + tmp += stride; + } + } + ok = keep_alpha + ? WebPPictureImportRGBA(pic, (const uint8_t*)raster, (int)stride) + : WebPPictureImportRGBX(pic, (const uint8_t*)raster, (int)stride); + } + _TIFFfree(raster); + } else { + fprintf(stderr, "Error allocating TIFF RGBA memory!\n"); + } + + if (ok) { + if (metadata != NULL) { + ok = ExtractMetadataFromTIFF(tif, metadata); + if (!ok) { + fprintf(stderr, "Error extracting TIFF metadata!\n"); + MetadataFree(metadata); + WebPPictureFree(pic); + } + } + } + End: + TIFFClose(tif); + return ok; +} +#else // !WEBP_HAVE_TIFF +int ReadTIFF(const uint8_t* const data, size_t data_size, + struct WebPPicture* const pic, int keep_alpha, + struct Metadata* const metadata) { + (void)data; + (void)data_size; + (void)pic; + (void)keep_alpha; + (void)metadata; + fprintf(stderr, "TIFF support not compiled. Please install the libtiff " + "development package before building.\n"); + return 0; +} +#endif // WEBP_HAVE_TIFF + +// ----------------------------------------------------------------------------- diff --git a/third-party/webp/libwebp/imageio/tiffdec.h b/third-party/webp/libwebp/imageio/tiffdec.h new file mode 100644 index 0000000000..0c8beccd32 --- /dev/null +++ b/third-party/webp/libwebp/imageio/tiffdec.h @@ -0,0 +1,37 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// TIFF decode. + +#ifndef WEBP_IMAGEIO_TIFFDEC_H_ +#define WEBP_IMAGEIO_TIFFDEC_H_ + +#include "webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct Metadata; +struct WebPPicture; + +// Reads a TIFF from 'data', returning the decoded output in 'pic'. +// Output is RGBA or YUVA, depending on pic->use_argb value. +// If 'keep_alpha' is true and the TIFF has an alpha channel, the output is RGBA +// or YUVA. Otherwise, alpha channel is dropped and output is RGB or YUV. +// Returns true on success. +int ReadTIFF(const uint8_t* const data, size_t data_size, + struct WebPPicture* const pic, int keep_alpha, + struct Metadata* const metadata); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_IMAGEIO_TIFFDEC_H_ diff --git a/third-party/webp/libwebp/imageio/webpdec.c b/third-party/webp/libwebp/imageio/webpdec.c new file mode 100644 index 0000000000..aed60e14b5 --- /dev/null +++ b/third-party/webp/libwebp/imageio/webpdec.c @@ -0,0 +1,244 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// WebP decode. + +#ifdef HAVE_CONFIG_H +#include "webp/config.h" +#endif + +#include "./webpdec.h" + +#include +#include +#include + +#include "webp/decode.h" +#include "webp/demux.h" +#include "webp/encode.h" +#include "../examples/unicode.h" +#include "./imageio_util.h" +#include "./metadata.h" + +//------------------------------------------------------------------------------ +// WebP decoding + +static const char* const kStatusMessages[VP8_STATUS_NOT_ENOUGH_DATA + 1] = { + "OK", "OUT_OF_MEMORY", "INVALID_PARAM", "BITSTREAM_ERROR", + "UNSUPPORTED_FEATURE", "SUSPENDED", "USER_ABORT", "NOT_ENOUGH_DATA" +}; + +static void PrintAnimationWarning(const WebPDecoderConfig* const config) { + if (config->input.has_animation) { + fprintf(stderr, + "Error! Decoding of an animated WebP file is not supported.\n" + " Use webpmux to extract the individual frames or\n" + " vwebp to view this image.\n"); + } +} + +void PrintWebPError(const char* const in_file, int status) { + WFPRINTF(stderr, "Decoding of %s failed.\n", (const W_CHAR*)in_file); + fprintf(stderr, "Status: %d", status); + if (status >= VP8_STATUS_OK && status <= VP8_STATUS_NOT_ENOUGH_DATA) { + fprintf(stderr, "(%s)", kStatusMessages[status]); + } + fprintf(stderr, "\n"); +} + +int LoadWebP(const char* const in_file, + const uint8_t** data, size_t* data_size, + WebPBitstreamFeatures* bitstream) { + VP8StatusCode status; + WebPBitstreamFeatures local_features; + if (!ImgIoUtilReadFile(in_file, data, data_size)) return 0; + + if (bitstream == NULL) { + bitstream = &local_features; + } + + status = WebPGetFeatures(*data, *data_size, bitstream); + if (status != VP8_STATUS_OK) { + WebPFree((void*)*data); + *data = NULL; + *data_size = 0; + PrintWebPError(in_file, status); + return 0; + } + return 1; +} + +//------------------------------------------------------------------------------ + +VP8StatusCode DecodeWebP(const uint8_t* const data, size_t data_size, + WebPDecoderConfig* const config) { + if (config == NULL) return VP8_STATUS_INVALID_PARAM; + PrintAnimationWarning(config); + return WebPDecode(data, data_size, config); +} + +VP8StatusCode DecodeWebPIncremental( + const uint8_t* const data, size_t data_size, + WebPDecoderConfig* const config) { + VP8StatusCode status = VP8_STATUS_OK; + if (config == NULL) return VP8_STATUS_INVALID_PARAM; + + PrintAnimationWarning(config); + + // Decoding call. + { + WebPIDecoder* const idec = WebPIDecode(data, data_size, config); + if (idec == NULL) { + fprintf(stderr, "Failed during WebPIDecode().\n"); + return VP8_STATUS_OUT_OF_MEMORY; + } else { + status = WebPIUpdate(idec, data, data_size); + WebPIDelete(idec); + } + } + return status; +} + +// ----------------------------------------------------------------------------- +// Metadata + +static int ExtractMetadata(const uint8_t* const data, size_t data_size, + Metadata* const metadata) { + WebPData webp_data = { data, data_size }; + WebPDemuxer* const demux = WebPDemux(&webp_data); + WebPChunkIterator chunk_iter; + uint32_t flags; + + if (demux == NULL) return 0; + assert(metadata != NULL); + + flags = WebPDemuxGetI(demux, WEBP_FF_FORMAT_FLAGS); + + if ((flags & ICCP_FLAG) && WebPDemuxGetChunk(demux, "ICCP", 1, &chunk_iter)) { + MetadataCopy((const char*)chunk_iter.chunk.bytes, chunk_iter.chunk.size, + &metadata->iccp); + WebPDemuxReleaseChunkIterator(&chunk_iter); + } + if ((flags & EXIF_FLAG) && WebPDemuxGetChunk(demux, "EXIF", 1, &chunk_iter)) { + MetadataCopy((const char*)chunk_iter.chunk.bytes, chunk_iter.chunk.size, + &metadata->exif); + WebPDemuxReleaseChunkIterator(&chunk_iter); + } + if ((flags & XMP_FLAG) && WebPDemuxGetChunk(demux, "XMP ", 1, &chunk_iter)) { + MetadataCopy((const char*)chunk_iter.chunk.bytes, chunk_iter.chunk.size, + &metadata->xmp); + WebPDemuxReleaseChunkIterator(&chunk_iter); + } + WebPDemuxDelete(demux); + return 1; +} + +// ----------------------------------------------------------------------------- + +int ReadWebP(const uint8_t* const data, size_t data_size, + WebPPicture* const pic, + int keep_alpha, Metadata* const metadata) { + int ok = 0; + VP8StatusCode status = VP8_STATUS_OK; + WebPDecoderConfig config; + WebPDecBuffer* const output_buffer = &config.output; + WebPBitstreamFeatures* const bitstream = &config.input; + + if (data == NULL || data_size == 0 || pic == NULL) return 0; + + if (!WebPInitDecoderConfig(&config)) { + fprintf(stderr, "Library version mismatch!\n"); + return 0; + } + + status = WebPGetFeatures(data, data_size, bitstream); + if (status != VP8_STATUS_OK) { + PrintWebPError("input data", status); + return 0; + } + + do { + const int has_alpha = keep_alpha && bitstream->has_alpha; + uint64_t stride; + pic->width = bitstream->width; + pic->height = bitstream->height; + if (pic->use_argb) { + stride = (uint64_t)bitstream->width * 4; + } else { + stride = (uint64_t)bitstream->width * (has_alpha ? 5 : 3) / 2; + pic->colorspace = has_alpha ? WEBP_YUV420A : WEBP_YUV420; + } + + if (!ImgIoUtilCheckSizeArgumentsOverflow(stride, bitstream->height)) { + status = VP8_STATUS_OUT_OF_MEMORY; + break; + } + + ok = WebPPictureAlloc(pic); + if (!ok) { + status = VP8_STATUS_OUT_OF_MEMORY; + break; + } + if (pic->use_argb) { +#ifdef WORDS_BIGENDIAN + output_buffer->colorspace = MODE_ARGB; +#else + output_buffer->colorspace = MODE_BGRA; +#endif + output_buffer->u.RGBA.rgba = (uint8_t*)pic->argb; + output_buffer->u.RGBA.stride = pic->argb_stride * sizeof(uint32_t); + output_buffer->u.RGBA.size = output_buffer->u.RGBA.stride * pic->height; + } else { + output_buffer->colorspace = has_alpha ? MODE_YUVA : MODE_YUV; + output_buffer->u.YUVA.y = pic->y; + output_buffer->u.YUVA.u = pic->u; + output_buffer->u.YUVA.v = pic->v; + output_buffer->u.YUVA.a = has_alpha ? pic->a : NULL; + output_buffer->u.YUVA.y_stride = pic->y_stride; + output_buffer->u.YUVA.u_stride = pic->uv_stride; + output_buffer->u.YUVA.v_stride = pic->uv_stride; + output_buffer->u.YUVA.a_stride = has_alpha ? pic->a_stride : 0; + output_buffer->u.YUVA.y_size = pic->height * pic->y_stride; + output_buffer->u.YUVA.u_size = (pic->height + 1) / 2 * pic->uv_stride; + output_buffer->u.YUVA.v_size = (pic->height + 1) / 2 * pic->uv_stride; + output_buffer->u.YUVA.a_size = pic->height * pic->a_stride; + } + output_buffer->is_external_memory = 1; + + status = DecodeWebP(data, data_size, &config); + ok = (status == VP8_STATUS_OK); + if (ok && !keep_alpha && pic->use_argb) { + // Need to wipe out the alpha value, as requested. + int x, y; + uint32_t* argb = pic->argb; + for (y = 0; y < pic->height; ++y) { + for (x = 0; x < pic->width; ++x) argb[x] |= 0xff000000u; + argb += pic->argb_stride; + } + } + } while (0); // <- so we can 'break' out of the loop + + if (status != VP8_STATUS_OK) { + PrintWebPError("input data", status); + ok = 0; + } + + WebPFreeDecBuffer(output_buffer); + + if (ok && metadata != NULL) { + ok = ExtractMetadata(data, data_size, metadata); + if (!ok) { + PrintWebPError("metadata", VP8_STATUS_BITSTREAM_ERROR); + } + } + if (!ok) WebPPictureFree(pic); + return ok; +} + +// ----------------------------------------------------------------------------- diff --git a/third-party/webp/libwebp/imageio/webpdec.h b/third-party/webp/libwebp/imageio/webpdec.h new file mode 100644 index 0000000000..d329d41f3b --- /dev/null +++ b/third-party/webp/libwebp/imageio/webpdec.h @@ -0,0 +1,67 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// WebP decode. + +#ifndef WEBP_IMAGEIO_WEBPDEC_H_ +#define WEBP_IMAGEIO_WEBPDEC_H_ + +#include "webp/decode.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct Metadata; +struct WebPPicture; + +//------------------------------------------------------------------------------ +// WebP decoding + +// Prints an informative error message regarding decode failure of 'in_file'. +// 'status' is treated as a VP8StatusCode and if valid will be printed as a +// text string. +void PrintWebPError(const char* const in_file, int status); + +// Reads a WebP from 'in_file', returning the contents and size in 'data' and +// 'data_size'. If not NULL, 'bitstream' is populated using WebPGetFeatures(). +// Returns true on success. +int LoadWebP(const char* const in_file, + const uint8_t** data, size_t* data_size, + WebPBitstreamFeatures* bitstream); + +// Decodes the WebP contained in 'data'. +// 'config' is a structure previously initialized by WebPInitDecoderConfig(). +// 'config->output' should have the desired colorspace selected. +// Returns the decoder status. On success 'config->output' will contain the +// decoded picture. +VP8StatusCode DecodeWebP(const uint8_t* const data, size_t data_size, + WebPDecoderConfig* const config); + +// Same as DecodeWebP(), but using the incremental decoder. +VP8StatusCode DecodeWebPIncremental( + const uint8_t* const data, size_t data_size, + WebPDecoderConfig* const config); + +//------------------------------------------------------------------------------ + +// Decodes a WebP contained in 'data', returning the decoded output in 'pic'. +// Output is RGBA or YUVA, depending on pic->use_argb value. +// If 'keep_alpha' is true and the WebP has an alpha channel, the output is RGBA +// or YUVA. Otherwise, alpha channel is dropped and output is RGB or YUV. +// Returns true on success. +int ReadWebP(const uint8_t* const data, size_t data_size, + struct WebPPicture* const pic, + int keep_alpha, struct Metadata* const metadata); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_IMAGEIO_WEBPDEC_H_ diff --git a/third-party/webp/libwebp/imageio/wicdec.c b/third-party/webp/libwebp/imageio/wicdec.c new file mode 100644 index 0000000000..42001c6e1a --- /dev/null +++ b/third-party/webp/libwebp/imageio/wicdec.c @@ -0,0 +1,413 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Windows Imaging Component (WIC) decode. + +#include "./wicdec.h" + +#ifdef HAVE_CONFIG_H +#include "webp/config.h" +#endif + +#include +#include +#include + +#ifdef HAVE_WINCODEC_H +#ifdef __MINGW32__ +#define INITGUID // Without this GUIDs are declared extern and fail to link +#endif +#define CINTERFACE +#define COBJMACROS +#define _WIN32_IE 0x500 // Workaround bug in shlwapi.h when compiling C++ + // code with COBJMACROS. +#include // CreateStreamOnHGlobal() +#include +#include +#include +#include + +#include "../examples/unicode.h" +#include "./imageio_util.h" +#include "./metadata.h" +#include "webp/encode.h" + +#define IFS(fn) \ + do { \ + if (SUCCEEDED(hr)) { \ + hr = (fn); \ + if (FAILED(hr)) fprintf(stderr, #fn " failed %08lx\n", hr); \ + } \ + } while (0) + +// modified version of DEFINE_GUID from guiddef.h. +#define WEBP_DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + static const GUID name = \ + { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } + +#ifdef __cplusplus +#define MAKE_REFGUID(x) (x) +#else +#define MAKE_REFGUID(x) &(x) +#endif + +typedef struct WICFormatImporter { + const GUID* pixel_format; + int bytes_per_pixel; + int (*import)(WebPPicture* const, const uint8_t* const, int); +} WICFormatImporter; + +// From Microsoft SDK 7.0a -- wincodec.h +// Create local copies for compatibility when building against earlier +// versions of the SDK. +WEBP_DEFINE_GUID(GUID_WICPixelFormat24bppBGR_, + 0x6fddc324, 0x4e03, 0x4bfe, + 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0c); +WEBP_DEFINE_GUID(GUID_WICPixelFormat24bppRGB_, + 0x6fddc324, 0x4e03, 0x4bfe, + 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0d); +WEBP_DEFINE_GUID(GUID_WICPixelFormat32bppBGRA_, + 0x6fddc324, 0x4e03, 0x4bfe, + 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0f); +WEBP_DEFINE_GUID(GUID_WICPixelFormat32bppRGBA_, + 0xf5c7ad2d, 0x6a8d, 0x43dd, + 0xa7, 0xa8, 0xa2, 0x99, 0x35, 0x26, 0x1a, 0xe9); +WEBP_DEFINE_GUID(GUID_WICPixelFormat64bppBGRA_, + 0x1562ff7c, 0xd352, 0x46f9, + 0x97, 0x9e, 0x42, 0x97, 0x6b, 0x79, 0x22, 0x46); +WEBP_DEFINE_GUID(GUID_WICPixelFormat64bppRGBA_, + 0x6fddc324, 0x4e03, 0x4bfe, + 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x16); + +static HRESULT OpenInputStream(const char* filename, IStream** stream) { + HRESULT hr = S_OK; + if (!WSTRCMP(filename, "-")) { + const uint8_t* data = NULL; + size_t data_size = 0; + const int ok = ImgIoUtilReadFile(filename, &data, &data_size); + if (ok) { + HGLOBAL image = GlobalAlloc(GMEM_MOVEABLE, data_size); + if (image != NULL) { + void* const image_mem = GlobalLock(image); + if (image_mem != NULL) { + memcpy(image_mem, data, data_size); + GlobalUnlock(image); + IFS(CreateStreamOnHGlobal(image, TRUE, stream)); + } else { + hr = E_FAIL; + } + } else { + hr = E_OUTOFMEMORY; + } + free((void*)data); + } else { + hr = E_FAIL; + } + } else { + IFS(SHCreateStreamOnFile((const LPTSTR)filename, STGM_READ, stream)); + } + + if (FAILED(hr)) { + _ftprintf(stderr, _T("Error opening input file %s (%08lx)\n"), + (const LPTSTR)filename, hr); + } + return hr; +} + +// ----------------------------------------------------------------------------- +// Metadata processing + +// Stores the first non-zero sized color profile from 'frame' to 'iccp'. +// Returns an HRESULT to indicate success or failure. The caller is responsible +// for freeing 'iccp->bytes' in either case. +static HRESULT ExtractICCP(IWICImagingFactory* const factory, + IWICBitmapFrameDecode* const frame, + MetadataPayload* const iccp) { + HRESULT hr = S_OK; + UINT i, count; + IWICColorContext** color_contexts; + + IFS(IWICBitmapFrameDecode_GetColorContexts(frame, 0, NULL, &count)); + if (FAILED(hr) || count == 0) { + // Treat unsupported operation as a non-fatal error. See crbug.com/webp/506. + return (hr == WINCODEC_ERR_UNSUPPORTEDOPERATION) ? S_OK : hr; + } + + color_contexts = (IWICColorContext**)calloc(count, sizeof(*color_contexts)); + if (color_contexts == NULL) return E_OUTOFMEMORY; + for (i = 0; SUCCEEDED(hr) && i < count; ++i) { + IFS(IWICImagingFactory_CreateColorContext(factory, &color_contexts[i])); + } + + if (SUCCEEDED(hr)) { + UINT num_color_contexts; + IFS(IWICBitmapFrameDecode_GetColorContexts(frame, + count, color_contexts, + &num_color_contexts)); + assert(FAILED(hr) || num_color_contexts <= count); + for (i = 0; SUCCEEDED(hr) && i < num_color_contexts; ++i) { + WICColorContextType type; + IFS(IWICColorContext_GetType(color_contexts[i], &type)); + if (SUCCEEDED(hr) && type == WICColorContextProfile) { + UINT size; + IFS(IWICColorContext_GetProfileBytes(color_contexts[i], + 0, NULL, &size)); + if (SUCCEEDED(hr) && size > 0) { + iccp->bytes = (uint8_t*)malloc(size); + if (iccp->bytes == NULL) { + hr = E_OUTOFMEMORY; + break; + } + iccp->size = size; + IFS(IWICColorContext_GetProfileBytes(color_contexts[i], + (UINT)iccp->size, iccp->bytes, + &size)); + if (SUCCEEDED(hr) && size != iccp->size) { + fprintf(stderr, "Warning! ICC profile size (%u) != expected (%u)\n", + size, (uint32_t)iccp->size); + iccp->size = size; + } + break; + } + } + } + } + for (i = 0; i < count; ++i) { + if (color_contexts[i] != NULL) IUnknown_Release(color_contexts[i]); + } + free(color_contexts); + return hr; +} + +static HRESULT ExtractMetadata(IWICImagingFactory* const factory, + IWICBitmapFrameDecode* const frame, + Metadata* const metadata) { + // TODO(jzern): add XMP/EXIF extraction. + const HRESULT hr = ExtractICCP(factory, frame, &metadata->iccp); + if (FAILED(hr)) MetadataFree(metadata); + return hr; +} + +// ----------------------------------------------------------------------------- + +static int HasPalette(GUID pixel_format) { + return (IsEqualGUID(MAKE_REFGUID(pixel_format), + MAKE_REFGUID(GUID_WICPixelFormat1bppIndexed)) || + IsEqualGUID(MAKE_REFGUID(pixel_format), + MAKE_REFGUID(GUID_WICPixelFormat2bppIndexed)) || + IsEqualGUID(MAKE_REFGUID(pixel_format), + MAKE_REFGUID(GUID_WICPixelFormat4bppIndexed)) || + IsEqualGUID(MAKE_REFGUID(pixel_format), + MAKE_REFGUID(GUID_WICPixelFormat8bppIndexed))); +} + +static int HasAlpha(IWICImagingFactory* const factory, + IWICBitmapDecoder* const decoder, + IWICBitmapFrameDecode* const frame, + GUID pixel_format) { + int has_alpha; + if (HasPalette(pixel_format)) { + IWICPalette* frame_palette = NULL; + IWICPalette* global_palette = NULL; + BOOL frame_palette_has_alpha = FALSE; + BOOL global_palette_has_alpha = FALSE; + + // A palette may exist at the frame or container level, + // check IWICPalette::HasAlpha() for both if present. + if (SUCCEEDED(IWICImagingFactory_CreatePalette(factory, &frame_palette)) && + SUCCEEDED(IWICBitmapFrameDecode_CopyPalette(frame, frame_palette))) { + IWICPalette_HasAlpha(frame_palette, &frame_palette_has_alpha); + } + if (SUCCEEDED(IWICImagingFactory_CreatePalette(factory, &global_palette)) && + SUCCEEDED(IWICBitmapDecoder_CopyPalette(decoder, global_palette))) { + IWICPalette_HasAlpha(global_palette, &global_palette_has_alpha); + } + has_alpha = frame_palette_has_alpha || global_palette_has_alpha; + + if (frame_palette != NULL) IUnknown_Release(frame_palette); + if (global_palette != NULL) IUnknown_Release(global_palette); + } else { + has_alpha = IsEqualGUID(MAKE_REFGUID(pixel_format), + MAKE_REFGUID(GUID_WICPixelFormat32bppRGBA_)) || + IsEqualGUID(MAKE_REFGUID(pixel_format), + MAKE_REFGUID(GUID_WICPixelFormat32bppBGRA_)) || + IsEqualGUID(MAKE_REFGUID(pixel_format), + MAKE_REFGUID(GUID_WICPixelFormat64bppRGBA_)) || + IsEqualGUID(MAKE_REFGUID(pixel_format), + MAKE_REFGUID(GUID_WICPixelFormat64bppBGRA_)); + } + return has_alpha; +} + +int ReadPictureWithWIC(const char* const filename, + WebPPicture* const pic, int keep_alpha, + Metadata* const metadata) { + // From Microsoft SDK 6.0a -- ks.h + // Define a local copy to avoid link errors under mingw. + WEBP_DEFINE_GUID(GUID_NULL_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + static const WICFormatImporter kAlphaFormatImporters[] = { + { &GUID_WICPixelFormat32bppBGRA_, 4, WebPPictureImportBGRA }, + { &GUID_WICPixelFormat32bppRGBA_, 4, WebPPictureImportRGBA }, + { NULL, 0, NULL }, + }; + static const WICFormatImporter kNonAlphaFormatImporters[] = { + { &GUID_WICPixelFormat24bppBGR_, 3, WebPPictureImportBGR }, + { &GUID_WICPixelFormat24bppRGB_, 3, WebPPictureImportRGB }, + { NULL, 0, NULL }, + }; + HRESULT hr = S_OK; + IWICBitmapFrameDecode* frame = NULL; + IWICFormatConverter* converter = NULL; + IWICImagingFactory* factory = NULL; + IWICBitmapDecoder* decoder = NULL; + IStream* stream = NULL; + UINT frame_count = 0; + UINT width = 0, height = 0; + BYTE* rgb = NULL; + WICPixelFormatGUID src_pixel_format = GUID_WICPixelFormatUndefined; + const WICFormatImporter* importer = NULL; + GUID src_container_format = GUID_NULL_; + // From Windows Kits\10\Include\10.0.19041.0\um\wincodec.h + WEBP_DEFINE_GUID(GUID_ContainerFormatWebp_, + 0xe094b0e2, 0x67f2, 0x45b3, + 0xb0, 0xea, 0x11, 0x53, 0x37, 0xca, 0x7c, 0xf3); + static const GUID* kAlphaContainers[] = { + &GUID_ContainerFormatBmp, + &GUID_ContainerFormatPng, + &GUID_ContainerFormatTiff, + &GUID_ContainerFormatWebp_, + NULL + }; + int has_alpha = 0; + int64_t stride; + + if (filename == NULL || pic == NULL) return 0; + + IFS(CoInitialize(NULL)); + IFS(CoCreateInstance(MAKE_REFGUID(CLSID_WICImagingFactory), NULL, + CLSCTX_INPROC_SERVER, + MAKE_REFGUID(IID_IWICImagingFactory), + (LPVOID*)&factory)); + if (hr == REGDB_E_CLASSNOTREG) { + fprintf(stderr, + "Couldn't access Windows Imaging Component (are you running " + "Windows XP SP3 or newer?). Most formats not available. " + "Use -s for the available YUV input.\n"); + } + // Prepare for image decoding. + IFS(OpenInputStream(filename, &stream)); + IFS(IWICImagingFactory_CreateDecoderFromStream( + factory, stream, NULL, + WICDecodeMetadataCacheOnDemand, &decoder)); + IFS(IWICBitmapDecoder_GetFrameCount(decoder, &frame_count)); + if (SUCCEEDED(hr)) { + if (frame_count == 0) { + fprintf(stderr, "No frame found in input file.\n"); + hr = E_FAIL; + } else if (frame_count > 1) { + // WIC will be tried before native WebP decoding so avoid duplicating the + // error message. + hr = E_FAIL; + } + } + IFS(IWICBitmapDecoder_GetFrame(decoder, 0, &frame)); + IFS(IWICBitmapFrameDecode_GetPixelFormat(frame, &src_pixel_format)); + IFS(IWICBitmapDecoder_GetContainerFormat(decoder, &src_container_format)); + + if (SUCCEEDED(hr) && keep_alpha) { + const GUID** guid; + for (guid = kAlphaContainers; *guid != NULL; ++guid) { + if (IsEqualGUID(MAKE_REFGUID(src_container_format), + MAKE_REFGUID(**guid))) { + has_alpha = HasAlpha(factory, decoder, frame, src_pixel_format); + break; + } + } + } + + // Prepare for pixel format conversion (if necessary). + IFS(IWICImagingFactory_CreateFormatConverter(factory, &converter)); + + for (importer = has_alpha ? kAlphaFormatImporters : kNonAlphaFormatImporters; + hr == S_OK && importer->import != NULL; ++importer) { + BOOL can_convert; + const HRESULT cchr = IWICFormatConverter_CanConvert( + converter, + MAKE_REFGUID(src_pixel_format), + MAKE_REFGUID(*importer->pixel_format), + &can_convert); + if (SUCCEEDED(cchr) && can_convert) break; + } + if (importer->import == NULL) hr = E_FAIL; + + IFS(IWICFormatConverter_Initialize(converter, (IWICBitmapSource*)frame, + importer->pixel_format, + WICBitmapDitherTypeNone, + NULL, 0.0, WICBitmapPaletteTypeCustom)); + + // Decode. + IFS(IWICFormatConverter_GetSize(converter, &width, &height)); + stride = (int64_t)importer->bytes_per_pixel * width * sizeof(*rgb); + if (stride != (int)stride || + !ImgIoUtilCheckSizeArgumentsOverflow(stride, height)) { + hr = E_FAIL; + } + + if (SUCCEEDED(hr)) { + rgb = (BYTE*)malloc((size_t)stride * height); + if (rgb == NULL) + hr = E_OUTOFMEMORY; + } + IFS(IWICFormatConverter_CopyPixels(converter, NULL, + (UINT)stride, (UINT)stride * height, rgb)); + + // WebP conversion. + if (SUCCEEDED(hr)) { + int ok; + pic->width = width; + pic->height = height; + pic->use_argb = 1; // For WIC, we always force to argb + ok = importer->import(pic, rgb, (int)stride); + if (!ok) hr = E_FAIL; + } + if (SUCCEEDED(hr)) { + if (metadata != NULL) { + hr = ExtractMetadata(factory, frame, metadata); + if (FAILED(hr)) { + fprintf(stderr, "Error extracting image metadata using WIC!\n"); + } + } + } + + // Cleanup. + if (converter != NULL) IUnknown_Release(converter); + if (frame != NULL) IUnknown_Release(frame); + if (decoder != NULL) IUnknown_Release(decoder); + if (factory != NULL) IUnknown_Release(factory); + if (stream != NULL) IUnknown_Release(stream); + free(rgb); + return SUCCEEDED(hr); +} +#else // !HAVE_WINCODEC_H +int ReadPictureWithWIC(const char* const filename, + struct WebPPicture* const pic, int keep_alpha, + struct Metadata* const metadata) { + (void)filename; + (void)pic; + (void)keep_alpha; + (void)metadata; + fprintf(stderr, "Windows Imaging Component (WIC) support not compiled. " + "Visual Studio and mingw-w64 builds support WIC. Make sure " + "wincodec.h detection is working correctly if using autoconf " + "and HAVE_WINCODEC_H is defined before building.\n"); + return 0; +} +#endif // HAVE_WINCODEC_H + +// ----------------------------------------------------------------------------- diff --git a/third-party/webp/libwebp/imageio/wicdec.h b/third-party/webp/libwebp/imageio/wicdec.h new file mode 100644 index 0000000000..d9eeca8297 --- /dev/null +++ b/third-party/webp/libwebp/imageio/wicdec.h @@ -0,0 +1,34 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Windows Imaging Component (WIC) decode. + +#ifndef WEBP_IMAGEIO_WICDEC_H_ +#define WEBP_IMAGEIO_WICDEC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct Metadata; +struct WebPPicture; + +// Reads an image from 'filename', returning the decoded output in 'pic'. +// If 'keep_alpha' is true and the image has an alpha channel, the output is +// RGBA otherwise it will be RGB. pic->use_argb is always forced to true. +// Returns true on success. +int ReadPictureWithWIC(const char* const filename, + struct WebPPicture* const pic, int keep_alpha, + struct Metadata* const metadata); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_IMAGEIO_WICDEC_H_ diff --git a/third-party/webp/libwebp/infra/common.sh b/third-party/webp/libwebp/infra/common.sh new file mode 100644 index 0000000000..b4892d5479 --- /dev/null +++ b/third-party/webp/libwebp/infra/common.sh @@ -0,0 +1,106 @@ +# Copyright (c) 2021, Google Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Google nor the names of its contributors may +# be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +log_err() { + echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2 +} + +####################################### +# Create build directory. Build directory will be deleted if it exists. +# Arguments: +# None. +# Returns: +# mkdir result. +####################################### +make_build_dir() { + if [[ "$#" -ne 1 ]]; then + return 1 + fi + + local build_dir + build_dir="$1" + rm -rf "${build_dir}" + mkdir -p "${build_dir}" +} + +####################################### +# Cleanup files from the build directory. +# Globals: +# LIBWEBP_ROOT repository's root path. +# Arguments: +# $1 build directory. +####################################### +cleanup() { + # $1 is not completely removed to allow for binary artifacts to be + # extracted. + find "${1:?"Build directory not defined"}" \ + \( -name "*.[ao]" -o -name "*.l[ao]" \) -exec rm -f {} + +} + +####################################### +# Setup ccache for toolchain. +# Globals: +# PATH +# Arguments: +# None. +####################################### +setup_ccache() { + if [[ -x "$(command -v ccache)" ]]; then + export CCACHE_CPP2=yes + export PATH="/usr/lib/ccache:${PATH}" + fi +} + +####################################### +# Detects whether test block should be run in the current test shard. +# Globals: +# TEST_TOTAL_SHARDS: Valid range: [1, N]. Defaults to 1. +# TEST_SHARD_INDEX: Valid range: [0, TEST_TOTAL_SHARDS). Defaults to 0. +# libwebp_test_id: current test number; incremented with each call. +# Arguments: +# None +# Returns: +# true if the shard is active +# false if the shard is inactive +####################################### +shard_should_run() { + TEST_TOTAL_SHARDS=${TEST_TOTAL_SHARDS:=1} + TEST_SHARD_INDEX=${TEST_SHARD_INDEX:=0} + libwebp_test_id=${libwebp_test_id:=-1} + : $((libwebp_test_id += 1)) + + if [[ "${TEST_SHARD_INDEX}" -lt 0 || + "${TEST_SHARD_INDEX}" -ge "${TEST_TOTAL_SHARDS}" ]]; then + log_err "Invalid TEST_SHARD_INDEX (${TEST_SHARD_INDEX})!" \ + "Expected [0, ${TEST_TOTAL_SHARDS})." + fi + + [[ "$((libwebp_test_id % TEST_TOTAL_SHARDS))" -eq "${TEST_SHARD_INDEX}" ]] +} diff --git a/third-party/webp/libwebp/infra/compile.sh b/third-party/webp/libwebp/infra/compile.sh new file mode 100755 index 0000000000..18e9ebeeb0 --- /dev/null +++ b/third-party/webp/libwebp/infra/compile.sh @@ -0,0 +1,401 @@ +#!/bin/bash +# Copyright (c) 2021, Google Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Google nor the names of its contributors may +# be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +set -xe +LIBWEBP_ROOT="$(realpath "$(dirname "$0")/..")" +WORKSPACE=${WORKSPACE:-"$(mktemp -d -t webp.XXX)"} + +# shellcheck source=infra/common.sh +source "${LIBWEBP_ROOT}/infra/common.sh" + +usage() { + cat << EOF +Usage: compile.sh BUILD_TYPE TARGET +Options: +BUILD_TYPE supported build type: (shared, static, static-debug) +TARGET supported target platforms: + aarch64-linux-clang + aarch64-linux-gnu + arm-linux-gnueabi + arm-neon-linux-gnueabi + cmake + cmake-aarch64 + cmake-arm + cmake-clang + disable-near-lossless + disable-sse4.1 + disable-stats + force-aligned-32 + force-aligned-64 + gradle + i686-linux-asan + i686-linux-clang + i686-linux-gnu + i686-w64-mingw32 + mips2el-linux-gnu + mips32dspr2el-linux-gnu + mips32eb-linux-gnu + mips32el-linux-gnu + mips32r2el-linux-gnu + mips32r5el-linux-gnu + mips64r2el-linux-gnu + mips64r6el-linux-gnu + native + reduce-csp + reduce-size + reduce-size-disable-stats + visibility-default-gnu + visibility-hidden-clang + visibility-hidden-gnu + wasm + x86_64-linux-clang + x86_64-linux-gnu + x86_64-linux-msan + x86_64-w64-mingw32 +Environment variables: +WORKSPACE directory where the build is done +EOF +} + +################################################################################ +echo "Building libwebp in ${WORKSPACE}" + +if [[ ! -d "${WORKSPACE}" ]]; then + log_err "${WORKSPACE} directory does not exist" + exit 1 +fi + +BUILD_TYPE=${1:?"Build type not defined.$( + echo + usage +)"} +TARGET=${2:?"Target not defined.$( + echo + usage +)"} +readonly BUILD_DIR="${WORKSPACE}/build-${BUILD_TYPE}" + +trap 'cleanup ${BUILD_DIR}' EXIT +make_build_dir "${BUILD_DIR}" + +config_flags=() +case "${BUILD_TYPE}" in + shared*) ;; # Valid BUILD_TYPE but no setup required + static*) config_flags+=("--disable-shared") ;; + experimental) config_flags+=("--enable-experimental") ;; + *) + log_err "Invalid BUILD_TYPE" + usage + exit 1 + ;; +esac + +if grep -m 1 -q "enable-asserts" "${LIBWEBP_ROOT}/configure.ac"; then + config_flags+=("--enable-asserts") +fi + +case "${TARGET}" in + aarch64-linux-clang) + TARGET="aarch64-linux-gnu" + CC="clang" + CC="${CC} --target=aarch64-linux-gnu" + export CC + export CFLAGS="-isystem /usr/aarch64-linux-gnu/include" + ;; + arm-linux-gnueabi) + export CFLAGS="-O3 -march=armv7-a -mfloat-abi=softfp -ftree-vectorize" + ;; + arm-neon-linux-gnueabi) + TARGET="arm-linux-gnueabi" + CFLAGS="-O3 -march=armv7-a -mfpu=neon -mfloat-abi=softfp -ftree-vectorize" + export CFLAGS + ;; + mips2el-linux-gnu) + export CFLAGS="-EL -O2 -mips2" + TARGET="mipsel-linux-gnu" + ;; + mips32el-linux-gnu) + export CFLAGS="-EL -O2 -mips32" + TARGET="mipsel-linux-gnu" + ;; + mips32r2el-linux-gnu) + export CFLAGS="-EL -O2 -mips32r2" + TARGET="mipsel-linux-gnu" + ;; + mips32dspr2el-linux-gnu) + export CFLAGS="-EL -O2 -mdspr2" + TARGET="mipsel-linux-gnu" + ;; + mips32r5el-linux-gnu) + export CFLAGS="-EL -O2 -mips32r5 -mmsa" + TARGET="mipsel-linux-gnu" + ;; + mips32eb-linux-gnu) + export CFLAGS="-EB -O2 -mips32" + TARGET="mips-linux-gnu" + ;; + mips64r2el-linux-gnu) + export CFLAGS="-EL -O2 -mips64r2 -mabi=64" + TARGET="mips64el-linux-gnuabi64" + ;; + mips64r6el-linux-gnu) + export CFLAGS="-EL -O2 -mips64r6 -mabi=64 -mmsa" + TARGET="mips-img-linux-gnu" + ;; + i686-linux-gnu) + export CC="gcc -m32" + ;; + i686-linux-clang) + TARGET="i686-linux-gnu" + export CC="clang -m32" + ;; + i686-linux-asan) + TARGET="i686-linux-gnu" + export CC="clang -m32 -fsanitize=address" + ;; + i686-linux-msan) + TARGET="i686-linux-gnu" + export CC="clang -m32 -fsanitize=memory" + ;; + x86_64-linux-clang) + TARGET="x86_64-linux-gnu" + export CC=clang + ;; + x86_64-linux-msan) + TARGET="x86_64-linux-gnu" + export CC="clang -fsanitize=memory" + ;; + force-aligned-32) + config_flags+=("--enable-aligned") + TARGET="i686-linux-gnu" + export CC="gcc -m32" + ;; + force-aligned-64) + config_flags+=("--enable-aligned") + TARGET="x86_64-linux-gnu" + ;; + visibility-default-*) + export CFLAGS="-O2 -g -fvisibility=default" + TARGET="x86_64-linux-gnu" + ;; + visibility-hidden-*) + export CFLAGS="-O2 -g -fvisibility=hidden" + if [[ "${TARGET}" = "visibility-hidden-clang" ]]; then + export CC=clang + fi + TARGET="x86_64-linux-gnu" + ;; + disable-sse4.1) + grep "${TARGET}" "${LIBWEBP_ROOT}/configure.ac" || exit 0 + config_flags+=("--${TARGET}") + TARGET="x86_64-linux-gnu" + ;; + disable-near-lossless) + grep "${TARGET}" "${LIBWEBP_ROOT}/configure.ac" || exit 0 + config_flags+=("--${TARGET}") + TARGET="x86_64-linux-gnu" + ;; + disable-stats) + git -C "${LIBWEBP_ROOT}" grep WEBP_DISABLE_STATS || exit 0 + export CFLAGS="-O2 -g -DWEBP_DISABLE_STATS" + TARGET="x86_64-linux-gnu" + ;; + reduce-size) + git -C "${LIBWEBP_ROOT}" grep WEBP_REDUCE_SIZE || exit 0 + export CFLAGS="-O2 -g -DWEBP_REDUCE_SIZE" + TARGET="x86_64-linux-gnu" + ;; + reduce-size-disable-stats) + git -C "${LIBWEBP_ROOT}" grep -e WEBP_DISABLE_STATS -e WEBP_REDUCE_SIZE \ + || exit 0 + export CFLAGS="-O2 -g -DWEBP_DISABLE_STATS -DWEBP_REDUCE_SIZE" + TARGET="x86_64-linux-gnu" + ;; + reduce-csp) + git -C "${LIBWEBP_ROOT}" grep WEBP_REDUCE_CSP || exit 0 + export CFLAGS="-O2 -g -DWEBP_REDUCE_CSP" + TARGET="x86_64-linux-gnu" + ;; + x86_64-linux-gnu | *mingw32 | aarch64*) ;; # Default target configuration + # non-configure based builds + native) + setup_ccache + # exercise makefile.unix then quit + make -C "${LIBWEBP_ROOT}" -f makefile.unix -j all + for tgt in extras examples/anim_diff; do + grep -q -m 1 "${tgt}" "${LIBWEBP_ROOT}/makefile.unix" \ + && make -C "${LIBWEBP_ROOT}" -f makefile.unix -j "${tgt}" + done + [[ -d "${LIBWEBP_ROOT}/tests/fuzzer" ]] \ + && make -j -C "${LIBWEBP_ROOT}/tests/fuzzer" -f makefile.unix + exit 0 + ;; + cmake*) + setup_ccache + # exercise cmake then quit + opts=() + case "${TARGET}" in + cmake-clang) + opts+=("-DCMAKE_C_COMPILER=clang") + ;; + cmake-arm) + opts+=("-DCMAKE_C_COMPILER=arm-linux-gnueabi-gcc") + case "${GERRIT_BRANCH:-}" in + portable-intrinsics | 0.6.1) exit 0 ;; + *) ;; # Skip configuration + esac + ;; + cmake-aarch64) + opts+=("-DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc") + case "${GERRIT_BRANCH:-}" in + portable-intrinsics | 0.6.1) exit 0 ;; + *) ;; # Skip configuration + esac + ;; + *) ;; # Skip configuration + esac + case "${BUILD_TYPE}" in + static*) + opts+=("-DBUILD_SHARED_LIBS=OFF") + ;; + experimental) + opts+=("-DWEBP_EXPERIMENTAL_FEATURES=ON" "-DBUILD_SHARED_LIBS=ON") + ;; + *) + opts+=("-DBUILD_SHARED_LIBS=ON") + ;; + esac + case "${BUILD_TYPE}" in + *debug) opts+=("-DCMAKE_BUILD_TYPE=Debug") ;; + *) opts+=("-DCMAKE_BUILD_TYPE=RelWithDebInfo") ;; + esac + cd "${BUILD_DIR}" + opts+=("-DWEBP_BUILD_CWEBP=ON" "-DWEBP_BUILD_DWEBP=ON") + grep -m 1 -q WEBP_BUILD_GIF2WEBP "${LIBWEBP_ROOT}/CMakeLists.txt" \ + && opts+=("-DWEBP_BUILD_GIF2WEBP=ON") + grep -m 1 -q WEBP_BUILD_IMG2WEBP "${LIBWEBP_ROOT}/CMakeLists.txt" \ + && opts+=("-DWEBP_BUILD_IMG2WEBP=ON") + cmake "${opts[@]}" "${LIBWEBP_ROOT}" + make VERBOSE=1 -j + case "${BUILD_TYPE}" in + static) + mkdir -p examples + cp [cd]webp examples + ;; + *) ;; # Skip configuration. + esac + + grep "install" "${LIBWEBP_ROOT}/CMakeLists.txt" || exit 0 + + make DESTDIR="${BUILD_DIR}/webp-install" install/strip + mkdir tmp + cd tmp + cat > CMakeLists.txt << EOF +cmake_minimum_required(VERSION 2.8.7) + +project(libwebp C) + +find_package(WebP) +if (NOT WebP_FOUND) + message(FATAL_ERROR "WebP package not found") +endif () +message("WebP_FOUND: \${WebP_FOUND}") +message("WebP_INCLUDE_DIRS: \${WebP_INCLUDE_DIRS}") +message("WebP_LIBRARIES: \${WebP_LIBRARIES}") +message("WEBP_INCLUDE_DIRS: \${WEBP_INCLUDE_DIRS}") +message("WEBP_LIBRARIES: \${WEBP_LIBRARIES}") +EOF + cmake . "${opts[@]}" \ + "-DCMAKE_PREFIX_PATH=${BUILD_DIR}/webp-install/usr/local" + exit 0 + ;; + gradle) + setup_ccache + # exercise gradle then quit + [[ -f "${LIBWEBP_ROOT}/gradlew" ]] || exit 0 + + cd "${BUILD_DIR}" + # TODO -g / --gradle-user-home could be used if there's a race between jobs + "${LIBWEBP_ROOT}/gradlew" -p "${LIBWEBP_ROOT}" buildAllExecutables + exit 0 + ;; + wasm) + grep -m 1 -q WEBP_ENABLE_WASM "${LIBWEBP_ROOT}/CMakeLists.txt" || exit 0 + opts+=("-DCMAKE_C_COMPILER=clang" "-DWEBP_ENABLE_WASM=ON") + opts+=("-DWEBP_BUILD_CWEBP=ON" "-DWEBP_BUILD_DWEBP=ON") + case "${BUILD_TYPE}" in + *debug) opts+=("-DCMAKE_BUILD_TYPE=Debug") ;; + *) opts+=("-DCMAKE_BUILD_TYPE=RelWithDebInfo") ;; + esac + cd "${BUILD_DIR}" + cmake "${opts[@]}" "${LIBWEBP_ROOT}" + make VERBOSE=1 -j + mkdir examples + case "${BUILD_TYPE}" in + static) + mkdir -p examples + cp [cd]webp examples + ;; + *) ;; # Skip configuration + esac + exit 0 + ;; + *) + log_err "Invalid TARGET" + usage + exit 1 + ;; +esac + +case "${TARGET}" in + *mingw32) ;; # Skip configuration + *) + case "${TARGET}-${CC}" in + static-debug-gcc* | static-debug-) + CFLAGS="${CFLAGS} -fprofile-arcs -ftest-coverage -O0 -g" + CXXFLAGS="${CXXFLAGS} -fprofile-arcs -ftest-coverage -O0 -g" + export CFLAGS CXXFLAGS + ;; + *) ;; # This case should not be reached. + esac + ;; +esac + +setup_ccache + +cd "${LIBWEBP_ROOT}" +./autogen.sh + +cd "${BUILD_DIR}" +"${LIBWEBP_ROOT}/configure" \ + --host "${TARGET}" --build "$("${LIBWEBP_ROOT}/config.guess")" \ + --enable-everything "${config_flags[@]}" +make -j V=1 diff --git a/third-party/webp/libwebp/infra/compile_android.sh b/third-party/webp/libwebp/infra/compile_android.sh new file mode 100755 index 0000000000..013b97cdaf --- /dev/null +++ b/third-party/webp/libwebp/infra/compile_android.sh @@ -0,0 +1,224 @@ +#!/bin/bash +# Copyright (c) 2021, Google Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Google nor the names of its contributors may +# be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +set -xe +LIBWEBP_ROOT="$(realpath "$(dirname "$0")/..")" +readonly LIBWEBP_ROOT +readonly WORKSPACE=${WORKSPACE:-"$(mktemp -d -t webp.android.XXX)"} +# shellcheck source=infra/common.sh +source "${LIBWEBP_ROOT}/infra/common.sh" + +usage() { + cat << EOF +Usage: $(basename "$0") BUILD_TYPE APP_ABI +Options: +BUILD_TYPE supported build types: + static + static-debug + shared + shared-debug +APP_ABI supported application binary interfaces: + armeabi-v7a + arm64-v8a + x86 + x86_64 +Environment variables: +WORKSPACE directory where the build is done. +ANDROID_NDK_DIR directory where the android ndk tools are. +EOF +} + +################################################################################ +echo "Building libwebp for Android in ${WORKSPACE}" + +if [[ ! -d "${WORKSPACE}" ]]; then + log_err "${WORKSPACE} directory does not exist." + exit 1 +fi + +readonly BUILD_TYPE=${1:?"BUILD_TYPE is not defined.$( + echo + usage +)"} +readonly APP_ABI=${2:?"APP_ABI not defined.$( + echo + usage +)"} +readonly ANDROID_NDK_DIR=${ANDROID_NDK_DIR:?"ANDROID_NDK_DIR is not defined.$( + echo + usage +)"} +readonly BUILD_DIR="${WORKSPACE}/build-${BUILD_TYPE}" +readonly STANDALONE_ANDROID_DIR="${WORKSPACE}/android" + +if [[ ! -x "${ANDROID_NDK_DIR}/ndk-build" ]]; then + log_err "unable to find ndk-build in ANDROID_NDK_DIR: ${ANDROID_NDK_DIR}." + exit 1 +fi + +CFLAGS= +LDFLAGS= +opts=() +case "${BUILD_TYPE}" in + *debug) + readonly APP_OPTIM="debug" + CFLAGS="-O0 -g" + opts+=("--enable-asserts") + ;; + static* | shared*) + readonly APP_OPTIM="release" + CFLAGS="-O2 -g" + ;; + *) + usage + exit 1 + ;; +esac + +case "${BUILD_TYPE}" in + shared*) readonly SHARED="1" ;; + *) + readonly SHARED="0" + CFLAGS="${CFLAGS} -fPIE" + LDFLAGS="${LDFLAGS} -Wl,-pie" + opts+=("--disable-shared") + ;; +esac + +# Create a fresh build directory +make_build_dir "${BUILD_DIR}" +cd "${BUILD_DIR}" +ln -s "${LIBWEBP_ROOT}" jni + +"${ANDROID_NDK_DIR}/ndk-build" -j2 \ + APP_ABI="${APP_ABI}" \ + APP_OPTIM="${APP_OPTIM}" \ + ENABLE_SHARED="${SHARED}" + +cd "${LIBWEBP_ROOT}" +./autogen.sh + +case "${APP_ABI}" in + armeabi*) arch="arm" ;; + arm64*) arch="arm64" ;; + *) arch="${APP_ABI}" ;; +esac +# TODO(b/185520507): remove this and use the binaries from +# toolchains/llvm/prebuilt/ directly. +rm -rf "${STANDALONE_ANDROID_DIR}" +"${ANDROID_NDK_DIR}/build/tools/make_standalone_toolchain.py" \ + --api 24 --arch "${arch}" --stl gnustl --install-dir \ + "${STANDALONE_ANDROID_DIR}" +export PATH="${STANDALONE_ANDROID_DIR}/bin:${PATH}" + +rm -rf "${BUILD_DIR}" +make_build_dir "${BUILD_DIR}" +cd "${BUILD_DIR}" + +case "${arch}" in + arm) + host="arm-linux-androideabi" + case "${APP_ABI}" in + armeabi) ;; + armeabi-v7a) + CFLAGS="${CFLAGS} -march=armv7-a -mfpu=neon -mfloat-abi=softfp" + ;; + *) ;; # No configuration needed + esac + ;; + arm64) + host="aarch64-linux-android" + ;; + x86) + host="i686-linux-android" + ;; + x86_64) + host="x86_64-linux-android" + ;; + *) ;; # Skip configuration +esac + +setup_ccache +CC="clang" + +"${LIBWEBP_ROOT}/configure" --host "${host}" --build \ + "$("${LIBWEBP_ROOT}/config.guess")" CC="${CC}" CFLAGS="${CFLAGS}" \ + LDFLAGS="${LDFLAGS}" "${opts[@]}" +make -j + +if [[ "${GERRIT_REFSPEC:-}" = "refs/heads/portable-intrinsics" ]] \ + || [[ "${GERRIT_BRANCH:-}" = "portable-intrinsics" ]]; then + cd "${WORKSPACE}" + rm -rf build && mkdir build + cd build + standalone="${WORKSPACE}/android" + cmake ../libwebp \ + -DWEBP_BUILD_DWEBP=1 \ + -DCMAKE_C_COMPILER="${standalone}/bin/clang" \ + -DCMAKE_PREFIX_PATH="${standalone}/sysroot/usr/lib" \ + -DCMAKE_C_FLAGS=-fPIE \ + -DCMAKE_EXE_LINKER_FLAGS=-Wl,-pie \ + -DCMAKE_BUILD_TYPE=Release \ + -DWEBP_ENABLE_WASM=1 + make -j2 + + cd "${WORKSPACE}" + make_build_dir "${BUILD_DIR}" + cd "${BUILD_DIR}" + case "${APP_ABI}" in + armeabi-v7a | arm64*) + cmake "${LIBWEBP_ROOT}" \ + -DWEBP_BUILD_DWEBP=1 \ + -DCMAKE_C_COMPILER="${standalone}/bin/clang" \ + -DCMAKE_PREFIX_PATH="${standalone}/sysroot/usr/lib" \ + -DCMAKE_C_FLAGS='-fPIE -DENABLE_NEON_BUILTIN_MULHI_INT16X8' \ + -DCMAKE_EXE_LINKER_FLAGS=-Wl,-pie \ + -DCMAKE_BUILD_TYPE=Release \ + -DWEBP_ENABLE_WASM=1 + make -j2 + ;; + x86*) + cmake "${LIBWEBP_ROOT}" \ + -DWEBP_BUILD_DWEBP=1 \ + -DCMAKE_C_COMPILER="${standalone}/bin/clang" \ + -DCMAKE_PREFIX_PATH="${standalone}/sysroot/usr/lib" \ + -DCMAKE_C_FLAGS='-fPIE -DENABLE_X86_BUILTIN_MULHI_INT16X8' \ + -DCMAKE_EXE_LINKER_FLAGS=-Wl,-pie \ + -DCMAKE_BUILD_TYPE=Release \ + -DWEBP_ENABLE_WASM=1 + make -j2 + ;; + *) + log_err "APP_ABI not supported." + exit 1 + ;; + esac +fi diff --git a/third-party/webp/libwebp/infra/compile_js.sh b/third-party/webp/libwebp/infra/compile_js.sh new file mode 100755 index 0000000000..6a13fe6a2e --- /dev/null +++ b/third-party/webp/libwebp/infra/compile_js.sh @@ -0,0 +1,75 @@ +#!/bin/bash +# Copyright (c) 2021, Google Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Google nor the names of its contributors may +# be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +set -ex + +readonly WORKSPACE="${WORKSPACE:-"$(mktemp -d -t webp.js.XXX)"}" +readonly BUILD_DIR="${WORKSPACE}/webp_js/" +readonly LIBWEBP_ROOT="$(realpath "$(dirname "$0")/..")" + +# shellcheck source=infra/common.sh +source "${LIBWEBP_ROOT}/infra/common.sh" + +usage() { + cat << EOF +Usage: $(basename "$0") +Environment variables: +WORKSPACE directory where the build is done +EMSDK_DIR directory where emsdk is installed +EOF +} + +[[ -d "${EMSDK_DIR:?Not defined}" ]] \ + || (log_err "${EMSDK_DIR} is not a valid directory." && exit 1) + +# shellcheck source=/opt/emsdk/emsdk_env.sh +source "${EMSDK_DIR}/emsdk_env.sh" + +readonly EMSCRIPTEN=${EMSCRIPTEN:-"${EMSDK}/upstream/emscripten"} +readonly \ + EMSCRIPTEN_CMAKE_FILE="${EMSCRIPTEN}/cmake/Modules/Platform/Emscripten.cmake" +make_build_dir "${BUILD_DIR}" + +pushd "${BUILD_DIR}" +opts=("-GUnix Makefiles" "-DWEBP_BUILD_WEBP_JS=ON") +if [[ -z "$(command -v emcmake)" ]]; then + opts+=("-DCMAKE_TOOLCHAIN_FILE=${EMSCRIPTEN_CMAKE_FILE}") + cmake \ + "${opts[@]}" \ + "${LIBWEBP_ROOT}" + make -j +else + emcmake cmake \ + "${opts[@]}" \ + "${LIBWEBP_ROOT}" + emmake make -j +fi +popd diff --git a/third-party/webp/libwebp/infra/run_static_analysis.sh b/third-party/webp/libwebp/infra/run_static_analysis.sh new file mode 100755 index 0000000000..fa8445caa6 --- /dev/null +++ b/third-party/webp/libwebp/infra/run_static_analysis.sh @@ -0,0 +1,98 @@ +#!/bin/bash +# Copyright (c) 2021, Google Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Google nor the names of its contributors may +# be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +set -xe + +LIBWEBP_ROOT="$(realpath "$(dirname "$0")/..")" +readonly LIBWEBP_ROOT +readonly WORKSPACE=${WORKSPACE:-"$(mktemp -d -t webp.scanbuild.XXX)"} + +# shellcheck source=infra/common.sh +source "${LIBWEBP_ROOT}/infra/common.sh" + +usage() { + cat << EOF +Usage: $(basename "$0") MODE +Options: +MODE supported scan modes: (shallow|deep) +Environment variables: +WORKSPACE directory where the build is done. +EOF +} + +####################################### +# Wrap clang-tools scan-build. +# Globals: +# OUTPUT_DIR target directory where scan-build report is generated. +# MODE scan-build mode +# Arguments: +# $* scan-build additional args. +# Returns: +# scan-build retcode +####################################### +scan_build() { + scan-build -o "${OUTPUT_DIR}" --use-analyzer="$(command -v clang)" \ + -analyzer-config mode="${MODE}" "$*" +} + +MODE=${1:?"MODE is not specified.$( + echo + usage +)"} + +readonly OUTPUT_DIR="${WORKSPACE}/output-${MODE}" +readonly BUILD_DIR="${WORKSPACE}/build" + +make_build_dir "${OUTPUT_DIR}" +make_build_dir "${BUILD_DIR}" + +cd "${LIBWEBP_ROOT}" +./autogen.sh + +cd "${BUILD_DIR}" +grep -m 1 -q 'enable-asserts' "${LIBWEBP_ROOT}/configure.ac" \ + && args='--enable-asserts' +scan_build "${LIBWEBP_ROOT}/configure" --enable-everything "${args}" +scan_build make -j4 + +index="$(find "${OUTPUT_DIR}" -name index.html)" +if [[ -f "${index}" ]]; then + mv "$(dirname "${index}")/"* "${OUTPUT_DIR}" +else + # make a empty report to wipe out any old bug reports. + cat << EOT > "${OUTPUT_DIR}/index.html" + + +No bugs reported. + + +EOT +fi diff --git a/third-party/webp/libwebp/iosbuild.sh b/third-party/webp/libwebp/iosbuild.sh new file mode 100755 index 0000000000..cd3a24cf52 --- /dev/null +++ b/third-party/webp/libwebp/iosbuild.sh @@ -0,0 +1,168 @@ +#!/bin/bash +# +# This script generates 'WebP.framework' and 'WebPDecoder.framework', +# 'WebPDemux.framework' and 'WebPMux.framework'. +# An iOS app can decode WebP images by including 'WebPDecoder.framework' and +# both encode and decode WebP images by including 'WebP.framework'. +# +# Run ./iosbuild.sh to generate the frameworks under the current directory +# (the previous build will be erased if it exists). +# +# This script is inspired by the build script written by Carson McDonald. +# (https://www.ioncannon.net/programming/1483/using-webp-to-reduce-native-ios-app-size/). + +set -e + +# Set this variable based on the desired minimum deployment target. +readonly IOS_MIN_VERSION=6.0 + +# Extract the latest SDK version from the final field of the form: iphoneosX.Y +readonly SDK=$(xcodebuild -showsdks \ + | grep iphoneos | sort | tail -n 1 | awk '{print substr($NF, 9)}' +) +# Extract Xcode version. +readonly XCODE=$(xcodebuild -version | grep Xcode | cut -d " " -f2) +if [[ -z "${XCODE}" ]]; then + echo "Xcode not available" + exit 1 +fi + +readonly OLDPATH=${PATH} + +# Add iPhoneOS-V6 to the list of platforms below if you need armv6 support. +# Note that iPhoneOS-V6 support is not available with the iOS6 SDK. +PLATFORMS="iPhoneSimulator iPhoneSimulator64" +PLATFORMS+=" iPhoneOS-V7 iPhoneOS-V7s iPhoneOS-V7-arm64" +readonly PLATFORMS +readonly SRCDIR=$(dirname $0) +readonly TOPDIR=$(pwd) +readonly BUILDDIR="${TOPDIR}/iosbuild" +readonly TARGETDIR="${TOPDIR}/WebP.framework" +readonly DECTARGETDIR="${TOPDIR}/WebPDecoder.framework" +readonly MUXTARGETDIR="${TOPDIR}/WebPMux.framework" +readonly DEMUXTARGETDIR="${TOPDIR}/WebPDemux.framework" +readonly DEVELOPER=$(xcode-select --print-path) +readonly PLATFORMSROOT="${DEVELOPER}/Platforms" +readonly LIPO=$(xcrun -sdk iphoneos${SDK} -find lipo) +LIBLIST='' +DECLIBLIST='' +MUXLIBLIST='' +DEMUXLIBLIST='' + +if [[ -z "${SDK}" ]]; then + echo "iOS SDK not available" + exit 1 +elif [[ ${SDK%%.*} -gt 8 ]]; then + EXTRA_CFLAGS="-fembed-bitcode" +elif [[ ${SDK%%.*} -le 6 ]]; then + echo "You need iOS SDK version 6.0 or above" + exit 1 +fi + +echo "Xcode Version: ${XCODE}" +echo "iOS SDK Version: ${SDK}" + +if [[ -e "${BUILDDIR}" || -e "${TARGETDIR}" || -e "${DECTARGETDIR}" \ + || -e "${MUXTARGETDIR}" || -e "${DEMUXTARGETDIR}" ]]; then + cat << EOF +WARNING: The following directories will be deleted: +WARNING: ${BUILDDIR} +WARNING: ${TARGETDIR} +WARNING: ${DECTARGETDIR} +WARNING: ${MUXTARGETDIR} +WARNING: ${DEMUXTARGETDIR} +WARNING: The build will continue in 5 seconds... +EOF + sleep 5 +fi +rm -rf ${BUILDDIR} ${TARGETDIR} ${DECTARGETDIR} \ + ${MUXTARGETDIR} ${DEMUXTARGETDIR} +mkdir -p ${BUILDDIR} ${TARGETDIR}/Headers/ ${DECTARGETDIR}/Headers/ \ + ${MUXTARGETDIR}/Headers/ ${DEMUXTARGETDIR}/Headers/ + +if [[ ! -e ${SRCDIR}/configure ]]; then + if ! (cd ${SRCDIR} && sh autogen.sh); then + cat << EOF +Error creating configure script! +This script requires the autoconf/automake and libtool to build. MacPorts can +be used to obtain these: +https://www.macports.org/install.php +EOF + exit 1 + fi +fi + +for PLATFORM in ${PLATFORMS}; do + ARCH2="" + if [[ "${PLATFORM}" == "iPhoneOS-V7-arm64" ]]; then + PLATFORM="iPhoneOS" + ARCH="aarch64" + ARCH2="arm64" + elif [[ "${PLATFORM}" == "iPhoneOS-V7s" ]]; then + PLATFORM="iPhoneOS" + ARCH="armv7s" + elif [[ "${PLATFORM}" == "iPhoneOS-V7" ]]; then + PLATFORM="iPhoneOS" + ARCH="armv7" + elif [[ "${PLATFORM}" == "iPhoneOS-V6" ]]; then + PLATFORM="iPhoneOS" + ARCH="armv6" + elif [[ "${PLATFORM}" == "iPhoneSimulator64" ]]; then + PLATFORM="iPhoneSimulator" + ARCH="x86_64" + else + ARCH="i386" + fi + + ROOTDIR="${BUILDDIR}/${PLATFORM}-${SDK}-${ARCH}" + mkdir -p "${ROOTDIR}" + + DEVROOT="${DEVELOPER}/Toolchains/XcodeDefault.xctoolchain" + SDKROOT="${PLATFORMSROOT}/" + SDKROOT+="${PLATFORM}.platform/Developer/SDKs/${PLATFORM}${SDK}.sdk/" + CFLAGS="-arch ${ARCH2:-${ARCH}} -pipe -isysroot ${SDKROOT} -O3 -DNDEBUG" + CFLAGS+=" -miphoneos-version-min=${IOS_MIN_VERSION} ${EXTRA_CFLAGS}" + + set -x + export PATH="${DEVROOT}/usr/bin:${OLDPATH}" + ${SRCDIR}/configure --host=${ARCH}-apple-darwin --prefix=${ROOTDIR} \ + --build=$(${SRCDIR}/config.guess) \ + --disable-shared --enable-static \ + --enable-libwebpdecoder --enable-swap-16bit-csp \ + --enable-libwebpmux \ + CFLAGS="${CFLAGS}" + set +x + + # Build only the libraries, skip the examples. + make V=0 -C sharpyuv + make V=0 -C src install + + LIBLIST+=" ${ROOTDIR}/lib/libwebp.a" + DECLIBLIST+=" ${ROOTDIR}/lib/libwebpdecoder.a" + MUXLIBLIST+=" ${ROOTDIR}/lib/libwebpmux.a" + DEMUXLIBLIST+=" ${ROOTDIR}/lib/libwebpdemux.a" + + make clean + + export PATH=${OLDPATH} +done + +echo "LIBLIST = ${LIBLIST}" +cp -a ${SRCDIR}/src/webp/{decode,encode,types}.h ${TARGETDIR}/Headers/ +${LIPO} -create ${LIBLIST} -output ${TARGETDIR}/WebP + +echo "DECLIBLIST = ${DECLIBLIST}" +cp -a ${SRCDIR}/src/webp/{decode,types}.h ${DECTARGETDIR}/Headers/ +${LIPO} -create ${DECLIBLIST} -output ${DECTARGETDIR}/WebPDecoder + +echo "MUXLIBLIST = ${MUXLIBLIST}" +cp -a ${SRCDIR}/src/webp/{types,mux,mux_types}.h \ + ${MUXTARGETDIR}/Headers/ +${LIPO} -create ${MUXLIBLIST} -output ${MUXTARGETDIR}/WebPMux + +echo "DEMUXLIBLIST = ${DEMUXLIBLIST}" +cp -a ${SRCDIR}/src/webp/{decode,types,mux_types,demux}.h \ + ${DEMUXTARGETDIR}/Headers/ +${LIPO} -create ${DEMUXLIBLIST} -output ${DEMUXTARGETDIR}/WebPDemux + +echo "SUCCESS" diff --git a/third-party/webp/libwebp/m4/ax_pthread.m4 b/third-party/webp/libwebp/m4/ax_pthread.m4 new file mode 100644 index 0000000000..d383ad5c6d --- /dev/null +++ b/third-party/webp/libwebp/m4/ax_pthread.m4 @@ -0,0 +1,332 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_pthread.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) +# +# DESCRIPTION +# +# This macro figures out how to build C programs using POSIX threads. It +# sets the PTHREAD_LIBS output variable to the threads library and linker +# flags, and the PTHREAD_CFLAGS output variable to any special C compiler +# flags that are needed. (The user can also force certain compiler +# flags/libs to be tested by setting these environment variables.) +# +# Also sets PTHREAD_CC to any special C compiler that is needed for +# multi-threaded programs (defaults to the value of CC otherwise). (This +# is necessary on AIX to use the special cc_r compiler alias.) +# +# NOTE: You are assumed to not only compile your program with these flags, +# but also link it with them as well. e.g. you should link with +# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS +# +# If you are only building threads programs, you may wish to use these +# variables in your default LIBS, CFLAGS, and CC: +# +# LIBS="$PTHREAD_LIBS $LIBS" +# CFLAGS="$CFLAGS $PTHREAD_CFLAGS" +# CC="$PTHREAD_CC" +# +# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant +# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name +# (e.g. PTHREAD_CREATE_UNDETACHED on AIX). +# +# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the +# PTHREAD_PRIO_INHERIT symbol is defined when compiling with +# PTHREAD_CFLAGS. +# +# ACTION-IF-FOUND is a list of shell commands to run if a threads library +# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it +# is not found. If ACTION-IF-FOUND is not specified, the default action +# will define HAVE_PTHREAD. +# +# Please let the authors know if this macro fails on any platform, or if +# you have any other suggestions or comments. This macro was based on work +# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help +# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by +# Alejandro Forero Cuervo to the autoconf macro repository. We are also +# grateful for the helpful feedback of numerous users. +# +# Updated for Autoconf 2.68 by Daniel Richard G. +# +# LICENSE +# +# Copyright (c) 2008 Steven G. Johnson +# Copyright (c) 2011 Daniel Richard G. +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 21 + +AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) +AC_DEFUN([AX_PTHREAD], [ +AC_REQUIRE([AC_CANONICAL_HOST]) +AC_LANG_PUSH([C]) +ax_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on True64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) + AC_TRY_LINK_FUNC([pthread_join], [ax_pthread_ok=yes]) + AC_MSG_RESULT([$ax_pthread_ok]) + if test x"$ax_pthread_ok" = xno; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items starting with a "-" are +# C compiler flags, and other items are library names, except for "none" +# which indicates that we try without any flags at all, and "pthread-config" +# which is a program returning the flags for the Pth emulation library. + +ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) +# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) +# -pthreads: Solaris/gcc +# -mthreads: Mingw32/gcc, Lynx/gcc +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads too; +# also defines -D_REENTRANT) +# ... -mt is also the pthreads flag for HP/aCC +# pthread: Linux, etcetera +# --thread-safe: KAI C++ +# pthread-config: use pthread-config program (for GNU Pth library) + +case ${host_os} in + solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (We need to link with -pthreads/-mt/ + # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather + # a function called by this macro, so we could check for that, but + # who knows whether they'll stub that too in a future libc.) So, + # we'll just look for -pthreads and -lpthread first: + + ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags" + ;; + + darwin*) + ax_pthread_flags="-pthread $ax_pthread_flags" + ;; +esac + +# Clang doesn't consider unrecognized options an error unless we specify +# -Werror. We throw in some extra Clang-specific options to ensure that +# this doesn't happen for GCC, which also accepts -Werror. + +AC_MSG_CHECKING([if compiler needs -Werror to reject unknown flags]) +save_CFLAGS="$CFLAGS" +ax_pthread_extra_flags="-Werror" +CFLAGS="$CFLAGS $ax_pthread_extra_flags -Wunknown-warning-option -Wsizeof-array-argument" +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int foo(void);],[foo()])], + [AC_MSG_RESULT([yes])], + [ax_pthread_extra_flags= + AC_MSG_RESULT([no])]) +CFLAGS="$save_CFLAGS" + +if test x"$ax_pthread_ok" = xno; then +for flag in $ax_pthread_flags; do + + case $flag in + none) + AC_MSG_CHECKING([whether pthreads work without any flags]) + ;; + + -*) + AC_MSG_CHECKING([whether pthreads work with $flag]) + PTHREAD_CFLAGS="$flag" + ;; + + pthread-config) + AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) + if test x"$ax_pthread_config" = xno; then continue; fi + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + AC_MSG_CHECKING([for the pthreads library -l$flag]) + PTHREAD_LIBS="-l$flag" + ;; + esac + + save_LIBS="$LIBS" + save_CFLAGS="$CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS $ax_pthread_extra_flags" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include + static void routine(void *a) { a = 0; } + static void *start_routine(void *a) { return a; }], + [pthread_t th; pthread_attr_t attr; + pthread_create(&th, 0, start_routine, 0); + pthread_join(th, 0); + pthread_attr_init(&attr); + pthread_cleanup_push(routine, 0); + pthread_cleanup_pop(0) /* ; */])], + [ax_pthread_ok=yes], + []) + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + AC_MSG_RESULT([$ax_pthread_ok]) + if test "x$ax_pthread_ok" = xyes; then + break; + fi + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + +# Various other checks: +if test "x$ax_pthread_ok" = xyes; then + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. + AC_MSG_CHECKING([for joinable pthread attribute]) + attr_name=unknown + for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], + [int attr = $attr; return attr /* ; */])], + [attr_name=$attr; break], + []) + done + AC_MSG_RESULT([$attr_name]) + if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then + AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], [$attr_name], + [Define to necessary symbol if this constant + uses a non-standard name on your system.]) + fi + + AC_MSG_CHECKING([if more special flags are required for pthreads]) + flag=no + case ${host_os} in + aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";; + osf* | hpux*) flag="-D_REENTRANT";; + solaris*) + if test "$GCC" = "yes"; then + flag="-D_REENTRANT" + else + # TODO: What about Clang on Solaris? + flag="-mt -D_REENTRANT" + fi + ;; + esac + AC_MSG_RESULT([$flag]) + if test "x$flag" != xno; then + PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" + fi + + AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], + [ax_cv_PTHREAD_PRIO_INHERIT], [ + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], + [[int i = PTHREAD_PRIO_INHERIT;]])], + [ax_cv_PTHREAD_PRIO_INHERIT=yes], + [ax_cv_PTHREAD_PRIO_INHERIT=no]) + ]) + AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"], + [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])]) + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + # More AIX lossage: compile with *_r variant + if test "x$GCC" != xyes; then + case $host_os in + aix*) + AS_CASE(["x/$CC"], + [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], + [#handle absolute path differently from PATH based program lookup + AS_CASE(["x$CC"], + [x/*], + [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], + [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) + ;; + esac + fi +fi + +test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" + +AC_SUBST([PTHREAD_LIBS]) +AC_SUBST([PTHREAD_CFLAGS]) +AC_SUBST([PTHREAD_CC]) + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test x"$ax_pthread_ok" = xyes; then + ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) + : +else + ax_pthread_ok=no + $2 +fi +AC_LANG_POP +])dnl AX_PTHREAD diff --git a/third-party/webp/libwebp/makefile.unix b/third-party/webp/libwebp/makefile.unix new file mode 100644 index 0000000000..857ea9880a --- /dev/null +++ b/third-party/webp/libwebp/makefile.unix @@ -0,0 +1,538 @@ +# This makefile is a simpler alternative to the autoconf-based build +# system, for simple local building of the libraries and tools. +# It will not install the libraries system-wide, but just create the 'cwebp' +# and 'dwebp' tools in the examples/ directory, along with the static +# libraries 'src/libwebp.a', 'src/libwebpdecoder.a', 'src/mux/libwebpmux.a', +# 'src/demux/libwebpdemux.a', 'extras/libwebpextras.a' and +# 'sharpyuv/libsharpyuv.a'. +# +# To build the library and examples, use: +# make -f makefile.unix +# from this top directory. + +#### Customizable part #### + +# These flags assume you have libpng, libjpeg, libtiff and libgif installed. If +# not, either follow the install instructions below or just comment out the next +# four lines. +EXTRA_FLAGS= -DWEBP_HAVE_PNG -DWEBP_HAVE_JPEG -DWEBP_HAVE_TIFF +DWEBP_LIBS= -lpng -lz +CWEBP_LIBS= $(DWEBP_LIBS) -ljpeg -ltiff +GIF_LIBS = -lgif + +ifeq ($(strip $(shell uname)), Darwin) + # Work around a problem linking tables marked as common symbols, + # cf., src/enc/yuv.[hc] + # Failure observed with: gcc 4.2.1 and 4.0.1. + EXTRA_FLAGS += -fno-common + EXTRA_FLAGS += -DHAVE_GLUT_GLUT_H + EXTRA_FLAGS += -Wno-deprecated-declarations + EXTRA_FLAGS += -I/opt/local/include + EXTRA_LIBS += -L/opt/local/lib + GL_LIBS = -framework GLUT -framework OpenGL +else + EXTRA_FLAGS += -I/usr/local/include + EXTRA_LIBS += -L/usr/local/lib + GL_LIBS = -lglut -lGL +endif + +# SDL flags: use sdl-config if it exists +SDL_CONFIG = $(shell sdl-config --version 2> /dev/null) +ifneq ($(SDL_CONFIG),) + SDL_LIBS = $(shell sdl-config --libs) + SDL_FLAGS = $(shell sdl-config --cflags) +else + # use best-guess + SDL_LIBS = -lSDL + SDL_FLAGS = +endif + +# To install libraries on Mac OS X: +# 1. Install MacPorts (https://www.macports.org/install.php) +# 2. Run "sudo port install jpeg" +# 3. Run "sudo port install libpng" +# 4. Run "sudo port install tiff" +# 5. Run "sudo port install giflib" + +# To install libraries on Linux: +# 1. Run "sudo apt-get install libjpeg62-dev" +# 2. Run "sudo apt-get install libpng12-dev" +# 3. Run "sudo apt-get install libtiff4-dev" +# 4. Run "sudo apt-get install libgif-dev" + +# Uncomment for build for 32bit platform +# Alternatively, you can just use the command +# 'make -f makefile.unix EXTRA_FLAGS=-m32' to that effect. +# EXTRA_FLAGS += -m32 + +# Extra flags to enable byte swap for 16 bit colorspaces. +# EXTRA_FLAGS += -DWEBP_SWAP_16BIT_CSP=1 + +# Extra flags to enable multi-threading +EXTRA_FLAGS += -DWEBP_USE_THREAD +EXTRA_LIBS += -lpthread + +# Control symbol visibility. Comment out if your compiler doesn't support it. +EXTRA_FLAGS += -fvisibility=hidden + +# Extra flags to emulate C89 strictness with the full ANSI +EXTRA_FLAGS += -Wextra -Wold-style-definition +EXTRA_FLAGS += -Wmissing-prototypes +EXTRA_FLAGS += -Wmissing-declarations +EXTRA_FLAGS += -Wdeclaration-after-statement +EXTRA_FLAGS += -Wshadow +EXTRA_FLAGS += -Wformat-security -Wformat-nonliteral +# EXTRA_FLAGS += -Wvla + +# SSE4.1-specific flags: +ifeq ($(HAVE_SSE41), 1) +EXTRA_FLAGS += -DWEBP_HAVE_SSE41 +src/dsp/%_sse41.o: EXTRA_FLAGS += -msse4.1 +endif + +# NEON-specific flags: +# EXTRA_FLAGS += -march=armv7-a -mfloat-abi=hard -mfpu=neon -mtune=cortex-a8 +# -> seems to make the overall lib slower: -fno-split-wide-types + +# MIPS (MSA) 32-bit build specific flags for mips32r5 (p5600): +# EXTRA_FLAGS += -mips32r5 -mabi=32 -mtune=p5600 -mmsa -mfp64 +# EXTRA_FLAGS += -msched-weight -mload-store-pairs + +# MIPS (MSA) 64-bit build specific flags for mips64r6 (i6400): +# EXTRA_FLAGS += -mips64r6 -mabi=64 -mtune=i6400 -mmsa -mfp64 +# EXTRA_FLAGS += -msched-weight -mload-store-pairs + +#### Nothing should normally be changed below this line #### + +AR = ar +ARFLAGS = r +CPPFLAGS = -I. -Isrc/ -Wall +ifeq ($(DEBUG), 1) + CFLAGS = -g +else + CFLAGS = -O3 -DNDEBUG +endif +CFLAGS += $(EXTRA_FLAGS) +CC = gcc +INSTALL = install +GROFF = /usr/bin/groff +COL = /usr/bin/col +LDFLAGS = $(EXTRA_LIBS) $(EXTRA_FLAGS) -lm + +ifdef BITTRACE +CFLAGS += -DBITTRACE=$(BITTRACE) +endif + +ANIM_UTIL_OBJS = \ + examples/anim_util.o \ + +SHARPYUV_OBJS = \ + sharpyuv/sharpyuv.o \ + sharpyuv/sharpyuv_cpu.o \ + sharpyuv/sharpyuv_csp.o \ + sharpyuv/sharpyuv_dsp.o \ + sharpyuv/sharpyuv_gamma.o \ + sharpyuv/sharpyuv_neon.o \ + sharpyuv/sharpyuv_sse2.o \ + +DEC_OBJS = \ + src/dec/alpha_dec.o \ + src/dec/buffer_dec.o \ + src/dec/frame_dec.o \ + src/dec/idec_dec.o \ + src/dec/io_dec.o \ + src/dec/quant_dec.o \ + src/dec/tree_dec.o \ + src/dec/vp8_dec.o \ + src/dec/vp8l_dec.o \ + src/dec/webp_dec.o \ + +DEMUX_OBJS = \ + src/demux/anim_decode.o \ + src/demux/demux.o \ + +DSP_DEC_OBJS = \ + src/dsp/alpha_processing.o \ + src/dsp/alpha_processing_mips_dsp_r2.o \ + src/dsp/alpha_processing_neon.o \ + src/dsp/alpha_processing_sse2.o \ + src/dsp/alpha_processing_sse41.o \ + src/dsp/cpu.o \ + src/dsp/dec.o \ + src/dsp/dec_clip_tables.o \ + src/dsp/dec_mips32.o \ + src/dsp/dec_mips_dsp_r2.o \ + src/dsp/dec_msa.o \ + src/dsp/dec_neon.o \ + src/dsp/dec_sse2.o \ + src/dsp/dec_sse41.o \ + src/dsp/filters.o \ + src/dsp/filters_mips_dsp_r2.o \ + src/dsp/filters_msa.o \ + src/dsp/filters_neon.o \ + src/dsp/filters_sse2.o \ + src/dsp/lossless.o \ + src/dsp/lossless_mips_dsp_r2.o \ + src/dsp/lossless_msa.o \ + src/dsp/lossless_neon.o \ + src/dsp/lossless_sse2.o \ + src/dsp/lossless_sse41.o \ + src/dsp/rescaler.o \ + src/dsp/rescaler_mips32.o \ + src/dsp/rescaler_mips_dsp_r2.o \ + src/dsp/rescaler_msa.o \ + src/dsp/rescaler_neon.o \ + src/dsp/rescaler_sse2.o \ + src/dsp/upsampling.o \ + src/dsp/upsampling_mips_dsp_r2.o \ + src/dsp/upsampling_msa.o \ + src/dsp/upsampling_neon.o \ + src/dsp/upsampling_sse2.o \ + src/dsp/upsampling_sse41.o \ + src/dsp/yuv.o \ + src/dsp/yuv_mips32.o \ + src/dsp/yuv_mips_dsp_r2.o \ + src/dsp/yuv_neon.o \ + src/dsp/yuv_sse2.o \ + src/dsp/yuv_sse41.o \ + +DSP_ENC_OBJS = \ + src/dsp/cost.o \ + src/dsp/cost_mips32.o \ + src/dsp/cost_mips_dsp_r2.o \ + src/dsp/cost_neon.o \ + src/dsp/cost_sse2.o \ + src/dsp/enc.o \ + src/dsp/enc_mips32.o \ + src/dsp/enc_mips_dsp_r2.o \ + src/dsp/enc_msa.o \ + src/dsp/enc_neon.o \ + src/dsp/enc_sse2.o \ + src/dsp/enc_sse41.o \ + src/dsp/lossless_enc.o \ + src/dsp/lossless_enc_mips32.o \ + src/dsp/lossless_enc_mips_dsp_r2.o \ + src/dsp/lossless_enc_msa.o \ + src/dsp/lossless_enc_neon.o \ + src/dsp/lossless_enc_sse2.o \ + src/dsp/lossless_enc_sse41.o \ + src/dsp/ssim.o \ + src/dsp/ssim_sse2.o \ + +ENC_OBJS = \ + src/enc/alpha_enc.o \ + src/enc/analysis_enc.o \ + src/enc/backward_references_cost_enc.o \ + src/enc/backward_references_enc.o \ + src/enc/config_enc.o \ + src/enc/cost_enc.o \ + src/enc/filter_enc.o \ + src/enc/frame_enc.o \ + src/enc/histogram_enc.o \ + src/enc/iterator_enc.o \ + src/enc/near_lossless_enc.o \ + src/enc/picture_enc.o \ + src/enc/picture_csp_enc.o \ + src/enc/picture_psnr_enc.o \ + src/enc/picture_rescale_enc.o \ + src/enc/picture_tools_enc.o \ + src/enc/predictor_enc.o \ + src/enc/quant_enc.o \ + src/enc/syntax_enc.o \ + src/enc/token_enc.o \ + src/enc/tree_enc.o \ + src/enc/vp8l_enc.o \ + src/enc/webp_enc.o \ + +EX_FORMAT_DEC_OBJS = \ + imageio/image_dec.o \ + imageio/jpegdec.o \ + imageio/metadata.o \ + imageio/pngdec.o \ + imageio/pnmdec.o \ + imageio/tiffdec.o \ + imageio/webpdec.o \ + +EX_FORMAT_ENC_OBJS = \ + imageio/image_enc.o \ + +EX_UTIL_OBJS = \ + examples/example_util.o \ + +GIFDEC_OBJS = \ + examples/gifdec.o \ + +IMAGE_UTIL_OBJS = \ + imageio/imageio_util.o \ + +MUX_OBJS = \ + src/mux/anim_encode.o \ + src/mux/muxedit.o \ + src/mux/muxinternal.o \ + src/mux/muxread.o \ + +UTILS_DEC_OBJS = \ + src/utils/bit_reader_utils.o \ + src/utils/color_cache_utils.o \ + src/utils/filters_utils.o \ + src/utils/huffman_utils.o \ + src/utils/palette.o \ + src/utils/quant_levels_dec_utils.o \ + src/utils/random_utils.o \ + src/utils/rescaler_utils.o \ + src/utils/thread_utils.o \ + src/utils/utils.o \ + +UTILS_ENC_OBJS = \ + src/utils/bit_writer_utils.o \ + src/utils/huffman_encode_utils.o \ + src/utils/quant_levels_utils.o \ + +EXTRA_OBJS = \ + extras/extras.o \ + extras/quality_estimate.o \ + +LIBWEBPDECODER_OBJS = $(DEC_OBJS) $(DSP_DEC_OBJS) $(UTILS_DEC_OBJS) +LIBWEBP_OBJS = $(LIBWEBPDECODER_OBJS) $(ENC_OBJS) \ + $(DSP_ENC_OBJS) $(UTILS_ENC_OBJS) +LIBWEBPMUX_OBJS = $(MUX_OBJS) +LIBWEBPDEMUX_OBJS = $(DEMUX_OBJS) +LIBWEBPEXTRA_OBJS = $(EXTRA_OBJS) +LIBSHARPYUV_OBJS = $(SHARPYUV_OBJS) + +HDRS_INSTALLED = \ + src/webp/decode.h \ + src/webp/demux.h \ + src/webp/encode.h \ + src/webp/mux.h \ + src/webp/mux_types.h \ + src/webp/types.h \ + +SHARPYUV_HDRS_INSTALLED = \ + sharpyuv/sharpyuv.h \ + sharpyuv/sharpyuv_cpu.h \ + sharpyuv/sharpyuv_csp.h \ + +HDRS = \ + src/dec/alphai_dec.h \ + src/dec/common_dec.h \ + src/dec/vp8_dec.h \ + src/dec/vp8i_dec.h \ + src/dec/vp8li_dec.h \ + src/dec/webpi_dec.h \ + src/dsp/common_sse2.h \ + src/dsp/cpu.h \ + src/dsp/dsp.h \ + src/dsp/lossless.h \ + src/dsp/lossless_common.h \ + src/dsp/mips_macro.h \ + src/dsp/msa_macro.h \ + src/dsp/neon.h \ + src/dsp/yuv.h \ + src/enc/backward_references_enc.h \ + src/enc/cost_enc.h \ + src/enc/histogram_enc.h \ + src/enc/vp8i_enc.h \ + src/enc/vp8li_enc.h \ + src/mux/animi.h \ + src/mux/muxi.h \ + src/utils/bit_reader_utils.h \ + src/utils/bit_reader_inl_utils.h \ + src/utils/bit_writer_utils.h \ + src/utils/color_cache_utils.h \ + src/utils/endian_inl_utils.h \ + src/utils/filters_utils.h \ + src/utils/huffman_utils.h \ + src/utils/huffman_encode_utils.h \ + src/utils/palette.h \ + src/utils/quant_levels_utils.h \ + src/utils/quant_levels_dec_utils.h \ + src/utils/random_utils.h \ + src/utils/rescaler_utils.h \ + src/utils/thread_utils.h \ + src/utils/utils.h \ + src/webp/format_constants.h \ + $(HDRS_INSTALLED) \ + $(SHARPYUV_HDRS_INSTALLED) \ + +OUT_LIBS = examples/libexample_util.a +OUT_LIBS += imageio/libimageio_util.a +OUT_LIBS += imageio/libimagedec.a +OUT_LIBS += imageio/libimageenc.a +OUT_LIBS += src/libwebpdecoder.a +OUT_LIBS += src/libwebp.a +OUT_LIBS += sharpyuv/libsharpyuv.a +EXTRA_LIB = extras/libwebpextras.a +OUT_EXAMPLES = examples/cwebp examples/dwebp +EXTRA_EXAMPLES = examples/gif2webp examples/vwebp examples/webpmux \ + examples/anim_diff examples/anim_dump \ + examples/img2webp examples/webpinfo +OTHER_EXAMPLES = extras/get_disto extras/webp_quality extras/vwebp_sdl + +OUTPUT = $(OUT_LIBS) $(OUT_EXAMPLES) +ifeq ($(MAKECMDGOALS),clean) + OUTPUT += $(EXTRA_EXAMPLES) $(OTHER_EXAMPLES) + OUTPUT += src/demux/libwebpdemux.a src/mux/libwebpmux.a $(EXTRA_LIB) + OUTPUT += examples/libgifdec.a examples/libanim_util.a +endif + +ex: $(OUT_EXAMPLES) +all: ex $(EXTRA_EXAMPLES) $(OTHER_EXAMPLES) +extras: $(EXTRA_LIB) + +$(EX_FORMAT_DEC_OBJS): %.o: %.h + +# special dependencies: +# tree_dec.c/vp8_dec.c/bit_reader_utils.c <-> +# bit_reader_inl_utils.h, endian_inl_utils.h +# bit_writer_utils.c <-> endian_inl_utils.h +src/dec/tree_dec.o: src/utils/bit_reader_inl_utils.h +src/dec/tree_dec.o: src/utils/endian_inl_utils.h +src/dec/vp8_dec.o: src/utils/bit_reader_inl_utils.h src/utils/endian_inl_utils.h +src/utils/bit_reader_utils.o: src/utils/bit_reader_inl_utils.h +src/utils/bit_reader_utils.o: src/utils/endian_inl_utils.h +src/utils/bit_writer_utils.o: src/utils/endian_inl_utils.h + +%.o: %.c $(HDRS) + $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ + +examples/libanim_util.a: $(ANIM_UTIL_OBJS) +examples/libexample_util.a: $(EX_UTIL_OBJS) +examples/libgifdec.a: $(GIFDEC_OBJS) +extras/libwebpextras.a: $(LIBWEBPEXTRA_OBJS) +imageio/libimagedec.a: $(EX_FORMAT_DEC_OBJS) +imageio/libimageenc.a: $(EX_FORMAT_ENC_OBJS) +imageio/libimageio_util.a: $(IMAGE_UTIL_OBJS) +src/libwebpdecoder.a: $(LIBWEBPDECODER_OBJS) +src/libwebp.a: $(LIBWEBP_OBJS) +src/mux/libwebpmux.a: $(LIBWEBPMUX_OBJS) +src/demux/libwebpdemux.a: $(LIBWEBPDEMUX_OBJS) +sharpyuv/libsharpyuv.a: $(LIBSHARPYUV_OBJS) + +%.a: + $(AR) $(ARFLAGS) $@ $^ + +examples/anim_diff: examples/anim_diff.o $(ANIM_UTIL_OBJS) $(GIFDEC_OBJS) +examples/anim_dump: examples/anim_dump.o $(ANIM_UTIL_OBJS) $(GIFDEC_OBJS) +examples/cwebp: examples/cwebp.o +examples/dwebp: examples/dwebp.o +examples/gif2webp: examples/gif2webp.o $(GIFDEC_OBJS) +examples/vwebp: examples/vwebp.o +examples/webpmux: examples/webpmux.o +examples/img2webp: examples/img2webp.o +examples/webpinfo: examples/webpinfo.o + +examples/anim_diff: examples/libanim_util.a examples/libgifdec.a +examples/anim_diff: src/demux/libwebpdemux.a examples/libexample_util.a +examples/anim_diff: imageio/libimageio_util.a src/libwebp.a +examples/anim_diff: sharpyuv/libsharpyuv.a +examples/anim_diff: override EXTRA_LIBS += $(GIF_LIBS) +examples/anim_diff: EXTRA_FLAGS += -DWEBP_HAVE_GIF +examples/anim_dump: examples/libanim_util.a examples/libgifdec.a +examples/anim_dump: src/demux/libwebpdemux.a +examples/anim_dump: examples/libexample_util.a +examples/anim_dump: imageio/libimageio_util.a +examples/anim_dump: imageio/libimageenc.a +examples/anim_dump: src/libwebp.a +examples/anim_dump: sharpyuv/libsharpyuv.a +examples/anim_dump: override EXTRA_LIBS += $(GIF_LIBS) $(DWEBP_LIBS) +examples/cwebp: examples/libexample_util.a +examples/cwebp: imageio/libimagedec.a +examples/cwebp: src/demux/libwebpdemux.a +examples/cwebp: imageio/libimageio_util.a +examples/cwebp: src/libwebp.a +examples/cwebp: sharpyuv/libsharpyuv.a +examples/cwebp: override EXTRA_LIBS += $(CWEBP_LIBS) +examples/dwebp: examples/libexample_util.a +examples/dwebp: imageio/libimagedec.a +examples/dwebp: src/demux/libwebpdemux.a +examples/dwebp: imageio/libimageenc.a +examples/dwebp: imageio/libimageio_util.a +examples/dwebp: src/libwebp.a +examples/dwebp: sharpyuv/libsharpyuv.a +examples/dwebp: override EXTRA_LIBS += $(DWEBP_LIBS) +examples/gif2webp: examples/libexample_util.a imageio/libimageio_util.a +examples/gif2webp: examples/libgifdec.a src/mux/libwebpmux.a src/libwebp.a +examples/gif2webp: sharpyuv/libsharpyuv.a +examples/gif2webp: override EXTRA_LIBS += $(GIF_LIBS) +examples/gif2webp: EXTRA_FLAGS += -DWEBP_HAVE_GIF +examples/vwebp: examples/libexample_util.a src/demux/libwebpdemux.a +examples/vwebp: imageio/libimageio_util.a src/libwebp.a +examples/vwebp: sharpyuv/libsharpyuv.a +examples/vwebp: override EXTRA_LIBS += $(GL_LIBS) +examples/vwebp: EXTRA_FLAGS += -DWEBP_HAVE_GL +examples/webpmux: examples/libexample_util.a imageio/libimageio_util.a +examples/webpmux: src/mux/libwebpmux.a src/libwebpdecoder.a +examples/img2webp: examples/libexample_util.a imageio/libimageio_util.a +examples/img2webp: imageio/libimagedec.a +examples/img2webp: src/demux/libwebpdemux.a +examples/img2webp: src/mux/libwebpmux.a +examples/img2webp: src/libwebp.a +examples/img2webp: sharpyuv/libsharpyuv.a +examples/img2webp: override EXTRA_LIBS += $(CWEBP_LIBS) +examples/webpinfo: examples/libexample_util.a imageio/libimageio_util.a +examples/webpinfo: src/libwebpdecoder.a + +extras/get_disto: extras/get_disto.o +extras/get_disto: imageio/libimagedec.a +extras/get_disto: src/demux/libwebpdemux.a +extras/get_disto: imageio/libimageio_util.a +extras/get_disto: src/libwebp.a +extras/get_disto: sharpyuv/libsharpyuv.a +extras/get_disto: override EXTRA_LIBS += $(CWEBP_LIBS) + +extras/webp_quality: extras/webp_quality.o +extras/webp_quality: imageio/libimageio_util.a +extras/webp_quality: $(EXTRA_LIB) src/libwebp.a +extras/webp_quality: sharpyuv/libsharpyuv.a + +extras/vwebp_sdl: extras/vwebp_sdl.o +extras/vwebp_sdl: extras/webp_to_sdl.o +extras/vwebp_sdl: imageio/libimageio_util.a +extras/vwebp_sdl: src/libwebp.a +extras/vwebp_sdl: sharpyuv/libsharpyuv.a +extras/vwebp_sdl: EXTRA_FLAGS += -DWEBP_HAVE_SDL $(SDL_FLAGS) +extras/vwebp_sdl: override EXTRA_LIBS += $(SDL_LIBS) + +$(OUT_EXAMPLES) $(EXTRA_EXAMPLES) $(OTHER_EXAMPLES): + $(CC) -o $@ $^ $(LDFLAGS) + +dist: DESTDIR := dist +dist: OUT_EXAMPLES += $(EXTRA_EXAMPLES) +dist: all + $(INSTALL) -m755 -d $(DESTDIR)/include/webp \ + $(DESTDIR)/include/webp/sharpyuv \ + $(DESTDIR)/bin $(DESTDIR)/doc $(DESTDIR)/lib + $(INSTALL) -m755 -s $(OUT_EXAMPLES) $(DESTDIR)/bin + $(INSTALL) -m644 $(HDRS_INSTALLED) $(DESTDIR)/include/webp + $(INSTALL) -m644 $(SHARPYUV_HDRS_INSTALLED) $(DESTDIR)/include/webp/sharpyuv + $(INSTALL) -m644 src/libwebp.a $(DESTDIR)/lib + $(INSTALL) -m644 src/demux/libwebpdemux.a $(DESTDIR)/lib + $(INSTALL) -m644 src/mux/libwebpmux.a $(DESTDIR)/lib + $(INSTALL) -m644 sharpyuv/libsharpyuv.a $(DESTDIR)/lib + umask 022; \ + for m in man/[cdv]webp.1 man/gif2webp.1 man/webpmux.1 \ + man/img2webp.1 man/webpinfo.1; do \ + basenam=$$(basename $$m .1); \ + $(GROFF) -t -e -man -T ascii $$m \ + | $(COL) -bx >$(DESTDIR)/doc/$${basenam}.txt; \ + $(GROFF) -t -e -man -T html $$m \ + | $(COL) -bx >$(DESTDIR)/doc/$${basenam}.html; \ + done + +clean: + $(RM) $(OUTPUT) *~ \ + examples/*.o examples/*~ \ + extras/*.o extras/*~ \ + imageio/*.o imageio/*~ \ + sharpyuv/*.o sharpyuv/*~ \ + src/dec/*.o src/dec/*~ \ + src/demux/*.o src/demux/*~ \ + src/dsp/*.o src/dsp/*~ \ + src/enc/*.o src/enc/*~ \ + src/mux/*.o src/mux/*~ \ + src/utils/*.o src/utils/*~ \ + src/webp/*~ man/*~ doc/*~ swig/*~ \ + +.PHONY: all clean dist ex +.SUFFIXES: diff --git a/third-party/webp/libwebp/man/Makefile.am b/third-party/webp/libwebp/man/Makefile.am new file mode 100644 index 0000000000..57e2483f51 --- /dev/null +++ b/third-party/webp/libwebp/man/Makefile.am @@ -0,0 +1,17 @@ +man_MANS = cwebp.1 dwebp.1 +if BUILD_MUX + man_MANS += webpmux.1 +endif +if BUILD_GIF2WEBP + man_MANS += gif2webp.1 +endif +if BUILD_IMG2WEBP + man_MANS += img2webp.1 +endif +if BUILD_VWEBP + man_MANS += vwebp.1 +endif +if BUILD_WEBPINFO + man_MANS += webpinfo.1 +endif +EXTRA_DIST = $(man_MANS) diff --git a/third-party/webp/libwebp/man/cwebp.1 b/third-party/webp/libwebp/man/cwebp.1 new file mode 100644 index 0000000000..28de4c9463 --- /dev/null +++ b/third-party/webp/libwebp/man/cwebp.1 @@ -0,0 +1,328 @@ +.\" Hey, EMACS: -*- nroff -*- +.TH CWEBP 1 "March 17, 2022" +.SH NAME +cwebp \- compress an image file to a WebP file +.SH SYNOPSIS +.B cwebp +.RI [ options ] " input_file \-o output_file.webp +.br +.SH DESCRIPTION +This manual page documents the +.B cwebp +command. +.PP +\fBcwebp\fP compresses an image using the WebP format. +Input format can be either PNG, JPEG, TIFF, WebP or raw Y'CbCr samples. +Note: Animated PNG and WebP files are not supported. +.SH OPTIONS +The basic options are: +.TP +.BI \-o " string +Specify the name of the output WebP file. If omitted, \fBcwebp\fP will +perform compression but only report statistics. +Using "\-" as output name will direct output to 'stdout'. +.TP +.BI \-\- " string +Explicitly specify the input file. This option is useful if the input +file starts with a '\-' for instance. This option must appear \fBlast\fP. +Any other options afterward will be ignored. +.TP +.B \-h, \-help +A short usage summary. +.TP +.B \-H, \-longhelp +A summary of all the possible options. +.TP +.B \-version +Print the version number (as major.minor.revision) and exit. +.TP +.B \-lossless +Encode the image without any loss. For images with fully transparent area, +the invisible pixel values (R/G/B or Y/U/V) will be preserved only if the +\-exact option is used. +.TP +.BI \-near_lossless " int +Specify the level of near\-lossless image preprocessing. This option adjusts +pixel values to help compressibility, but has minimal impact on the visual +quality. It triggers lossless compression mode automatically. The range is 0 +(maximum preprocessing) to 100 (no preprocessing, the default). The typical +value is around 60. Note that lossy with \fB\-q 100\fP can at times yield +better results. +.TP +.BI \-q " float +Specify the compression factor for RGB channels between 0 and 100. The default +is 75. +.br +In case of lossy compression (default), a small factor produces a smaller file +with lower quality. Best quality is achieved by using a value of 100. +.br +In case of lossless compression (specified by the \fB\-lossless\fP option), a +small factor enables faster compression speed, but produces a larger file. +Maximum compression is achieved by using a value of 100. +.TP +.BI \-z " int +Switch on \fBlossless\fP compression mode with the specified level between 0 +and 9, with level 0 being the fastest, 9 being the slowest. Fast mode +produces larger file size than slower ones. A good default is \fB\-z 6\fP. +This option is actually a shortcut for some predefined settings for quality +and method. If options \fB\-q\fP or \fB\-m\fP are subsequently used, they will +invalidate the effect of this option. +.TP +.BI \-alpha_q " int +Specify the compression factor for alpha compression between 0 and 100. +Lossless compression of alpha is achieved using a value of 100, while the lower +values result in a lossy compression. The default is 100. +.TP +.BI \-preset " string +Specify a set of pre\-defined parameters to suit a particular type of +source material. Possible values are: \fBdefault\fP, \fBphoto\fP, +\fBpicture\fP, \fBdrawing\fP, \fBicon\fP, \fBtext\fP. Since +\fB\-preset\fP overwrites the other parameters' values (except the +\fB\-q\fP one), this option should preferably appear first in the +order of the arguments. +.TP +.BI \-m " int +Specify the compression method to use. This parameter controls the +trade off between encoding speed and the compressed file size and quality. +Possible values range from 0 to 6. Default value is 4. +When higher values are used, the encoder will spend more time inspecting +additional encoding possibilities and decide on the quality gain. +Lower value can result in faster processing time at the expense of +larger file size and lower compression quality. +.TP +.BI \-crop " x_position y_position width height +Crop the source to a rectangle with top\-left corner at coordinates +(\fBx_position\fP, \fBy_position\fP) and size \fBwidth\fP x \fBheight\fP. +This cropping area must be fully contained within the source rectangle. +Note: the cropping is applied \fIbefore\fP any scaling. +.TP +.BI \-resize " width height +Resize the source to a rectangle with size \fBwidth\fP x \fBheight\fP. +If either (but not both) of the \fBwidth\fP or \fBheight\fP parameters is 0, +the value will be calculated preserving the aspect\-ratio. Note: scaling +is applied \fIafter\fP cropping. +.TP +.B \-mt +Use multi\-threading for encoding, if possible. +.TP +.B \-low_memory +Reduce memory usage of lossy encoding by saving four times the compressed +size (typically). This will make the encoding slower and the output slightly +different in size and distortion. This flag is only effective for methods +3 and up, and is off by default. Note that leaving this flag off will have +some side effects on the bitstream: it forces certain bitstream features +like number of partitions (forced to 1). Note that a more detailed report +of bitstream size is printed by \fBcwebp\fP when using this option. + +.SS LOSSY OPTIONS +These options are only effective when doing lossy encoding (the default, with +or without alpha). + +.TP +.BI \-size " int +Specify a target size (in bytes) to try and reach for the compressed output. +The compressor will make several passes of partial encoding in order to get as +close as possible to this target. If both \fB\-size\fP and \fB\-psnr\fP +are used, \fB\-size\fP value will prevail. +.TP +.BI \-psnr " float +Specify a target PSNR (in dB) to try and reach for the compressed output. +The compressor will make several passes of partial encoding in order to get as +close as possible to this target. If both \fB\-size\fP and \fB\-psnr\fP +are used, \fB\-size\fP value will prevail. +.TP +.BI \-pass " int +Set a maximum number of passes to use during the dichotomy used by +options \fB\-size\fP or \fB\-psnr\fP. Maximum value is 10, default is 1. +If options \fB\-size\fP or \fB\-psnr\fP were used, but \fB\-pass\fP wasn't +specified, a default value of '6' passes will be used. +.TP +.BI \-qrange " int int +Specifies the permissible interval for the quality factor. This is particularly +useful when using multi-pass (\fB\-size\fP or \fB\-psnr\fP options). +Default is 0 100. +If the quality factor is outside this range, it will be clamped. +If the minimum value must be less or equal to the maximum one. +.TP +.B \-af +Turns auto\-filter on. This algorithm will spend additional time optimizing +the filtering strength to reach a well\-balanced quality. +.TP +.B \-jpeg_like +Change the internal parameter mapping to better match the expected size +of JPEG compression. This flag will generally produce an output file of +similar size to its JPEG equivalent (for the same \fB\-q\fP setting), but +with less visual distortion. + +.TP +Advanced options: + +.TP +.BI \-f " int +Specify the strength of the deblocking filter, between 0 (no filtering) +and 100 (maximum filtering). A value of 0 will turn off any filtering. +Higher value will increase the strength of the filtering process applied +after decoding the picture. The higher the value the smoother the picture will +appear. Typical values are usually in the range of 20 to 50. +.TP +.BI \-sharpness " int +Specify the sharpness of the filtering (if used). +Range is 0 (sharpest) to 7 (least sharp). Default is 0. +.TP +.B \-strong +Use strong filtering (if filtering is being used thanks to the +\fB\-f\fP option). Strong filtering is on by default. +.TP +.B \-nostrong +Disable strong filtering (if filtering is being used thanks to the +\fB\-f\fP option) and use simple filtering instead. +.TP +.B \-sharp_yuv +Use more accurate and sharper RGB->YUV conversion if needed. Note that this +process is slower than the default 'fast' RGB->YUV conversion. +.TP +.BI \-sns " int +Specify the amplitude of the spatial noise shaping. Spatial noise shaping +(or \fBsns\fP for short) refers to a general collection of built\-in algorithms +used to decide which area of the picture should use relatively less bits, +and where else to better transfer these bits. The possible range goes from +0 (algorithm is off) to 100 (the maximal effect). The default value is 50. +.TP +.BI \-segments " int +Change the number of partitions to use during the segmentation of the +sns algorithm. Segments should be in range 1 to 4. Default value is 4. +This option has no effect for methods 3 and up, unless \fB\-low_memory\fP +is used. +.TP +.BI \-partition_limit " int +Degrade quality by limiting the number of bits used by some macroblocks. +Range is 0 (no degradation, the default) to 100 (full degradation). +Useful values are usually around 30\-70 for moderately large images. +In the VP8 format, the so\-called control partition has a limit of 512k and +is used to store the following information: whether the macroblock is skipped, +which segment it belongs to, whether it is coded as intra 4x4 or intra 16x16 +mode, and finally the prediction modes to use for each of the sub\-blocks. +For a very large image, 512k only leaves room to few bits per 16x16 macroblock. +The absolute minimum is 4 bits per macroblock. Skip, segment, and mode +information can use up almost all these 4 bits (although the case is unlikely), +which is problematic for very large images. The partition_limit factor controls +how frequently the most bit\-costly mode (intra 4x4) will be used. This is +useful in case the 512k limit is reached and the following message is displayed: +\fIError code: 6 (PARTITION0_OVERFLOW: Partition #0 is too big to fit 512k)\fP. +If using \fB\-partition_limit\fP is not enough to meet the 512k constraint, one +should use less segments in order to save more header bits per macroblock. +See the \fB\-segments\fP option. + +.SS LOGGING OPTIONS +These options control the level of output: +.TP +.B \-v +Print extra information (encoding time in particular). +.TP +.B \-print_psnr +Compute and report average PSNR (Peak\-Signal\-To\-Noise ratio). +.TP +.B \-print_ssim +Compute and report average SSIM (structural similarity +metric, see https://en.wikipedia.org/wiki/SSIM for additional details). +.TP +.B \-print_lsim +Compute and report local similarity metric (sum of lowest error amongst the +collocated pixel neighbors). +.TP +.B \-progress +Report encoding progress in percent. +.TP +.B \-quiet +Do not print anything. +.TP +.B \-short +Only print brief information (output file size and PSNR) for testing purposes. +.TP +.BI \-map " int +Output additional ASCII\-map of encoding information. Possible map values +range from 1 to 6. This is only meant to help debugging. + +.SS ADDITIONAL OPTIONS +More advanced options are: +.TP +.BI \-s " width height +Specify that the input file actually consists of raw Y'CbCr samples following +the ITU\-R BT.601 recommendation, in 4:2:0 linear format. +The luma plane has size \fBwidth\fP x \fBheight\fP. +.TP +.BI \-pre " int +Specify some preprocessing steps. Using a value of '2' will trigger +quality\-dependent pseudo\-random dithering during RGBA\->YUVA conversion +(lossy compression only). +.TP +.BI \-alpha_filter " string +Specify the predictive filtering method for the alpha plane. One of 'none', +\&'fast' or 'best', in increasing complexity and slowness order. Default is +\&'fast'. Internally, alpha filtering is performed using four possible +predictions (none, horizontal, vertical, gradient). The 'best' mode will try +each mode in turn and pick the one which gives the smaller size. The 'fast' +mode will just try to form an a priori guess without testing all modes. +.TP +.BI \-alpha_method " int +Specify the algorithm used for alpha compression: 0 or 1. Algorithm 0 denotes +no compression, 1 uses WebP lossless format for compression. The default is 1. +.TP +.B \-exact +Preserve RGB values in transparent area. The default is off, to help +compressibility. +.TP +.BI \-blend_alpha " int +This option blends the alpha channel (if present) with the source using the +background color specified in hexadecimal as 0xrrggbb. The alpha channel is +afterward reset to the opaque value 255. +.TP +.B \-noalpha +Using this option will discard the alpha channel. +.TP +.BI \-hint " string +Specify the hint about input image type. Possible values are: +\fBphoto\fP, \fBpicture\fP or \fBgraph\fP. +.TP +.BI \-metadata " string +A comma separated list of metadata to copy from the input to the output if +present. +Valid values: \fBall\fP, \fBnone\fP, \fBexif\fP, \fBicc\fP, \fBxmp\fP. +The default is \fBnone\fP. + +Note: each input format may not support all combinations. +.TP +.B \-noasm +Disable all assembly optimizations. + +.SH BUGS +Please report all bugs to the issue tracker: +https://bugs.chromium.org/p/webp +.br +Patches welcome! See this page to get started: +https://www.webmproject.org/code/contribute/submitting\-patches/ + +.SH EXAMPLES +cwebp \-q 50 -lossless picture.png \-o picture_lossless.webp +.br +cwebp \-q 70 picture_with_alpha.png \-o picture_with_alpha.webp +.br +cwebp \-sns 70 \-f 50 \-size 60000 picture.png \-o picture.webp +.br +cwebp \-o picture.webp \-\- \-\-\-picture.png + +.SH AUTHORS +\fBcwebp\fP is a part of libwebp and was written by the WebP team. +.br +The latest source tree is available at +https://chromium.googlesource.com/webm/libwebp +.PP +This manual page was written by Pascal Massimino , +for the Debian project (and may be used by others). + +.SH SEE ALSO +.BR dwebp (1), +.BR gif2webp (1) +.br +Please refer to https://developers.google.com/speed/webp/ for additional +information. diff --git a/third-party/webp/libwebp/man/dwebp.1 b/third-party/webp/libwebp/man/dwebp.1 new file mode 100644 index 0000000000..e718aba720 --- /dev/null +++ b/third-party/webp/libwebp/man/dwebp.1 @@ -0,0 +1,150 @@ +.\" Hey, EMACS: -*- nroff -*- +.TH DWEBP 1 "November 17, 2021" +.SH NAME +dwebp \- decompress a WebP file to an image file +.SH SYNOPSIS +.B dwebp +.RI [ options ] " input_file.webp +.br +.SH DESCRIPTION +This manual page documents the +.B dwebp +command. +.PP +\fBdwebp\fP decompresses WebP files into PNG, PAM, PPM or PGM images. +Note: Animated WebP files are not supported. +.SH OPTIONS +The basic options are: +.TP +.B \-h +Print usage summary. +.TP +.B \-version +Print the version number (as major.minor.revision) and exit. +.TP +.BI \-o " string +Specify the name of the output file (as PNG format by default). +Using "-" as output name will direct output to 'stdout'. +.TP +.BI \-\- " string +Explicitly specify the input file. This option is useful if the input +file starts with an '\-' for instance. This option must appear \fBlast\fP. +Any other options afterward will be ignored. If the input file is "\-", +the data will be read from \fIstdin\fP instead of a file. +.TP +.B \-bmp +Change the output format to uncompressed BMP. +.TP +.B \-tiff +Change the output format to uncompressed TIFF. +.TP +.B \-pam +Change the output format to PAM (retains alpha). +.TP +.B \-ppm +Change the output format to PPM (discards alpha). +.TP +.B \-pgm +Change the output format to PGM. The output consists of luma/chroma +samples instead of RGB, using the IMC4 layout. This option is mainly +for verification and debugging purposes. +.TP +.B \-yuv +Change the output format to raw YUV. The output consists of +luma/chroma-U/chroma-V samples instead of RGB, saved sequentially as +individual planes. This option is mainly for verification and debugging +purposes. +.TP +.B \-nofancy +Don't use the fancy upscaler for YUV420. This may lead to jaggy +edges (especially the red ones), but should be faster. +.TP +.B \-nofilter +Don't use the in-loop filtering process even if it is required by +the bitstream. This may produce visible blocks on the non-compliant output, +but it will make the decoding faster. +.TP +.BI \-dither " strength +Specify a dithering \fBstrength\fP between 0 and 100. Dithering is a +post-processing effect applied to chroma components in lossy compression. +It helps by smoothing gradients and avoiding banding artifacts. +.TP +.BI \-alpha_dither +If the compressed file contains a transparency plane that was quantized +during compression, this flag will allow dithering the reconstructed plane +in order to generate smoother transparency gradients. +.TP +.B \-nodither +Disable all dithering (default). +.TP +.B \-mt +Use multi-threading for decoding, if possible. +.TP +.BI \-crop " x_position y_position width height +Crop the decoded picture to a rectangle with top-left corner at coordinates +(\fBx_position\fP, \fBy_position\fP) and size \fBwidth\fP x \fBheight\fP. +This cropping area must be fully contained within the source rectangle. +The top-left corner will be snapped to even coordinates if needed. +This option is meant to reduce the memory needed for cropping large images. +Note: the cropping is applied \fIbefore\fP any scaling. +.TP +.B \-flip +Flip decoded image vertically (can be useful for OpenGL textures for instance). +.TP +\fB\-resize\fR, \fB\-scale\fI width height\fR +Rescale the decoded picture to dimension \fBwidth\fP x \fBheight\fP. This +option is mostly intended to reducing the memory needed to decode large images, +when only a small version is needed (thumbnail, preview, etc.). Note: scaling +is applied \fIafter\fP cropping. +If either (but not both) of the \fBwidth\fP or \fBheight\fP parameters is 0, +the value will be calculated preserving the aspect-ratio. +.TP +.B \-quiet +Do not print anything. +.TP +.B \-v +Print extra information (decoding time in particular). +.TP +.B \-noasm +Disable all assembly optimizations. + +.SH BUGS +Please report all bugs to the issue tracker: +https://bugs.chromium.org/p/webp +.br +Patches welcome! See this page to get started: +https://www.webmproject.org/code/contribute/submitting\-patches/ + +.SH EXAMPLES +dwebp picture.webp \-o output.png +.br +dwebp picture.webp \-ppm \-o output.ppm +.br +dwebp \-o output.ppm \-\- \-\-\-picture.webp +.br +cat picture.webp | dwebp \-o \- \-\- \- > output.ppm + +.SH AUTHORS +\fBdwebp\fP is a part of libwebp and was written by the WebP team. +.br +The latest source tree is available at +https://chromium.googlesource.com/webm/libwebp +.PP +This manual page was written by Pascal Massimino , +for the Debian project (and may be used by others). + +.SH SEE ALSO +.BR cwebp (1), +.BR gif2webp (1), +.BR webpmux (1) +.br +Please refer to https://developers.google.com/speed/webp/ for additional +information. +.SS Output file format details +PAM: http://netpbm.sourceforge.net/doc/pam.html +.br +PGM: http://netpbm.sourceforge.net/doc/pgm.html +.br +PPM: http://netpbm.sourceforge.net/doc/ppm.html +.br +PNG: http://www.libpng.org/pub/png/png-sitemap.html#info diff --git a/third-party/webp/libwebp/man/gif2webp.1 b/third-party/webp/libwebp/man/gif2webp.1 new file mode 100644 index 0000000000..3bf43bcc50 --- /dev/null +++ b/third-party/webp/libwebp/man/gif2webp.1 @@ -0,0 +1,164 @@ +.\" Hey, EMACS: -*- nroff -*- +.TH GIF2WEBP 1 "November 17, 2021" +.SH NAME +gif2webp \- Convert a GIF image to WebP +.SH SYNOPSIS +.B gif2webp +.RI [ options ] " input_file.gif \-o output_file.webp +.br +.SH DESCRIPTION +This manual page documents the +.B gif2webp +command. +.PP +\fBgif2webp\fP converts a GIF image to a WebP image. +.SH OPTIONS +The basic options are: +.TP +.BI \-o " string +Specify the name of the output WebP file. If omitted, \fBgif2webp\fP will +perform conversion but only report statistics. +Using "\-" as output name will direct output to 'stdout'. +.TP +.BI \-\- " string +Explicitly specify the input file. This option is useful if the input +file starts with an '\-' for instance. This option must appear \fBlast\fP. +Any other options afterward will be ignored. If the input file is "\-", +the data will be read from \fIstdin\fP instead of a file. +.TP +.B \-h, \-help +Usage information. +.TP +.B \-version +Print the version number (as major.minor.revision) and exit. +.TP +.B \-lossy +Encode the image using lossy compression. +.TP +.B \-mixed +Mixed compression mode: optimize compression of the image by picking either +lossy or lossless compression for each frame heuristically. +.TP +.BI \-q " float +Specify the compression factor for RGB channels between 0 and 100. The default +is 75. +.br +In case of lossless compression (default), a small factor enables faster +compression speed, but produces a larger file. Maximum compression is achieved +by using a value of 100. +.br +In case of lossy compression (specified by the \-lossy option), a small factor +produces a smaller file with lower quality. Best quality is achieved by using a +value of 100. +.TP +.BI \-m " int +Specify the compression method to use. This parameter controls the +trade off between encoding speed and the compressed file size and quality. +Possible values range from 0 to 6. Default value is 4. +When higher values are used, the encoder will spend more time inspecting +additional encoding possibilities and decide on the quality gain. +Lower value can result is faster processing time at the expense of +larger file size and lower compression quality. +.TP +.BI \-min_size +Encode image to achieve smallest size. This disables key frame insertion and +picks the dispose method resulting in the smallest output for each frame. It +uses lossless compression by default, but can be combined with \-q, \-m, +\-lossy or \-mixed options. +.TP +.BI \-kmin " int +.TP +.BI \-kmax " int +Specify the minimum and maximum distance between consecutive key frames +(independently decodable frames) in the output animation. The tool will insert +some key frames into the output animation as needed so that this criteria is +satisfied. +.br +A 'kmax' value of 0 will turn off insertion of key frames. A 'kmax' value of 1 +will result in all frames being key frames. 'kmin' value is not taken into +account in both these special cases. +Typical values are in the range 3 to 30. Default values are kmin = 9, +kmax = 17 for lossless compression and kmin = 3, kmax = 5 for lossy compression. +.br +These two options are relevant only for animated images with large number of +frames (>50). +.br +When lower values are used, more frames will be converted to key frames. This +may lead to smaller number of frames required to decode a frame on average, +thereby improving the decoding performance. But this may lead to slightly bigger +file sizes. +Higher values may lead to worse decoding performance, but smaller file sizes. +.br +Some restrictions: +.br +(i) kmin < kmax, +.br +(ii) kmin >= kmax / 2 + 1 and +.br +(iii) kmax - kmin <= 30. +.br +If any of these restrictions are not met, they will be enforced automatically. +.TP +.BI \-metadata " string +A comma separated list of metadata to copy from the input to the output if +present. +Valid values: \fBall\fP, \fBnone\fP, \fBicc\fP, \fBxmp\fP. +The default is \fBxmp\fP. +.TP +.BI \-f " int +For lossy encoding only (specified by the \-lossy option). Specify the strength +of the deblocking filter, between 0 (no filtering) and 100 (maximum filtering). +A value of 0 will turn off any filtering. Higher value will increase the +strength of the filtering process applied after decoding the picture. The higher +the value the smoother the picture will appear. Typical values are usually in +the range of 20 to 50. +.TP +.B \-mt +Use multi-threading for encoding, if possible. +.TP +.B \-loop_compatibility +If enabled, handle the loop information in a compatible fashion for Chrome +version prior to M62 (inclusive) and Firefox. +.TP +.B \-v +Print extra information. +.TP +.B \-quiet +Do not print anything. + +.SH BUGS +Please report all bugs to the issue tracker: +https://bugs.chromium.org/p/webp +.br +Patches welcome! See this page to get started: +https://www.webmproject.org/code/contribute/submitting\-patches/ + +.SH EXAMPLES +gif2webp picture.gif \-o picture.webp +.br +gif2webp \-q 70 picture.gif \-o picture.webp +.br +gif2webp \-lossy \-m 3 picture.gif \-o picture_lossy.webp +.br +gif2webp \-lossy \-f 50 picture.gif \-o picture.webp +.br +gif2webp \-q 70 \-o picture.webp \-\- \-\-\-picture.gif +.br +cat picture.gif | gif2webp \-o \- \-\- \- > output.webp + +.SH AUTHORS +\fBgif2webp\fP is a part of libwebp and was written by the WebP team. +.br +The latest source tree is available at +https://chromium.googlesource.com/webm/libwebp +.PP +This manual page was written by Urvang Joshi , for the +Debian project (and may be used by others). + +.SH SEE ALSO +.BR cwebp (1), +.BR dwebp (1), +.BR webpmux (1) +.br +Please refer to https://developers.google.com/speed/webp/ for additional +information. diff --git a/third-party/webp/libwebp/man/img2webp.1 b/third-party/webp/libwebp/man/img2webp.1 new file mode 100644 index 0000000000..fc493e1239 --- /dev/null +++ b/third-party/webp/libwebp/man/img2webp.1 @@ -0,0 +1,117 @@ +.\" Hey, EMACS: -*- nroff -*- +.TH IMG2WEBP 1 "March 17, 2023" +.SH NAME +img2webp \- create animated WebP file from a sequence of input images. +.SH SYNOPSIS +.B img2webp +[file_options] [[frame_options] frame_file]... [\-o webp_file] +.br +.B img2webp argument_file_name +.br +.SH DESCRIPTION +This manual page documents the +.B img2webp +command. +.PP +\fBimg2webp\fP compresses a sequence of images using the animated WebP format. +Input images can either be PNG, JPEG, TIFF or WebP. +If a single file name (not starting with the character '\-') is supplied as +the argument, the command line arguments are actually tokenized from this file. +This allows for easy scripting or using a large number of arguments. +.SH FILE-LEVEL OPTIONS +The file-level options are applied at the beginning of the compression process, +before the input frames are read. +.TP +.BI \-o " string +Specify the name of the output WebP file. +.TP +.BI \-min_size +Encode images to achieve smallest size. This disables key frame insertion and +picks the parameters resulting in the smallest output for each frame. It uses +lossless compression by default, but can be combined with \-q, \-m, \-lossy or +\-mixed options. +.TP +.BI \-kmin " int +.TP +.BI \-kmax " int +Specify the minimum and maximum distance between consecutive key frames +(independently decodable frames) in the output animation. The tool will insert +some key frames into the output animation as needed so that this criteria is +satisfied. +.br +.B \-mixed +Mixed compression mode: optimize compression of the image by picking either +lossy or lossless compression for each frame heuristically. This global +option disables the local option \fB-lossy\fP and \fB-lossless\fP . +.TP +.BI \-near_lossless " int +Specify the level of near\-lossless image preprocessing. This option adjusts +pixel values to help compressibility, but has minimal impact on the visual +quality. It triggers lossless compression mode automatically. The range is 0 +(maximum preprocessing) to 100 (no preprocessing, the default). The typical +value is around 60. Note that lossy with \fB\-q 100\fP can at times yield +better results. +.TP +.B \-sharp_yuv +Use more accurate and sharper RGB->YUV conversion if needed. Note that this +process is slower than the default 'fast' RGB->YUV conversion. +.TP +.BI \-loop " int +Specifies the number of times the animation should loop. Using '0' +means 'loop indefinitely'. +.TP +.BI \-v +Be more verbose. +.TP +.B \-h, \-help +A short usage summary. +.TP +.B \-version +Print the version numbers of the relevant libraries used. + +.SH PER-FRAME OPTIONS +The per-frame options are applied for the images following as arguments in the +command line. They can be modified any number of times preceding each particular +input image. +.TP +.BI \-d " int +Specify the image duration in milliseconds. +.TP +.B \-lossless, \-lossy +Compress the next image(s) using lossless or lossy compression mode. The +default mode is lossless. +.TP +.BI \-q " float +Specify the compression factor between 0 and 100. The default is 75. +.TP +.BI \-m " int +Specify the compression method to use. This parameter controls the +trade off between encoding speed and the compressed file size and quality. +Possible values range from 0 to 6. Default value is 4. + +.SH EXAMPLE +img2webp -loop 2 in0.png -lossy in1.jpg -d 80 in2.tiff -o out.webp +.br + +.SH BUGS +Please report all bugs to the issue tracker: +https://bugs.chromium.org/p/webp +.br +Patches welcome! See this page to get started: +https://www.webmproject.org/code/contribute/submitting\-patches/ + +.SH AUTHORS +\fBimg2webp\fP is a part of libwebp and was written by the WebP team. +.br +The latest source tree is available at +https://chromium.googlesource.com/webm/libwebp +.PP +This manual page was written by Pascal Massimino , +for the Debian project (and may be used by others). + +.SH SEE ALSO +.BR webpmux (1), +.BR gif2webp (1) +.br +Please refer to https://developers.google.com/speed/webp/ for additional +information. diff --git a/third-party/webp/libwebp/man/vwebp.1 b/third-party/webp/libwebp/man/vwebp.1 new file mode 100644 index 0000000000..fa48db6d78 --- /dev/null +++ b/third-party/webp/libwebp/man/vwebp.1 @@ -0,0 +1,101 @@ +.\" Hey, EMACS: -*- nroff -*- +.TH VWEBP 1 "November 17, 2021" +.SH NAME +vwebp \- decompress a WebP file and display it in a window +.SH SYNOPSIS +.B vwebp +.RI [ options ] " input_file.webp +.br +.SH DESCRIPTION +This manual page documents the +.B vwebp +command. +.PP +\fBvwebp\fP decompresses a WebP file and displays it in a window using OpenGL. +.SH OPTIONS +.TP +.B \-h +Print usage summary. +.TP +.B \-version +Print version number and exit. +.TP +.B \-noicc +Don't use the ICC profile if present. +.TP +.B \-nofancy +Don't use the fancy YUV420 upscaler. +.TP +.B \-nofilter +Disable in-loop filtering. +.TP +.BI \-dither " strength +Specify a dithering \fBstrength\fP between 0 and 100. Dithering is a +post-processing effect applied to chroma components in lossy compression. +It helps by smoothing gradients and avoiding banding artifacts. Default: 50. +.TP +.BI \-noalphadither +By default, quantized transparency planes are dithered during decompression, +to smooth the gradients. This flag will prevent this dithering. +.TP +.B \-usebgcolor +Fill transparent areas with the bitstream's own background color instead of +checkerboard only. Default is white for non-animated images. +.TP +.B \-mt +Use multi-threading for decoding, if possible. +.TP +.B \-info +Display image information on top of the decoded image. +.TP +.BI \-\- " string +Explicitly specify the input file. This option is useful if the input +file starts with an '\-' for instance. This option must appear \fBlast\fP. +Any other options afterward will be ignored. If the input file is "\-", +the data will be read from \fIstdin\fP instead of a file. +.TP + +.SH KEYBOARD SHORTCUTS +.TP +.B 'c' +Toggle use of color profile. +.TP +.B 'b' +Toggle display of background color. +.TP +.B 'i' +Overlay file information. +.TP +.B 'd' +Disable blending and disposal process, for debugging purposes. +.TP +.B 'q' / 'Q' / ESC +Quit. + +.SH BUGS +Please report all bugs to the issue tracker: +https://bugs.chromium.org/p/webp +.br +Patches welcome! See this page to get started: +https://www.webmproject.org/code/contribute/submitting\-patches/ + +.SH EXAMPLES +vwebp picture.webp +.br +vwebp picture.webp -mt -dither 0 +.br +vwebp \-\- \-\-\-picture.webp + +.SH AUTHORS +\fBvwebp\fP is a part of libwebp and was written by the WebP team. +.br +The latest source tree is available at +https://chromium.googlesource.com/webm/libwebp +.PP +This manual page was written for the Debian project (and may be used by others). + +.SH SEE ALSO +.BR dwebp (1) +.br +Please refer to https://developers.google.com/speed/webp/ for additional +information. diff --git a/third-party/webp/libwebp/man/webpinfo.1 b/third-party/webp/libwebp/man/webpinfo.1 new file mode 100644 index 0000000000..35d6d92f28 --- /dev/null +++ b/third-party/webp/libwebp/man/webpinfo.1 @@ -0,0 +1,80 @@ +.\" Hey, EMACS: -*- nroff -*- +.TH WEBPINFO 1 "November 17, 2021" +.SH NAME +webpinfo \- print out the chunk level structure of WebP files +along with basic integrity checks. +.SH SYNOPSIS +.B webpinfo +.I OPTIONS +.I INPUT +.br +.B webpinfo [\-h|\-help|\-H|\-longhelp] +.br + +.SH DESCRIPTION +This manual page documents the +.B webpinfo +command. +.PP +\fBwebpinfo\fP can be used to print out the chunk level structure and bitstream +header information of WebP files. It can also check if the files are of valid +WebP format. + +.SH OPTIONS +.TP +.B \-version +Print the version number (as major.minor.revision) and exit. +.TP +.B \-quiet +Do not show chunk parsing information. +.TP +.B \-diag +Show parsing error diagnosis. +.TP +.B \-summary +Show chunk stats summary. +.TP +.BI \-bitstream_info +Parse bitstream header. +.TP +.B \-h, \-help +A short usage summary. +.TP +.B \-H, \-longhelp +Detailed usage instructions. + +.SH INPUT +Input files in WebP format. Input files must come last, following +options (if any). There can be multiple input files. + +.SH BUGS +Please report all bugs to the issue tracker: +https://bugs.chromium.org/p/webp +.br +Patches welcome! See this page to get started: +https://www.webmproject.org/code/contribute/submitting\-patches/ + +.SH EXAMPLES +.br +webpinfo \-h +.br +webpinfo \-diag \-summary input_file.webp +.br +webpinfo \-bitstream_info input_file_1.webp input_file_2.webp +.br +webpinfo *.webp + +.SH AUTHORS +\fBwebpinfo\fP is a part of libwebp and was written by the WebP team. +.br +The latest source tree is available at +https://chromium.googlesource.com/webm/libwebp +.PP +This manual page was written by Hui Su , +for the Debian project (and may be used by others). + +.SH SEE ALSO +.BR webpmux (1) +.br +Please refer to https://developers.google.com/speed/webp/ for additional +information. diff --git a/third-party/webp/libwebp/man/webpmux.1 b/third-party/webp/libwebp/man/webpmux.1 new file mode 100644 index 0000000000..07e8738952 --- /dev/null +++ b/third-party/webp/libwebp/man/webpmux.1 @@ -0,0 +1,271 @@ +.\" Hey, EMACS: -*- nroff -*- +.TH WEBPMUX 1 "November 17, 2021" +.SH NAME +webpmux \- create animated WebP files from non\-animated WebP images, extract +frames from animated WebP images, and manage XMP/EXIF metadata and ICC profile. +.SH SYNOPSIS +.B webpmux \-get +.I GET_OPTIONS +.I INPUT +.B \-o +.I OUTPUT +.br +.B webpmux \-set +.I SET_OPTIONS +.I INPUT +.B \-o +.I OUTPUT +.br +.B webpmux \-strip +.I STRIP_OPTIONS +.I INPUT +.B \-o +.I OUTPUT +.br +.B webpmux \-frame +.I FRAME_OPTIONS +.B [ \-frame ... ] [ \-loop +.I LOOP_COUNT +.B ] +.br +.RS 8 +.B [ \-bgcolor +.I BACKGROUND_COLOR +.B ] \-o +.I OUTPUT +.RE +.br +.B webpmux \-duration +.I DURATION OPTIONS +.B [ \-duration ... ] +.I INPUT +.B \-o +.I OUTPUT +.br +.B webpmux \-info +.I INPUT +.br +.B webpmux [\-h|\-help] +.br +.B webpmux \-version +.br +.B webpmux argument_file_name +.SH DESCRIPTION +This manual page documents the +.B webpmux +command. +.PP +\fBwebpmux\fP can be used to create/extract from animated WebP files, as well as +to add/extract/strip XMP/EXIF metadata and ICC profile. +If a single file name (not starting with the character '\-') is supplied as +the argument, the command line arguments are actually tokenized from this file. +This allows for easy scripting or using a large number of arguments. +.SH OPTIONS +.SS GET_OPTIONS (\-get): +.TP +.B icc +Get ICC profile. +.TP +.B exif +Get EXIF metadata. +.TP +.B xmp +Get XMP metadata. +.TP +.BI frame " n +Get nth frame from an animated image. (n = 0 has a special meaning: last frame). + +.SS SET_OPTIONS (\-set) +.TP +.BI loop " loop_count +Set loop count on an animated file. +.P +Where: 'loop_count' must be in range [0, 65535]. +.TP +.BI bgcolor " A,R,G,B +Set the background color of the canvas on an animated file. +.P +where: 'A', 'R', 'G' and 'B' are integers in the range 0 to 255 specifying the +Alpha, Red, Green and Blue component values respectively. +.TP +.BI icc " file.icc +Set ICC profile. +.P +Where: 'file.icc' contains the ICC profile to be set. +.TP +.BI exif " file.exif +Set EXIF metadata. +.P +Where: 'file.exif' contains the EXIF metadata to be set. +.TP +.BI xmp " file.xmp +Set XMP metadata. +.P +Where: 'file.xmp' contains the XMP metadata to be set. + +.SS STRIP_OPTIONS (\-strip) +.TP +.B icc +Strip ICC profile. +.TP +.B exif +Strip EXIF metadata. +.TP +.B xmp +Strip XMP metadata. + +.SS DURATION_OPTIONS (\-duration) +Amend the duration of a specific interval of frames. This option is only +effective on animated WebP and has no effect on a single-frame file. +.TP +.I duration[,start[,end]] +Where: +.br +.B duration +is the duration for the interval in milliseconds (mandatory). +Must be non-negative. +.br +.B start +is the starting frame index of the interval (optional). +.br +.B end +is the ending frame index (inclusive) of the interval (optional). +.TP +The three typical usages of this option are: +.br +.B -duration d + set the duration to 'd' for the whole animation. +.br +.B -duration d,f + set the duration of frame 'f' to 'd'. +.br +.B -duration d,start,end + set the duration to 'd' for the whole [start,end] interval. +.TP +.P +Note that the frames outside of the [start, end] interval will remain untouched. +The 'end' value '0' has the special meaning 'last frame of the animation'. +.TP +.I Reminder: +frame indexing starts at '1'. +.br + +.SS FRAME_OPTIONS (\-frame) +Create an animated WebP file from multiple (non\-animated) WebP images. +.TP +.I file_i +di[+xi+yi[+mi[bi]]] +Where: 'file_i' is the i'th frame (WebP format), 'xi','yi' specify the image +offset for this frame, 'di' is the pause duration before next frame, 'mi' is +the dispose method for this frame (0 for NONE or 1 for BACKGROUND) and 'bi' is +the blending method for this frame (+b for BLEND or \-b for NO_BLEND). +Argument 'bi' can be omitted and will default to +b (BLEND). +Also, 'mi' can be omitted if 'bi' is omitted and will default to 0 (NONE). +Finally, if 'mi' and 'bi' are omitted then 'xi' and 'yi' can be omitted and will +default to +0+0. +.TP +.BI \-loop " n +Loop the frames n number of times. 0 indicates the frames should loop forever. +Valid range is 0 to 65535 [Default: 0 (infinite)]. +.TP +.BI \-bgcolor " A,R,G,B +Background color of the canvas. +.br +where: 'A', 'R', 'G' and 'B' are integers in the range 0 to 255 specifying the +Alpha, Red, Green and Blue component values respectively +[Default: 255,255,255,255]. + +.SS INPUT +.TP +Input file in WebP format. + +.SS OUTPUT (\-o) +.TP +Output file in WebP format. + +.SS Note: +.TP +The nature of EXIF, XMP and ICC data is not checked and is assumed to be valid. + +.SH BUGS +Please report all bugs to the issue tracker: +https://bugs.chromium.org/p/webp +.br +Patches welcome! See this page to get started: +https://www.webmproject.org/code/contribute/submitting\-patches/ + +.SH EXAMPLES +.P +Add ICC profile: +.br +webpmux \-set icc image_profile.icc in.webp \-o icc_container.webp +.P +Extract ICC profile: +.br +webpmux \-get icc icc_container.webp \-o image_profile.icc +.P +Strip ICC profile: +.br +webpmux \-strip icc icc_container.webp \-o without_icc.webp +.P +Add XMP metadata: +.br +webpmux \-set xmp image_metadata.xmp in.webp \-o xmp_container.webp +.P +Extract XMP metadata: +.br +webpmux \-get xmp xmp_container.webp \-o image_metadata.xmp +.P +Strip XMP metadata: +.br +webpmux \-strip xmp xmp_container.webp \-o without_xmp.webp +.P +Add EXIF metadata: +.br +webpmux \-set exif image_metadata.exif in.webp \-o exif_container.webp +.P +Extract EXIF metadata: +.br +webpmux \-get exif exif_container.webp \-o image_metadata.exif +.P +Strip EXIF metadata: +.br +webpmux \-strip exif exif_container.webp \-o without_exif.webp +.P +Create an animated WebP file from 3 (non\-animated) WebP images: +.br +webpmux \-frame 1.webp +100 \-frame 2.webp +100+50+50 +.br +.RS 8 +\-frame 3.webp +100+50+50+1+b \-loop 10 \-bgcolor 255,255,255,255 +.br +\-o anim_container.webp +.RE +.P +Get the 2nd frame from an animated WebP file: +.br +webpmux \-get frame 2 anim_container.webp \-o frame_2.webp +.P +Using \-get/\-set/\-strip with input file name starting with '\-': +.br +webpmux \-set icc image_profile.icc \-o icc_container.webp \-\- \-\-\-in.webp +.br +webpmux \-get icc \-o image_profile.icc \-\- \-\-\-icc_container.webp +.br +webpmux \-strip icc \-o without_icc.webp \-\- \-\-\-icc_container.webp + +.SH AUTHORS +\fBwebpmux\fP is a part of libwebp and was written by the WebP team. +.br +The latest source tree is available at +https://chromium.googlesource.com/webm/libwebp +.PP +This manual page was written by Vikas Arora , +for the Debian project (and may be used by others). + +.SH SEE ALSO +.BR cwebp (1), +.BR dwebp (1), +.BR gif2webp (1) +.br +Please refer to https://developers.google.com/speed/webp/ for additional +information. diff --git a/third-party/webp/libwebp/sharpyuv/Makefile.am b/third-party/webp/libwebp/sharpyuv/Makefile.am new file mode 100644 index 0000000000..8d9ba7cadd --- /dev/null +++ b/third-party/webp/libwebp/sharpyuv/Makefile.am @@ -0,0 +1,41 @@ +AM_CPPFLAGS += -I$(top_builddir) -I$(top_srcdir) +AM_CPPFLAGS += -I$(top_builddir)/src -I$(top_srcdir)/src + +lib_LTLIBRARIES = libsharpyuv.la + +noinst_LTLIBRARIES = +noinst_LTLIBRARIES += libsharpyuv_sse2.la +noinst_LTLIBRARIES += libsharpyuv_neon.la + +libsharpyuvinclude_HEADERS = +libsharpyuvinclude_HEADERS += sharpyuv.h +libsharpyuvinclude_HEADERS += sharpyuv_csp.h +noinst_HEADERS = +noinst_HEADERS += ../src/dsp/cpu.c +noinst_HEADERS += ../src/dsp/cpu.h +noinst_HEADERS += ../src/webp/types.h + +libsharpyuv_sse2_la_SOURCES = +libsharpyuv_sse2_la_SOURCES += sharpyuv_sse2.c +libsharpyuv_sse2_la_CPPFLAGS = $(libsharpyuv_la_CPPFLAGS) +libsharpyuv_sse2_la_CFLAGS = $(AM_CFLAGS) $(SSE2_FLAGS) + +libsharpyuv_neon_la_SOURCES = +libsharpyuv_neon_la_SOURCES += sharpyuv_neon.c +libsharpyuv_neon_la_CPPFLAGS = $(libsharpyuv_la_CPPFLAGS) +libsharpyuv_neon_la_CFLAGS = $(AM_CFLAGS) $(NEON_FLAGS) + +libsharpyuv_la_SOURCES = +libsharpyuv_la_SOURCES += sharpyuv_cpu.c sharpyuv_cpu.h +libsharpyuv_la_SOURCES += sharpyuv_csp.c sharpyuv_csp.h +libsharpyuv_la_SOURCES += sharpyuv_dsp.c sharpyuv_dsp.h +libsharpyuv_la_SOURCES += sharpyuv_gamma.c sharpyuv_gamma.h +libsharpyuv_la_SOURCES += sharpyuv.c sharpyuv.h + +libsharpyuv_la_CPPFLAGS = $(AM_CPPFLAGS) +libsharpyuv_la_LDFLAGS = -no-undefined -version-info 0:1:0 -lm +libsharpyuv_la_LIBADD = +libsharpyuv_la_LIBADD += libsharpyuv_sse2.la +libsharpyuv_la_LIBADD += libsharpyuv_neon.la +libsharpyuvincludedir = $(includedir)/webp/sharpyuv +pkgconfig_DATA = libsharpyuv.pc diff --git a/third-party/webp/libwebp/sharpyuv/libsharpyuv.pc.in b/third-party/webp/libwebp/sharpyuv/libsharpyuv.pc.in new file mode 100644 index 0000000000..0fb565a61e --- /dev/null +++ b/third-party/webp/libwebp/sharpyuv/libsharpyuv.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/webp + +Name: libsharpyuv +Description: Library for sharp RGB to YUV conversion +Version: @PACKAGE_VERSION@ +Cflags: -I${includedir} +Libs: -L${libdir} -l@webp_libname_prefix@sharpyuv +Libs.private: -lm @PTHREAD_CFLAGS@ @PTHREAD_LIBS@ diff --git a/third-party/webp/libwebp/sharpyuv/libsharpyuv.rc b/third-party/webp/libwebp/sharpyuv/libsharpyuv.rc new file mode 100644 index 0000000000..49c338a3f1 --- /dev/null +++ b/third-party/webp/libwebp/sharpyuv/libsharpyuv.rc @@ -0,0 +1,41 @@ +#define APSTUDIO_READONLY_SYMBOLS +#include "winres.h" +#undef APSTUDIO_READONLY_SYMBOLS + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 0,0,2,1 + PRODUCTVERSION 0,0,2,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "Google, Inc." + VALUE "FileDescription", "libsharpyuv DLL" + VALUE "FileVersion", "0.2.1" + VALUE "InternalName", "libsharpyuv.dll" + VALUE "LegalCopyright", "Copyright (C) 2023" + VALUE "OriginalFilename", "libsharpyuv.dll" + VALUE "ProductName", "SharpYuv Library" + VALUE "ProductVersion", "0.2.1" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // English (United States) resources diff --git a/third-party/webp/libwebp/sharpyuv/sharpyuv.c b/third-party/webp/libwebp/sharpyuv/sharpyuv.c new file mode 100644 index 0000000000..b94885a6c3 --- /dev/null +++ b/third-party/webp/libwebp/sharpyuv/sharpyuv.c @@ -0,0 +1,565 @@ +// Copyright 2022 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Sharp RGB to YUV conversion. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "sharpyuv/sharpyuv.h" + +#include +#include +#include +#include +#include + +#include "src/webp/types.h" +#include "sharpyuv/sharpyuv_cpu.h" +#include "sharpyuv/sharpyuv_dsp.h" +#include "sharpyuv/sharpyuv_gamma.h" + +//------------------------------------------------------------------------------ + +int SharpYuvGetVersion(void) { + return SHARPYUV_VERSION; +} + +//------------------------------------------------------------------------------ +// Sharp RGB->YUV conversion + +static const int kNumIterations = 4; + +#define YUV_FIX 16 // fixed-point precision for RGB->YUV +static const int kYuvHalf = 1 << (YUV_FIX - 1); + +// Max bit depth so that intermediate calculations fit in 16 bits. +static const int kMaxBitDepth = 14; + +// Returns the precision shift to use based on the input rgb_bit_depth. +static int GetPrecisionShift(int rgb_bit_depth) { + // Try to add 2 bits of precision if it fits in kMaxBitDepth. Otherwise remove + // bits if needed. + return ((rgb_bit_depth + 2) <= kMaxBitDepth) ? 2 + : (kMaxBitDepth - rgb_bit_depth); +} + +typedef int16_t fixed_t; // signed type with extra precision for UV +typedef uint16_t fixed_y_t; // unsigned type with extra precision for W + +//------------------------------------------------------------------------------ + +static uint8_t clip_8b(fixed_t v) { + return (!(v & ~0xff)) ? (uint8_t)v : (v < 0) ? 0u : 255u; +} + +static uint16_t clip(fixed_t v, int max) { + return (v < 0) ? 0 : (v > max) ? max : (uint16_t)v; +} + +static fixed_y_t clip_bit_depth(int y, int bit_depth) { + const int max = (1 << bit_depth) - 1; + return (!(y & ~max)) ? (fixed_y_t)y : (y < 0) ? 0 : max; +} + +//------------------------------------------------------------------------------ + +static int RGBToGray(int64_t r, int64_t g, int64_t b) { + const int64_t luma = 13933 * r + 46871 * g + 4732 * b + kYuvHalf; + return (int)(luma >> YUV_FIX); +} + +static uint32_t ScaleDown(uint16_t a, uint16_t b, uint16_t c, uint16_t d, + int rgb_bit_depth, + SharpYuvTransferFunctionType transfer_type) { + const int bit_depth = rgb_bit_depth + GetPrecisionShift(rgb_bit_depth); + const uint32_t A = SharpYuvGammaToLinear(a, bit_depth, transfer_type); + const uint32_t B = SharpYuvGammaToLinear(b, bit_depth, transfer_type); + const uint32_t C = SharpYuvGammaToLinear(c, bit_depth, transfer_type); + const uint32_t D = SharpYuvGammaToLinear(d, bit_depth, transfer_type); + return SharpYuvLinearToGamma((A + B + C + D + 2) >> 2, bit_depth, + transfer_type); +} + +static WEBP_INLINE void UpdateW(const fixed_y_t* src, fixed_y_t* dst, int w, + int rgb_bit_depth, + SharpYuvTransferFunctionType transfer_type) { + const int bit_depth = rgb_bit_depth + GetPrecisionShift(rgb_bit_depth); + int i; + for (i = 0; i < w; ++i) { + const uint32_t R = + SharpYuvGammaToLinear(src[0 * w + i], bit_depth, transfer_type); + const uint32_t G = + SharpYuvGammaToLinear(src[1 * w + i], bit_depth, transfer_type); + const uint32_t B = + SharpYuvGammaToLinear(src[2 * w + i], bit_depth, transfer_type); + const uint32_t Y = RGBToGray(R, G, B); + dst[i] = (fixed_y_t)SharpYuvLinearToGamma(Y, bit_depth, transfer_type); + } +} + +static void UpdateChroma(const fixed_y_t* src1, const fixed_y_t* src2, + fixed_t* dst, int uv_w, int rgb_bit_depth, + SharpYuvTransferFunctionType transfer_type) { + int i; + for (i = 0; i < uv_w; ++i) { + const int r = + ScaleDown(src1[0 * uv_w + 0], src1[0 * uv_w + 1], src2[0 * uv_w + 0], + src2[0 * uv_w + 1], rgb_bit_depth, transfer_type); + const int g = + ScaleDown(src1[2 * uv_w + 0], src1[2 * uv_w + 1], src2[2 * uv_w + 0], + src2[2 * uv_w + 1], rgb_bit_depth, transfer_type); + const int b = + ScaleDown(src1[4 * uv_w + 0], src1[4 * uv_w + 1], src2[4 * uv_w + 0], + src2[4 * uv_w + 1], rgb_bit_depth, transfer_type); + const int W = RGBToGray(r, g, b); + dst[0 * uv_w] = (fixed_t)(r - W); + dst[1 * uv_w] = (fixed_t)(g - W); + dst[2 * uv_w] = (fixed_t)(b - W); + dst += 1; + src1 += 2; + src2 += 2; + } +} + +static void StoreGray(const fixed_y_t* rgb, fixed_y_t* y, int w) { + int i; + assert(w > 0); + for (i = 0; i < w; ++i) { + y[i] = RGBToGray(rgb[0 * w + i], rgb[1 * w + i], rgb[2 * w + i]); + } +} + +//------------------------------------------------------------------------------ + +static WEBP_INLINE fixed_y_t Filter2(int A, int B, int W0, int bit_depth) { + const int v0 = (A * 3 + B + 2) >> 2; + return clip_bit_depth(v0 + W0, bit_depth); +} + +//------------------------------------------------------------------------------ + +static WEBP_INLINE int Shift(int v, int shift) { + return (shift >= 0) ? (v << shift) : (v >> -shift); +} + +static void ImportOneRow(const uint8_t* const r_ptr, + const uint8_t* const g_ptr, + const uint8_t* const b_ptr, + int rgb_step, + int rgb_bit_depth, + int pic_width, + fixed_y_t* const dst) { + // Convert the rgb_step from a number of bytes to a number of uint8_t or + // uint16_t values depending the bit depth. + const int step = (rgb_bit_depth > 8) ? rgb_step / 2 : rgb_step; + int i; + const int w = (pic_width + 1) & ~1; + for (i = 0; i < pic_width; ++i) { + const int off = i * step; + const int shift = GetPrecisionShift(rgb_bit_depth); + if (rgb_bit_depth == 8) { + dst[i + 0 * w] = Shift(r_ptr[off], shift); + dst[i + 1 * w] = Shift(g_ptr[off], shift); + dst[i + 2 * w] = Shift(b_ptr[off], shift); + } else { + dst[i + 0 * w] = Shift(((uint16_t*)r_ptr)[off], shift); + dst[i + 1 * w] = Shift(((uint16_t*)g_ptr)[off], shift); + dst[i + 2 * w] = Shift(((uint16_t*)b_ptr)[off], shift); + } + } + if (pic_width & 1) { // replicate rightmost pixel + dst[pic_width + 0 * w] = dst[pic_width + 0 * w - 1]; + dst[pic_width + 1 * w] = dst[pic_width + 1 * w - 1]; + dst[pic_width + 2 * w] = dst[pic_width + 2 * w - 1]; + } +} + +static void InterpolateTwoRows(const fixed_y_t* const best_y, + const fixed_t* prev_uv, + const fixed_t* cur_uv, + const fixed_t* next_uv, + int w, + fixed_y_t* out1, + fixed_y_t* out2, + int rgb_bit_depth) { + const int uv_w = w >> 1; + const int len = (w - 1) >> 1; // length to filter + int k = 3; + const int bit_depth = rgb_bit_depth + GetPrecisionShift(rgb_bit_depth); + while (k-- > 0) { // process each R/G/B segments in turn + // special boundary case for i==0 + out1[0] = Filter2(cur_uv[0], prev_uv[0], best_y[0], bit_depth); + out2[0] = Filter2(cur_uv[0], next_uv[0], best_y[w], bit_depth); + + SharpYuvFilterRow(cur_uv, prev_uv, len, best_y + 0 + 1, out1 + 1, + bit_depth); + SharpYuvFilterRow(cur_uv, next_uv, len, best_y + w + 1, out2 + 1, + bit_depth); + + // special boundary case for i == w - 1 when w is even + if (!(w & 1)) { + out1[w - 1] = Filter2(cur_uv[uv_w - 1], prev_uv[uv_w - 1], + best_y[w - 1 + 0], bit_depth); + out2[w - 1] = Filter2(cur_uv[uv_w - 1], next_uv[uv_w - 1], + best_y[w - 1 + w], bit_depth); + } + out1 += w; + out2 += w; + prev_uv += uv_w; + cur_uv += uv_w; + next_uv += uv_w; + } +} + +static WEBP_INLINE int RGBToYUVComponent(int r, int g, int b, + const int coeffs[4], int sfix) { + const int srounder = 1 << (YUV_FIX + sfix - 1); + const int luma = coeffs[0] * r + coeffs[1] * g + coeffs[2] * b + + coeffs[3] + srounder; + return (luma >> (YUV_FIX + sfix)); +} + +static int ConvertWRGBToYUV(const fixed_y_t* best_y, const fixed_t* best_uv, + uint8_t* y_ptr, int y_stride, uint8_t* u_ptr, + int u_stride, uint8_t* v_ptr, int v_stride, + int rgb_bit_depth, + int yuv_bit_depth, int width, int height, + const SharpYuvConversionMatrix* yuv_matrix) { + int i, j; + const fixed_t* const best_uv_base = best_uv; + const int w = (width + 1) & ~1; + const int h = (height + 1) & ~1; + const int uv_w = w >> 1; + const int uv_h = h >> 1; + const int sfix = GetPrecisionShift(rgb_bit_depth); + const int yuv_max = (1 << yuv_bit_depth) - 1; + + for (best_uv = best_uv_base, j = 0; j < height; ++j) { + for (i = 0; i < width; ++i) { + const int off = (i >> 1); + const int W = best_y[i]; + const int r = best_uv[off + 0 * uv_w] + W; + const int g = best_uv[off + 1 * uv_w] + W; + const int b = best_uv[off + 2 * uv_w] + W; + const int y = RGBToYUVComponent(r, g, b, yuv_matrix->rgb_to_y, sfix); + if (yuv_bit_depth <= 8) { + y_ptr[i] = clip_8b(y); + } else { + ((uint16_t*)y_ptr)[i] = clip(y, yuv_max); + } + } + best_y += w; + best_uv += (j & 1) * 3 * uv_w; + y_ptr += y_stride; + } + for (best_uv = best_uv_base, j = 0; j < uv_h; ++j) { + for (i = 0; i < uv_w; ++i) { + const int off = i; + // Note r, g and b values here are off by W, but a constant offset on all + // 3 components doesn't change the value of u and v with a YCbCr matrix. + const int r = best_uv[off + 0 * uv_w]; + const int g = best_uv[off + 1 * uv_w]; + const int b = best_uv[off + 2 * uv_w]; + const int u = RGBToYUVComponent(r, g, b, yuv_matrix->rgb_to_u, sfix); + const int v = RGBToYUVComponent(r, g, b, yuv_matrix->rgb_to_v, sfix); + if (yuv_bit_depth <= 8) { + u_ptr[i] = clip_8b(u); + v_ptr[i] = clip_8b(v); + } else { + ((uint16_t*)u_ptr)[i] = clip(u, yuv_max); + ((uint16_t*)v_ptr)[i] = clip(v, yuv_max); + } + } + best_uv += 3 * uv_w; + u_ptr += u_stride; + v_ptr += v_stride; + } + return 1; +} + +//------------------------------------------------------------------------------ +// Main function + +static void* SafeMalloc(uint64_t nmemb, size_t size) { + const uint64_t total_size = nmemb * (uint64_t)size; + if (total_size != (size_t)total_size) return NULL; + return malloc((size_t)total_size); +} + +#define SAFE_ALLOC(W, H, T) ((T*)SafeMalloc((W) * (H), sizeof(T))) + +static int DoSharpArgbToYuv(const uint8_t* r_ptr, const uint8_t* g_ptr, + const uint8_t* b_ptr, int rgb_step, int rgb_stride, + int rgb_bit_depth, uint8_t* y_ptr, int y_stride, + uint8_t* u_ptr, int u_stride, uint8_t* v_ptr, + int v_stride, int yuv_bit_depth, int width, + int height, + const SharpYuvConversionMatrix* yuv_matrix, + SharpYuvTransferFunctionType transfer_type) { + // we expand the right/bottom border if needed + const int w = (width + 1) & ~1; + const int h = (height + 1) & ~1; + const int uv_w = w >> 1; + const int uv_h = h >> 1; + uint64_t prev_diff_y_sum = ~0; + int j, iter; + + // TODO(skal): allocate one big memory chunk. But for now, it's easier + // for valgrind debugging to have several chunks. + fixed_y_t* const tmp_buffer = SAFE_ALLOC(w * 3, 2, fixed_y_t); // scratch + fixed_y_t* const best_y_base = SAFE_ALLOC(w, h, fixed_y_t); + fixed_y_t* const target_y_base = SAFE_ALLOC(w, h, fixed_y_t); + fixed_y_t* const best_rgb_y = SAFE_ALLOC(w, 2, fixed_y_t); + fixed_t* const best_uv_base = SAFE_ALLOC(uv_w * 3, uv_h, fixed_t); + fixed_t* const target_uv_base = SAFE_ALLOC(uv_w * 3, uv_h, fixed_t); + fixed_t* const best_rgb_uv = SAFE_ALLOC(uv_w * 3, 1, fixed_t); + fixed_y_t* best_y = best_y_base; + fixed_y_t* target_y = target_y_base; + fixed_t* best_uv = best_uv_base; + fixed_t* target_uv = target_uv_base; + const uint64_t diff_y_threshold = (uint64_t)(3.0 * w * h); + int ok; + assert(w > 0); + assert(h > 0); + + if (best_y_base == NULL || best_uv_base == NULL || + target_y_base == NULL || target_uv_base == NULL || + best_rgb_y == NULL || best_rgb_uv == NULL || + tmp_buffer == NULL) { + ok = 0; + goto End; + } + + // Import RGB samples to W/RGB representation. + for (j = 0; j < height; j += 2) { + const int is_last_row = (j == height - 1); + fixed_y_t* const src1 = tmp_buffer + 0 * w; + fixed_y_t* const src2 = tmp_buffer + 3 * w; + + // prepare two rows of input + ImportOneRow(r_ptr, g_ptr, b_ptr, rgb_step, rgb_bit_depth, width, + src1); + if (!is_last_row) { + ImportOneRow(r_ptr + rgb_stride, g_ptr + rgb_stride, b_ptr + rgb_stride, + rgb_step, rgb_bit_depth, width, src2); + } else { + memcpy(src2, src1, 3 * w * sizeof(*src2)); + } + StoreGray(src1, best_y + 0, w); + StoreGray(src2, best_y + w, w); + + UpdateW(src1, target_y, w, rgb_bit_depth, transfer_type); + UpdateW(src2, target_y + w, w, rgb_bit_depth, transfer_type); + UpdateChroma(src1, src2, target_uv, uv_w, rgb_bit_depth, transfer_type); + memcpy(best_uv, target_uv, 3 * uv_w * sizeof(*best_uv)); + best_y += 2 * w; + best_uv += 3 * uv_w; + target_y += 2 * w; + target_uv += 3 * uv_w; + r_ptr += 2 * rgb_stride; + g_ptr += 2 * rgb_stride; + b_ptr += 2 * rgb_stride; + } + + // Iterate and resolve clipping conflicts. + for (iter = 0; iter < kNumIterations; ++iter) { + const fixed_t* cur_uv = best_uv_base; + const fixed_t* prev_uv = best_uv_base; + uint64_t diff_y_sum = 0; + + best_y = best_y_base; + best_uv = best_uv_base; + target_y = target_y_base; + target_uv = target_uv_base; + for (j = 0; j < h; j += 2) { + fixed_y_t* const src1 = tmp_buffer + 0 * w; + fixed_y_t* const src2 = tmp_buffer + 3 * w; + { + const fixed_t* const next_uv = cur_uv + ((j < h - 2) ? 3 * uv_w : 0); + InterpolateTwoRows(best_y, prev_uv, cur_uv, next_uv, w, + src1, src2, rgb_bit_depth); + prev_uv = cur_uv; + cur_uv = next_uv; + } + + UpdateW(src1, best_rgb_y + 0 * w, w, rgb_bit_depth, transfer_type); + UpdateW(src2, best_rgb_y + 1 * w, w, rgb_bit_depth, transfer_type); + UpdateChroma(src1, src2, best_rgb_uv, uv_w, rgb_bit_depth, transfer_type); + + // update two rows of Y and one row of RGB + diff_y_sum += + SharpYuvUpdateY(target_y, best_rgb_y, best_y, 2 * w, + rgb_bit_depth + GetPrecisionShift(rgb_bit_depth)); + SharpYuvUpdateRGB(target_uv, best_rgb_uv, best_uv, 3 * uv_w); + + best_y += 2 * w; + best_uv += 3 * uv_w; + target_y += 2 * w; + target_uv += 3 * uv_w; + } + // test exit condition + if (iter > 0) { + if (diff_y_sum < diff_y_threshold) break; + if (diff_y_sum > prev_diff_y_sum) break; + } + prev_diff_y_sum = diff_y_sum; + } + + // final reconstruction + ok = ConvertWRGBToYUV(best_y_base, best_uv_base, y_ptr, y_stride, u_ptr, + u_stride, v_ptr, v_stride, rgb_bit_depth, yuv_bit_depth, + width, height, yuv_matrix); + + End: + free(best_y_base); + free(best_uv_base); + free(target_y_base); + free(target_uv_base); + free(best_rgb_y); + free(best_rgb_uv); + free(tmp_buffer); + return ok; +} +#undef SAFE_ALLOC + +#if defined(WEBP_USE_THREAD) && !defined(_WIN32) +#include // NOLINT + +#define LOCK_ACCESS \ + static pthread_mutex_t sharpyuv_lock = PTHREAD_MUTEX_INITIALIZER; \ + if (pthread_mutex_lock(&sharpyuv_lock)) return +#define UNLOCK_ACCESS_AND_RETURN \ + do { \ + (void)pthread_mutex_unlock(&sharpyuv_lock); \ + return; \ + } while (0) +#else // !(defined(WEBP_USE_THREAD) && !defined(_WIN32)) +#define LOCK_ACCESS do {} while (0) +#define UNLOCK_ACCESS_AND_RETURN return +#endif // defined(WEBP_USE_THREAD) && !defined(_WIN32) + +// Hidden exported init function. +// By default SharpYuvConvert calls it with SharpYuvGetCPUInfo. If needed, +// users can declare it as extern and call it with an alternate VP8CPUInfo +// function. +extern VP8CPUInfo SharpYuvGetCPUInfo; +SHARPYUV_EXTERN void SharpYuvInit(VP8CPUInfo cpu_info_func); +void SharpYuvInit(VP8CPUInfo cpu_info_func) { + static volatile VP8CPUInfo sharpyuv_last_cpuinfo_used = + (VP8CPUInfo)&sharpyuv_last_cpuinfo_used; + LOCK_ACCESS; + // Only update SharpYuvGetCPUInfo when called from external code to avoid a + // race on reading the value in SharpYuvConvert(). + if (cpu_info_func != (VP8CPUInfo)&SharpYuvGetCPUInfo) { + SharpYuvGetCPUInfo = cpu_info_func; + } + if (sharpyuv_last_cpuinfo_used == SharpYuvGetCPUInfo) { + UNLOCK_ACCESS_AND_RETURN; + } + + SharpYuvInitDsp(); + SharpYuvInitGammaTables(); + + sharpyuv_last_cpuinfo_used = SharpYuvGetCPUInfo; + UNLOCK_ACCESS_AND_RETURN; +} + +int SharpYuvConvert(const void* r_ptr, const void* g_ptr, const void* b_ptr, + int rgb_step, int rgb_stride, int rgb_bit_depth, + void* y_ptr, int y_stride, void* u_ptr, int u_stride, + void* v_ptr, int v_stride, int yuv_bit_depth, int width, + int height, const SharpYuvConversionMatrix* yuv_matrix) { + SharpYuvOptions options; + options.yuv_matrix = yuv_matrix; + options.transfer_type = kSharpYuvTransferFunctionSrgb; + return SharpYuvConvertWithOptions( + r_ptr, g_ptr, b_ptr, rgb_step, rgb_stride, rgb_bit_depth, y_ptr, y_stride, + u_ptr, u_stride, v_ptr, v_stride, yuv_bit_depth, width, height, &options); +} + +int SharpYuvOptionsInitInternal(const SharpYuvConversionMatrix* yuv_matrix, + SharpYuvOptions* options, int version) { + const int major = (version >> 24); + const int minor = (version >> 16) & 0xff; + if (options == NULL || yuv_matrix == NULL || + (major == SHARPYUV_VERSION_MAJOR && major == 0 && + minor != SHARPYUV_VERSION_MINOR) || + (major != SHARPYUV_VERSION_MAJOR)) { + return 0; + } + options->yuv_matrix = yuv_matrix; + options->transfer_type = kSharpYuvTransferFunctionSrgb; + return 1; +} + +int SharpYuvConvertWithOptions(const void* r_ptr, const void* g_ptr, + const void* b_ptr, int rgb_step, int rgb_stride, + int rgb_bit_depth, void* y_ptr, int y_stride, + void* u_ptr, int u_stride, void* v_ptr, + int v_stride, int yuv_bit_depth, int width, + int height, const SharpYuvOptions* options) { + const SharpYuvConversionMatrix* yuv_matrix = options->yuv_matrix; + SharpYuvTransferFunctionType transfer_type = options->transfer_type; + SharpYuvConversionMatrix scaled_matrix; + const int rgb_max = (1 << rgb_bit_depth) - 1; + const int rgb_round = 1 << (rgb_bit_depth - 1); + const int yuv_max = (1 << yuv_bit_depth) - 1; + const int sfix = GetPrecisionShift(rgb_bit_depth); + + if (width < 1 || height < 1 || width == INT_MAX || height == INT_MAX || + r_ptr == NULL || g_ptr == NULL || b_ptr == NULL || y_ptr == NULL || + u_ptr == NULL || v_ptr == NULL) { + return 0; + } + if (rgb_bit_depth != 8 && rgb_bit_depth != 10 && rgb_bit_depth != 12 && + rgb_bit_depth != 16) { + return 0; + } + if (yuv_bit_depth != 8 && yuv_bit_depth != 10 && yuv_bit_depth != 12) { + return 0; + } + if (rgb_bit_depth > 8 && (rgb_step % 2 != 0 || rgb_stride %2 != 0)) { + // Step/stride should be even for uint16_t buffers. + return 0; + } + if (yuv_bit_depth > 8 && + (y_stride % 2 != 0 || u_stride % 2 != 0 || v_stride % 2 != 0)) { + // Stride should be even for uint16_t buffers. + return 0; + } + // The address of the function pointer is used to avoid a read race. + SharpYuvInit((VP8CPUInfo)&SharpYuvGetCPUInfo); + + // Add scaling factor to go from rgb_bit_depth to yuv_bit_depth, to the + // rgb->yuv conversion matrix. + if (rgb_bit_depth == yuv_bit_depth) { + memcpy(&scaled_matrix, yuv_matrix, sizeof(scaled_matrix)); + } else { + int i; + for (i = 0; i < 3; ++i) { + scaled_matrix.rgb_to_y[i] = + (yuv_matrix->rgb_to_y[i] * yuv_max + rgb_round) / rgb_max; + scaled_matrix.rgb_to_u[i] = + (yuv_matrix->rgb_to_u[i] * yuv_max + rgb_round) / rgb_max; + scaled_matrix.rgb_to_v[i] = + (yuv_matrix->rgb_to_v[i] * yuv_max + rgb_round) / rgb_max; + } + } + // Also incorporate precision change scaling. + scaled_matrix.rgb_to_y[3] = Shift(yuv_matrix->rgb_to_y[3], sfix); + scaled_matrix.rgb_to_u[3] = Shift(yuv_matrix->rgb_to_u[3], sfix); + scaled_matrix.rgb_to_v[3] = Shift(yuv_matrix->rgb_to_v[3], sfix); + + return DoSharpArgbToYuv(r_ptr, g_ptr, b_ptr, rgb_step, rgb_stride, + rgb_bit_depth, y_ptr, y_stride, u_ptr, u_stride, + v_ptr, v_stride, yuv_bit_depth, width, height, + &scaled_matrix, transfer_type); +} + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/sharpyuv/sharpyuv.h b/third-party/webp/libwebp/sharpyuv/sharpyuv.h new file mode 100644 index 0000000000..23a69ce39c --- /dev/null +++ b/third-party/webp/libwebp/sharpyuv/sharpyuv.h @@ -0,0 +1,174 @@ +// Copyright 2022 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Sharp RGB to YUV conversion. + +#ifndef WEBP_SHARPYUV_SHARPYUV_H_ +#define WEBP_SHARPYUV_SHARPYUV_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef SHARPYUV_EXTERN +#ifdef WEBP_EXTERN +#define SHARPYUV_EXTERN WEBP_EXTERN +#else +// This explicitly marks library functions and allows for changing the +// signature for e.g., Windows DLL builds. +#if defined(__GNUC__) && __GNUC__ >= 4 +#define SHARPYUV_EXTERN extern __attribute__((visibility("default"))) +#else +#if defined(_MSC_VER) && defined(WEBP_DLL) +#define SHARPYUV_EXTERN __declspec(dllexport) +#else +#define SHARPYUV_EXTERN extern +#endif /* _MSC_VER && WEBP_DLL */ +#endif /* __GNUC__ >= 4 */ +#endif /* WEBP_EXTERN */ +#endif /* SHARPYUV_EXTERN */ + +#ifndef SHARPYUV_INLINE +#ifdef WEBP_INLINE +#define SHARPYUV_INLINE WEBP_INLINE +#else +#ifndef _MSC_VER +#if defined(__cplusplus) || !defined(__STRICT_ANSI__) || \ + (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) +#define SHARPYUV_INLINE inline +#else +#define SHARPYUV_INLINE +#endif +#else +#define SHARPYUV_INLINE __forceinline +#endif /* _MSC_VER */ +#endif /* WEBP_INLINE */ +#endif /* SHARPYUV_INLINE */ + +// SharpYUV API version following the convention from semver.org +#define SHARPYUV_VERSION_MAJOR 0 +#define SHARPYUV_VERSION_MINOR 4 +#define SHARPYUV_VERSION_PATCH 0 +// Version as a uint32_t. The major number is the high 8 bits. +// The minor number is the middle 8 bits. The patch number is the low 16 bits. +#define SHARPYUV_MAKE_VERSION(MAJOR, MINOR, PATCH) \ + (((MAJOR) << 24) | ((MINOR) << 16) | (PATCH)) +#define SHARPYUV_VERSION \ + SHARPYUV_MAKE_VERSION(SHARPYUV_VERSION_MAJOR, SHARPYUV_VERSION_MINOR, \ + SHARPYUV_VERSION_PATCH) + +// Returns the library's version number, packed in hexadecimal. See +// SHARPYUV_VERSION. +SHARPYUV_EXTERN int SharpYuvGetVersion(void); + +// RGB to YUV conversion matrix, in 16 bit fixed point. +// y = rgb_to_y[0] * r + rgb_to_y[1] * g + rgb_to_y[2] * b + rgb_to_y[3] +// u = rgb_to_u[0] * r + rgb_to_u[1] * g + rgb_to_u[2] * b + rgb_to_u[3] +// v = rgb_to_v[0] * r + rgb_to_v[1] * g + rgb_to_v[2] * b + rgb_to_v[3] +// Then y, u and v values are divided by 1<<16 and rounded. +typedef struct { + int rgb_to_y[4]; + int rgb_to_u[4]; + int rgb_to_v[4]; +} SharpYuvConversionMatrix; + +typedef struct SharpYuvOptions SharpYuvOptions; + +// Enums for transfer functions, as defined in H.273, +// https://www.itu.int/rec/T-REC-H.273-202107-I/en +typedef enum SharpYuvTransferFunctionType { + // 0 is reserved + kSharpYuvTransferFunctionBt709 = 1, + // 2 is unspecified + // 3 is reserved + kSharpYuvTransferFunctionBt470M = 4, + kSharpYuvTransferFunctionBt470Bg = 5, + kSharpYuvTransferFunctionBt601 = 6, + kSharpYuvTransferFunctionSmpte240 = 7, + kSharpYuvTransferFunctionLinear = 8, + kSharpYuvTransferFunctionLog100 = 9, + kSharpYuvTransferFunctionLog100_Sqrt10 = 10, + kSharpYuvTransferFunctionIec61966 = 11, + kSharpYuvTransferFunctionBt1361 = 12, + kSharpYuvTransferFunctionSrgb = 13, + kSharpYuvTransferFunctionBt2020_10Bit = 14, + kSharpYuvTransferFunctionBt2020_12Bit = 15, + kSharpYuvTransferFunctionSmpte2084 = 16, // PQ + kSharpYuvTransferFunctionSmpte428 = 17, + kSharpYuvTransferFunctionHlg = 18, + kSharpYuvTransferFunctionNum +} SharpYuvTransferFunctionType; + +// Converts RGB to YUV420 using a downsampling algorithm that minimizes +// artefacts caused by chroma subsampling. +// This is slower than standard downsampling (averaging of 4 UV values). +// Assumes that the image will be upsampled using a bilinear filter. If nearest +// neighbor is used instead, the upsampled image might look worse than with +// standard downsampling. +// r_ptr, g_ptr, b_ptr: pointers to the source r, g and b channels. Should point +// to uint8_t buffers if rgb_bit_depth is 8, or uint16_t buffers otherwise. +// rgb_step: distance in bytes between two horizontally adjacent pixels on the +// r, g and b channels. If rgb_bit_depth is > 8, it should be a +// multiple of 2. +// rgb_stride: distance in bytes between two vertically adjacent pixels on the +// r, g, and b channels. If rgb_bit_depth is > 8, it should be a +// multiple of 2. +// rgb_bit_depth: number of bits for each r/g/b value. One of: 8, 10, 12, 16. +// Note: 16 bit input is truncated to 14 bits before conversion to yuv. +// yuv_bit_depth: number of bits for each y/u/v value. One of: 8, 10, 12. +// y_ptr, u_ptr, v_ptr: pointers to the destination y, u and v channels. Should +// point to uint8_t buffers if yuv_bit_depth is 8, or uint16_t buffers +// otherwise. +// y_stride, u_stride, v_stride: distance in bytes between two vertically +// adjacent pixels on the y, u and v channels. If yuv_bit_depth > 8, they +// should be multiples of 2. +// width, height: width and height of the image in pixels +// This function calls SharpYuvConvertWithOptions with a default transfer +// function of kSharpYuvTransferFunctionSrgb. +SHARPYUV_EXTERN int SharpYuvConvert(const void* r_ptr, const void* g_ptr, + const void* b_ptr, int rgb_step, + int rgb_stride, int rgb_bit_depth, + void* y_ptr, int y_stride, void* u_ptr, + int u_stride, void* v_ptr, int v_stride, + int yuv_bit_depth, int width, int height, + const SharpYuvConversionMatrix* yuv_matrix); + +struct SharpYuvOptions { + // This matrix cannot be NULL and can be initialized by + // SharpYuvComputeConversionMatrix. + const SharpYuvConversionMatrix* yuv_matrix; + SharpYuvTransferFunctionType transfer_type; +}; + +// Internal, version-checked, entry point +SHARPYUV_EXTERN int SharpYuvOptionsInitInternal(const SharpYuvConversionMatrix*, + SharpYuvOptions*, int); + +// Should always be called, to initialize a fresh SharpYuvOptions +// structure before modification. SharpYuvOptionsInit() must have succeeded +// before using the 'options' object. +static SHARPYUV_INLINE int SharpYuvOptionsInit( + const SharpYuvConversionMatrix* yuv_matrix, SharpYuvOptions* options) { + return SharpYuvOptionsInitInternal(yuv_matrix, options, SHARPYUV_VERSION); +} + +SHARPYUV_EXTERN int SharpYuvConvertWithOptions( + const void* r_ptr, const void* g_ptr, const void* b_ptr, int rgb_step, + int rgb_stride, int rgb_bit_depth, void* y_ptr, int y_stride, void* u_ptr, + int u_stride, void* v_ptr, int v_stride, int yuv_bit_depth, int width, + int height, const SharpYuvOptions* options); + +// TODO(b/194336375): Add YUV444 to YUV420 conversion. Maybe also add 422 +// support (it's rarely used in practice, especially for images). + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_SHARPYUV_SHARPYUV_H_ diff --git a/third-party/webp/libwebp/sharpyuv/sharpyuv_cpu.c b/third-party/webp/libwebp/sharpyuv/sharpyuv_cpu.c new file mode 100644 index 0000000000..29425a0c49 --- /dev/null +++ b/third-party/webp/libwebp/sharpyuv/sharpyuv_cpu.c @@ -0,0 +1,14 @@ +// Copyright 2022 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +#include "sharpyuv/sharpyuv_cpu.h" + +// Include src/dsp/cpu.c to create SharpYuvGetCPUInfo from VP8GetCPUInfo. The +// function pointer is renamed in sharpyuv_cpu.h. +#include "src/dsp/cpu.c" diff --git a/third-party/webp/libwebp/sharpyuv/sharpyuv_cpu.h b/third-party/webp/libwebp/sharpyuv/sharpyuv_cpu.h new file mode 100644 index 0000000000..176ca3eb16 --- /dev/null +++ b/third-party/webp/libwebp/sharpyuv/sharpyuv_cpu.h @@ -0,0 +1,22 @@ +// Copyright 2022 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +#ifndef WEBP_SHARPYUV_SHARPYUV_CPU_H_ +#define WEBP_SHARPYUV_SHARPYUV_CPU_H_ + +#include "sharpyuv/sharpyuv.h" + +// Avoid exporting SharpYuvGetCPUInfo in shared object / DLL builds. +// SharpYuvInit() replaces the use of the function pointer. +#undef WEBP_EXTERN +#define WEBP_EXTERN extern +#define VP8GetCPUInfo SharpYuvGetCPUInfo +#include "src/dsp/cpu.h" + +#endif // WEBP_SHARPYUV_SHARPYUV_CPU_H_ diff --git a/third-party/webp/libwebp/sharpyuv/sharpyuv_csp.c b/third-party/webp/libwebp/sharpyuv/sharpyuv_csp.c new file mode 100644 index 0000000000..0ad22be945 --- /dev/null +++ b/third-party/webp/libwebp/sharpyuv/sharpyuv_csp.c @@ -0,0 +1,110 @@ +// Copyright 2022 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Colorspace utilities. + +#include "sharpyuv/sharpyuv_csp.h" + +#include +#include +#include + +static int ToFixed16(float f) { return (int)floor(f * (1 << 16) + 0.5f); } + +void SharpYuvComputeConversionMatrix(const SharpYuvColorSpace* yuv_color_space, + SharpYuvConversionMatrix* matrix) { + const float kr = yuv_color_space->kr; + const float kb = yuv_color_space->kb; + const float kg = 1.0f - kr - kb; + const float cr = 0.5f / (1.0f - kb); + const float cb = 0.5f / (1.0f - kr); + + const int shift = yuv_color_space->bit_depth - 8; + + const float denom = (float)((1 << yuv_color_space->bit_depth) - 1); + float scale_y = 1.0f; + float add_y = 0.0f; + float scale_u = cr; + float scale_v = cb; + float add_uv = (float)(128 << shift); + assert(yuv_color_space->bit_depth >= 8); + + if (yuv_color_space->range == kSharpYuvRangeLimited) { + scale_y *= (219 << shift) / denom; + scale_u *= (224 << shift) / denom; + scale_v *= (224 << shift) / denom; + add_y = (float)(16 << shift); + } + + matrix->rgb_to_y[0] = ToFixed16(kr * scale_y); + matrix->rgb_to_y[1] = ToFixed16(kg * scale_y); + matrix->rgb_to_y[2] = ToFixed16(kb * scale_y); + matrix->rgb_to_y[3] = ToFixed16(add_y); + + matrix->rgb_to_u[0] = ToFixed16(-kr * scale_u); + matrix->rgb_to_u[1] = ToFixed16(-kg * scale_u); + matrix->rgb_to_u[2] = ToFixed16((1 - kb) * scale_u); + matrix->rgb_to_u[3] = ToFixed16(add_uv); + + matrix->rgb_to_v[0] = ToFixed16((1 - kr) * scale_v); + matrix->rgb_to_v[1] = ToFixed16(-kg * scale_v); + matrix->rgb_to_v[2] = ToFixed16(-kb * scale_v); + matrix->rgb_to_v[3] = ToFixed16(add_uv); +} + +// Matrices are in YUV_FIX fixed point precision. +// WebP's matrix, similar but not identical to kRec601LimitedMatrix. +static const SharpYuvConversionMatrix kWebpMatrix = { + {16839, 33059, 6420, 16 << 16}, + {-9719, -19081, 28800, 128 << 16}, + {28800, -24116, -4684, 128 << 16}, +}; +// Kr=0.2990f Kb=0.1140f bits=8 range=kSharpYuvRangeLimited +static const SharpYuvConversionMatrix kRec601LimitedMatrix = { + {16829, 33039, 6416, 16 << 16}, + {-9714, -19071, 28784, 128 << 16}, + {28784, -24103, -4681, 128 << 16}, +}; +// Kr=0.2990f Kb=0.1140f bits=8 range=kSharpYuvRangeFull +static const SharpYuvConversionMatrix kRec601FullMatrix = { + {19595, 38470, 7471, 0}, + {-11058, -21710, 32768, 128 << 16}, + {32768, -27439, -5329, 128 << 16}, +}; +// Kr=0.2126f Kb=0.0722f bits=8 range=kSharpYuvRangeLimited +static const SharpYuvConversionMatrix kRec709LimitedMatrix = { + {11966, 40254, 4064, 16 << 16}, + {-6596, -22189, 28784, 128 << 16}, + {28784, -26145, -2639, 128 << 16}, +}; +// Kr=0.2126f Kb=0.0722f bits=8 range=kSharpYuvRangeFull +static const SharpYuvConversionMatrix kRec709FullMatrix = { + {13933, 46871, 4732, 0}, + {-7509, -25259, 32768, 128 << 16}, + {32768, -29763, -3005, 128 << 16}, +}; + +const SharpYuvConversionMatrix* SharpYuvGetConversionMatrix( + SharpYuvMatrixType matrix_type) { + switch (matrix_type) { + case kSharpYuvMatrixWebp: + return &kWebpMatrix; + case kSharpYuvMatrixRec601Limited: + return &kRec601LimitedMatrix; + case kSharpYuvMatrixRec601Full: + return &kRec601FullMatrix; + case kSharpYuvMatrixRec709Limited: + return &kRec709LimitedMatrix; + case kSharpYuvMatrixRec709Full: + return &kRec709FullMatrix; + case kSharpYuvMatrixNum: + return NULL; + } + return NULL; +} diff --git a/third-party/webp/libwebp/sharpyuv/sharpyuv_csp.h b/third-party/webp/libwebp/sharpyuv/sharpyuv_csp.h new file mode 100644 index 0000000000..3214e3ac60 --- /dev/null +++ b/third-party/webp/libwebp/sharpyuv/sharpyuv_csp.h @@ -0,0 +1,60 @@ +// Copyright 2022 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Colorspace utilities. + +#ifndef WEBP_SHARPYUV_SHARPYUV_CSP_H_ +#define WEBP_SHARPYUV_SHARPYUV_CSP_H_ + +#include "sharpyuv/sharpyuv.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Range of YUV values. +typedef enum { + kSharpYuvRangeFull, // YUV values between [0;255] (for 8 bit) + kSharpYuvRangeLimited // Y in [16;235], YUV in [16;240] (for 8 bit) +} SharpYuvRange; + +// Constants that define a YUV color space. +typedef struct { + // Kr and Kb are defined such that: + // Y = Kr * r + Kg * g + Kb * b where Kg = 1 - Kr - Kb. + float kr; + float kb; + int bit_depth; // 8, 10 or 12 + SharpYuvRange range; +} SharpYuvColorSpace; + +// Fills in 'matrix' for the given YUVColorSpace. +SHARPYUV_EXTERN void SharpYuvComputeConversionMatrix( + const SharpYuvColorSpace* yuv_color_space, + SharpYuvConversionMatrix* matrix); + +// Enums for precomputed conversion matrices. +typedef enum { + kSharpYuvMatrixWebp = 0, + kSharpYuvMatrixRec601Limited, + kSharpYuvMatrixRec601Full, + kSharpYuvMatrixRec709Limited, + kSharpYuvMatrixRec709Full, + kSharpYuvMatrixNum +} SharpYuvMatrixType; + +// Returns a pointer to a matrix for one of the predefined colorspaces. +SHARPYUV_EXTERN const SharpYuvConversionMatrix* SharpYuvGetConversionMatrix( + SharpYuvMatrixType matrix_type); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_SHARPYUV_SHARPYUV_CSP_H_ diff --git a/third-party/webp/libwebp/sharpyuv/sharpyuv_dsp.c b/third-party/webp/libwebp/sharpyuv/sharpyuv_dsp.c new file mode 100644 index 0000000000..0da3efc0b8 --- /dev/null +++ b/third-party/webp/libwebp/sharpyuv/sharpyuv_dsp.c @@ -0,0 +1,104 @@ +// Copyright 2022 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Speed-critical functions for Sharp YUV. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "sharpyuv/sharpyuv_dsp.h" + +#include +#include + +#include "sharpyuv/sharpyuv_cpu.h" + +//----------------------------------------------------------------------------- + +#if !WEBP_NEON_OMIT_C_CODE +static uint16_t clip(int v, int max) { + return (v < 0) ? 0 : (v > max) ? max : (uint16_t)v; +} + +static uint64_t SharpYuvUpdateY_C(const uint16_t* ref, const uint16_t* src, + uint16_t* dst, int len, int bit_depth) { + uint64_t diff = 0; + int i; + const int max_y = (1 << bit_depth) - 1; + for (i = 0; i < len; ++i) { + const int diff_y = ref[i] - src[i]; + const int new_y = (int)dst[i] + diff_y; + dst[i] = clip(new_y, max_y); + diff += (uint64_t)abs(diff_y); + } + return diff; +} + +static void SharpYuvUpdateRGB_C(const int16_t* ref, const int16_t* src, + int16_t* dst, int len) { + int i; + for (i = 0; i < len; ++i) { + const int diff_uv = ref[i] - src[i]; + dst[i] += diff_uv; + } +} + +static void SharpYuvFilterRow_C(const int16_t* A, const int16_t* B, int len, + const uint16_t* best_y, uint16_t* out, + int bit_depth) { + int i; + const int max_y = (1 << bit_depth) - 1; + for (i = 0; i < len; ++i, ++A, ++B) { + const int v0 = (A[0] * 9 + A[1] * 3 + B[0] * 3 + B[1] + 8) >> 4; + const int v1 = (A[1] * 9 + A[0] * 3 + B[1] * 3 + B[0] + 8) >> 4; + out[2 * i + 0] = clip(best_y[2 * i + 0] + v0, max_y); + out[2 * i + 1] = clip(best_y[2 * i + 1] + v1, max_y); + } +} +#endif // !WEBP_NEON_OMIT_C_CODE + +//----------------------------------------------------------------------------- + +uint64_t (*SharpYuvUpdateY)(const uint16_t* src, const uint16_t* ref, + uint16_t* dst, int len, int bit_depth); +void (*SharpYuvUpdateRGB)(const int16_t* src, const int16_t* ref, int16_t* dst, + int len); +void (*SharpYuvFilterRow)(const int16_t* A, const int16_t* B, int len, + const uint16_t* best_y, uint16_t* out, + int bit_depth); + +extern VP8CPUInfo SharpYuvGetCPUInfo; +extern void InitSharpYuvSSE2(void); +extern void InitSharpYuvNEON(void); + +void SharpYuvInitDsp(void) { +#if !WEBP_NEON_OMIT_C_CODE + SharpYuvUpdateY = SharpYuvUpdateY_C; + SharpYuvUpdateRGB = SharpYuvUpdateRGB_C; + SharpYuvFilterRow = SharpYuvFilterRow_C; +#endif + + if (SharpYuvGetCPUInfo != NULL) { +#if defined(WEBP_HAVE_SSE2) + if (SharpYuvGetCPUInfo(kSSE2)) { + InitSharpYuvSSE2(); + } +#endif // WEBP_HAVE_SSE2 + } + +#if defined(WEBP_HAVE_NEON) + if (WEBP_NEON_OMIT_C_CODE || + (SharpYuvGetCPUInfo != NULL && SharpYuvGetCPUInfo(kNEON))) { + InitSharpYuvNEON(); + } +#endif // WEBP_HAVE_NEON + + assert(SharpYuvUpdateY != NULL); + assert(SharpYuvUpdateRGB != NULL); + assert(SharpYuvFilterRow != NULL); +} diff --git a/third-party/webp/libwebp/sharpyuv/sharpyuv_dsp.h b/third-party/webp/libwebp/sharpyuv/sharpyuv_dsp.h new file mode 100644 index 0000000000..805fbadbf6 --- /dev/null +++ b/third-party/webp/libwebp/sharpyuv/sharpyuv_dsp.h @@ -0,0 +1,28 @@ +// Copyright 2022 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Speed-critical functions for Sharp YUV. + +#ifndef WEBP_SHARPYUV_SHARPYUV_DSP_H_ +#define WEBP_SHARPYUV_SHARPYUV_DSP_H_ + +#include "sharpyuv/sharpyuv_cpu.h" +#include "src/webp/types.h" + +extern uint64_t (*SharpYuvUpdateY)(const uint16_t* src, const uint16_t* ref, + uint16_t* dst, int len, int bit_depth); +extern void (*SharpYuvUpdateRGB)(const int16_t* src, const int16_t* ref, + int16_t* dst, int len); +extern void (*SharpYuvFilterRow)(const int16_t* A, const int16_t* B, int len, + const uint16_t* best_y, uint16_t* out, + int bit_depth); + +void SharpYuvInitDsp(void); + +#endif // WEBP_SHARPYUV_SHARPYUV_DSP_H_ diff --git a/third-party/webp/libwebp/sharpyuv/sharpyuv_gamma.c b/third-party/webp/libwebp/sharpyuv/sharpyuv_gamma.c new file mode 100644 index 0000000000..fecadc6480 --- /dev/null +++ b/third-party/webp/libwebp/sharpyuv/sharpyuv_gamma.c @@ -0,0 +1,419 @@ +// Copyright 2022 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Gamma correction utilities. + +#include "sharpyuv/sharpyuv_gamma.h" + +#include +#include +#include + +#include "src/webp/types.h" + +// Gamma correction compensates loss of resolution during chroma subsampling. +// Size of pre-computed table for converting from gamma to linear. +#define GAMMA_TO_LINEAR_TAB_BITS 10 +#define GAMMA_TO_LINEAR_TAB_SIZE (1 << GAMMA_TO_LINEAR_TAB_BITS) +static uint32_t kGammaToLinearTabS[GAMMA_TO_LINEAR_TAB_SIZE + 2]; +#define LINEAR_TO_GAMMA_TAB_BITS 9 +#define LINEAR_TO_GAMMA_TAB_SIZE (1 << LINEAR_TO_GAMMA_TAB_BITS) +static uint32_t kLinearToGammaTabS[LINEAR_TO_GAMMA_TAB_SIZE + 2]; + +static const double kGammaF = 1. / 0.45; +#define GAMMA_TO_LINEAR_BITS 16 + +static volatile int kGammaTablesSOk = 0; +void SharpYuvInitGammaTables(void) { + assert(GAMMA_TO_LINEAR_BITS <= 16); + if (!kGammaTablesSOk) { + int v; + const double a = 0.09929682680944; + const double thresh = 0.018053968510807; + const double final_scale = 1 << GAMMA_TO_LINEAR_BITS; + // Precompute gamma to linear table. + { + const double norm = 1. / GAMMA_TO_LINEAR_TAB_SIZE; + const double a_rec = 1. / (1. + a); + for (v = 0; v <= GAMMA_TO_LINEAR_TAB_SIZE; ++v) { + const double g = norm * v; + double value; + if (g <= thresh * 4.5) { + value = g / 4.5; + } else { + value = pow(a_rec * (g + a), kGammaF); + } + kGammaToLinearTabS[v] = (uint32_t)(value * final_scale + .5); + } + // to prevent small rounding errors to cause read-overflow: + kGammaToLinearTabS[GAMMA_TO_LINEAR_TAB_SIZE + 1] = + kGammaToLinearTabS[GAMMA_TO_LINEAR_TAB_SIZE]; + } + // Precompute linear to gamma table. + { + const double scale = 1. / LINEAR_TO_GAMMA_TAB_SIZE; + for (v = 0; v <= LINEAR_TO_GAMMA_TAB_SIZE; ++v) { + const double g = scale * v; + double value; + if (g <= thresh) { + value = 4.5 * g; + } else { + value = (1. + a) * pow(g, 1. / kGammaF) - a; + } + kLinearToGammaTabS[v] = + (uint32_t)(final_scale * value + 0.5); + } + // to prevent small rounding errors to cause read-overflow: + kLinearToGammaTabS[LINEAR_TO_GAMMA_TAB_SIZE + 1] = + kLinearToGammaTabS[LINEAR_TO_GAMMA_TAB_SIZE]; + } + kGammaTablesSOk = 1; + } +} + +static WEBP_INLINE int Shift(int v, int shift) { + return (shift >= 0) ? (v << shift) : (v >> -shift); +} + +static WEBP_INLINE uint32_t FixedPointInterpolation(int v, uint32_t* tab, + int tab_pos_shift_right, + int tab_value_shift) { + const uint32_t tab_pos = Shift(v, -tab_pos_shift_right); + // fractional part, in 'tab_pos_shift' fixed-point precision + const uint32_t x = v - (tab_pos << tab_pos_shift_right); // fractional part + // v0 / v1 are in kGammaToLinearBits fixed-point precision (range [0..1]) + const uint32_t v0 = Shift(tab[tab_pos + 0], tab_value_shift); + const uint32_t v1 = Shift(tab[tab_pos + 1], tab_value_shift); + // Final interpolation. + const uint32_t v2 = (v1 - v0) * x; // note: v1 >= v0. + const int half = + (tab_pos_shift_right > 0) ? 1 << (tab_pos_shift_right - 1) : 0; + const uint32_t result = v0 + ((v2 + half) >> tab_pos_shift_right); + return result; +} + +static uint32_t ToLinearSrgb(uint16_t v, int bit_depth) { + const int shift = GAMMA_TO_LINEAR_TAB_BITS - bit_depth; + if (shift > 0) { + return kGammaToLinearTabS[v << shift]; + } + return FixedPointInterpolation(v, kGammaToLinearTabS, -shift, 0); +} + +static uint16_t FromLinearSrgb(uint32_t value, int bit_depth) { + return FixedPointInterpolation( + value, kLinearToGammaTabS, + (GAMMA_TO_LINEAR_BITS - LINEAR_TO_GAMMA_TAB_BITS), + bit_depth - GAMMA_TO_LINEAR_BITS); +} + +//////////////////////////////////////////////////////////////////////////////// + +#define CLAMP(x, low, high) \ + (((x) < (low)) ? (low) : (((high) < (x)) ? (high) : (x))) +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + +static WEBP_INLINE float Roundf(float x) { + if (x < 0) + return (float)ceil((double)(x - 0.5f)); + else + return (float)floor((double)(x + 0.5f)); +} + +static WEBP_INLINE float Powf(float base, float exp) { + return (float)pow((double)base, (double)exp); +} + +static WEBP_INLINE float Log10f(float x) { return (float)log10((double)x); } + +static float ToLinear709(float gamma) { + if (gamma < 0.f) { + return 0.f; + } else if (gamma < 4.5f * 0.018053968510807f) { + return gamma / 4.5f; + } else if (gamma < 1.f) { + return Powf((gamma + 0.09929682680944f) / 1.09929682680944f, 1.f / 0.45f); + } + return 1.f; +} + +static float FromLinear709(float linear) { + if (linear < 0.f) { + return 0.f; + } else if (linear < 0.018053968510807f) { + return linear * 4.5f; + } else if (linear < 1.f) { + return 1.09929682680944f * Powf(linear, 0.45f) - 0.09929682680944f; + } + return 1.f; +} + +static float ToLinear470M(float gamma) { + return Powf(CLAMP(gamma, 0.f, 1.f), 1.f / 2.2f); +} + +static float FromLinear470M(float linear) { + return Powf(CLAMP(linear, 0.f, 1.f), 2.2f); +} + +static float ToLinear470Bg(float gamma) { + return Powf(CLAMP(gamma, 0.f, 1.f), 1.f / 2.8f); +} + +static float FromLinear470Bg(float linear) { + return Powf(CLAMP(linear, 0.f, 1.f), 2.8f); +} + +static float ToLinearSmpte240(float gamma) { + if (gamma < 0.f) { + return 0.f; + } else if (gamma < 4.f * 0.022821585529445f) { + return gamma / 4.f; + } else if (gamma < 1.f) { + return Powf((gamma + 0.111572195921731f) / 1.111572195921731f, 1.f / 0.45f); + } + return 1.f; +} + +static float FromLinearSmpte240(float linear) { + if (linear < 0.f) { + return 0.f; + } else if (linear < 0.022821585529445f) { + return linear * 4.f; + } else if (linear < 1.f) { + return 1.111572195921731f * Powf(linear, 0.45f) - 0.111572195921731f; + } + return 1.f; +} + +static float ToLinearLog100(float gamma) { + return (gamma < 0.01f) ? 0.0f : 1.0f + Log10f(MIN(gamma, 1.f)) / 2.0f; +} + +static float FromLinearLog100(float linear) { + // The function is non-bijective so choose the middle of [0, 0.01]. + const float mid_interval = 0.01f / 2.f; + return (linear <= 0.0f) ? mid_interval + : Powf(10.0f, 2.f * (MIN(linear, 1.f) - 1.0f)); +} + +static float ToLinearLog100Sqrt10(float gamma) { + return (gamma < 0.00316227766f) ? 0.0f + : 1.0f + Log10f(MIN(gamma, 1.f)) / 2.5f; +} + +static float FromLinearLog100Sqrt10(float linear) { + // The function is non-bijective so choose the middle of [0, 0.00316227766f[. + const float mid_interval = 0.00316227766f / 2.f; + return (linear < 0.0f) ? mid_interval + : Powf(10.0f, 2.5f * (MIN(linear, 1.f) - 1.0f)); +} + +static float ToLinearIec61966(float gamma) { + if (gamma <= -4.5f * 0.018053968510807f) { + return Powf((-gamma + 0.09929682680944f) / -1.09929682680944f, 1.f / 0.45f); + } else if (gamma < 4.5f * 0.018053968510807f) { + return gamma / 4.5f; + } + return Powf((gamma + 0.09929682680944f) / 1.09929682680944f, 1.f / 0.45f); +} + +static float FromLinearIec61966(float linear) { + if (linear <= -0.018053968510807f) { + return -1.09929682680944f * Powf(-linear, 0.45f) + 0.09929682680944f; + } else if (linear < 0.018053968510807f) { + return linear * 4.5f; + } + return 1.09929682680944f * Powf(linear, 0.45f) - 0.09929682680944f; +} + +static float ToLinearBt1361(float gamma) { + if (gamma < -0.25f) { + return -0.25f; + } else if (gamma < 0.f) { + return Powf((gamma - 0.02482420670236f) / -0.27482420670236f, 1.f / 0.45f) / + -4.f; + } else if (gamma < 4.5f * 0.018053968510807f) { + return gamma / 4.5f; + } else if (gamma < 1.f) { + return Powf((gamma + 0.09929682680944f) / 1.09929682680944f, 1.f / 0.45f); + } + return 1.f; +} + +static float FromLinearBt1361(float linear) { + if (linear < -0.25f) { + return -0.25f; + } else if (linear < 0.f) { + return -0.27482420670236f * Powf(-4.f * linear, 0.45f) + 0.02482420670236f; + } else if (linear < 0.018053968510807f) { + return linear * 4.5f; + } else if (linear < 1.f) { + return 1.09929682680944f * Powf(linear, 0.45f) - 0.09929682680944f; + } + return 1.f; +} + +static float ToLinearPq(float gamma) { + if (gamma > 0.f) { + const float pow_gamma = Powf(gamma, 32.f / 2523.f); + const float num = MAX(pow_gamma - 107.f / 128.f, 0.0f); + const float den = MAX(2413.f / 128.f - 2392.f / 128.f * pow_gamma, FLT_MIN); + return Powf(num / den, 4096.f / 653.f); + } + return 0.f; +} + +static float FromLinearPq(float linear) { + if (linear > 0.f) { + const float pow_linear = Powf(linear, 653.f / 4096.f); + const float num = 107.f / 128.f + 2413.f / 128.f * pow_linear; + const float den = 1.0f + 2392.f / 128.f * pow_linear; + return Powf(num / den, 2523.f / 32.f); + } + return 0.f; +} + +static float ToLinearSmpte428(float gamma) { + return Powf(0.91655527974030934f * MAX(gamma, 0.f), 1.f / 2.6f); +} + +static float FromLinearSmpte428(float linear) { + return Powf(MAX(linear, 0.f), 2.6f) / 0.91655527974030934f; +} + +// Conversion in BT.2100 requires RGB info. Simplify to gamma correction here. +static float ToLinearHlg(float gamma) { + if (gamma < 0.f) { + return 0.f; + } else if (gamma <= 0.5f) { + return Powf((gamma * gamma) * (1.f / 3.f), 1.2f); + } + return Powf((expf((gamma - 0.55991073f) / 0.17883277f) + 0.28466892f) / 12.0f, + 1.2f); +} + +static float FromLinearHlg(float linear) { + linear = Powf(linear, 1.f / 1.2f); + if (linear < 0.f) { + return 0.f; + } else if (linear <= (1.f / 12.f)) { + return sqrtf(3.f * linear); + } + return 0.17883277f * logf(12.f * linear - 0.28466892f) + 0.55991073f; +} + +uint32_t SharpYuvGammaToLinear(uint16_t v, int bit_depth, + SharpYuvTransferFunctionType transfer_type) { + float v_float, linear; + if (transfer_type == kSharpYuvTransferFunctionSrgb) { + return ToLinearSrgb(v, bit_depth); + } + v_float = (float)v / ((1 << bit_depth) - 1); + switch (transfer_type) { + case kSharpYuvTransferFunctionBt709: + case kSharpYuvTransferFunctionBt601: + case kSharpYuvTransferFunctionBt2020_10Bit: + case kSharpYuvTransferFunctionBt2020_12Bit: + linear = ToLinear709(v_float); + break; + case kSharpYuvTransferFunctionBt470M: + linear = ToLinear470M(v_float); + break; + case kSharpYuvTransferFunctionBt470Bg: + linear = ToLinear470Bg(v_float); + break; + case kSharpYuvTransferFunctionSmpte240: + linear = ToLinearSmpte240(v_float); + break; + case kSharpYuvTransferFunctionLinear: + return v; + case kSharpYuvTransferFunctionLog100: + linear = ToLinearLog100(v_float); + break; + case kSharpYuvTransferFunctionLog100_Sqrt10: + linear = ToLinearLog100Sqrt10(v_float); + break; + case kSharpYuvTransferFunctionIec61966: + linear = ToLinearIec61966(v_float); + break; + case kSharpYuvTransferFunctionBt1361: + linear = ToLinearBt1361(v_float); + break; + case kSharpYuvTransferFunctionSmpte2084: + linear = ToLinearPq(v_float); + break; + case kSharpYuvTransferFunctionSmpte428: + linear = ToLinearSmpte428(v_float); + break; + case kSharpYuvTransferFunctionHlg: + linear = ToLinearHlg(v_float); + break; + default: + assert(0); + linear = 0; + break; + } + return (uint32_t)Roundf(linear * ((1 << 16) - 1)); +} + +uint16_t SharpYuvLinearToGamma(uint32_t v, int bit_depth, + SharpYuvTransferFunctionType transfer_type) { + float v_float, linear; + if (transfer_type == kSharpYuvTransferFunctionSrgb) { + return FromLinearSrgb(v, bit_depth); + } + v_float = (float)v / ((1 << 16) - 1); + switch (transfer_type) { + case kSharpYuvTransferFunctionBt709: + case kSharpYuvTransferFunctionBt601: + case kSharpYuvTransferFunctionBt2020_10Bit: + case kSharpYuvTransferFunctionBt2020_12Bit: + linear = FromLinear709(v_float); + break; + case kSharpYuvTransferFunctionBt470M: + linear = FromLinear470M(v_float); + break; + case kSharpYuvTransferFunctionBt470Bg: + linear = FromLinear470Bg(v_float); + break; + case kSharpYuvTransferFunctionSmpte240: + linear = FromLinearSmpte240(v_float); + break; + case kSharpYuvTransferFunctionLinear: + return v; + case kSharpYuvTransferFunctionLog100: + linear = FromLinearLog100(v_float); + break; + case kSharpYuvTransferFunctionLog100_Sqrt10: + linear = FromLinearLog100Sqrt10(v_float); + break; + case kSharpYuvTransferFunctionIec61966: + linear = FromLinearIec61966(v_float); + break; + case kSharpYuvTransferFunctionBt1361: + linear = FromLinearBt1361(v_float); + break; + case kSharpYuvTransferFunctionSmpte2084: + linear = FromLinearPq(v_float); + break; + case kSharpYuvTransferFunctionSmpte428: + linear = FromLinearSmpte428(v_float); + break; + case kSharpYuvTransferFunctionHlg: + linear = FromLinearHlg(v_float); + break; + default: + assert(0); + linear = 0; + break; + } + return (uint16_t)Roundf(linear * ((1 << bit_depth) - 1)); +} diff --git a/third-party/webp/libwebp/sharpyuv/sharpyuv_gamma.h b/third-party/webp/libwebp/sharpyuv/sharpyuv_gamma.h new file mode 100644 index 0000000000..b8ba7e9870 --- /dev/null +++ b/third-party/webp/libwebp/sharpyuv/sharpyuv_gamma.h @@ -0,0 +1,38 @@ +// Copyright 2022 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Gamma correction utilities. + +#ifndef WEBP_SHARPYUV_SHARPYUV_GAMMA_H_ +#define WEBP_SHARPYUV_SHARPYUV_GAMMA_H_ + +#include "sharpyuv/sharpyuv.h" +#include "src/webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Initializes precomputed tables. Must be called once before calling +// SharpYuvGammaToLinear or SharpYuvLinearToGamma. +void SharpYuvInitGammaTables(void); + +// Converts a 'bit_depth'-bit gamma color value to a 16-bit linear value. +uint32_t SharpYuvGammaToLinear(uint16_t v, int bit_depth, + SharpYuvTransferFunctionType transfer_type); + +// Converts a 16-bit linear color value to a 'bit_depth'-bit gamma value. +uint16_t SharpYuvLinearToGamma(uint32_t value, int bit_depth, + SharpYuvTransferFunctionType transfer_type); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_SHARPYUV_SHARPYUV_GAMMA_H_ diff --git a/third-party/webp/libwebp/sharpyuv/sharpyuv_neon.c b/third-party/webp/libwebp/sharpyuv/sharpyuv_neon.c new file mode 100644 index 0000000000..5840914865 --- /dev/null +++ b/third-party/webp/libwebp/sharpyuv/sharpyuv_neon.c @@ -0,0 +1,181 @@ +// Copyright 2022 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Speed-critical functions for Sharp YUV. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "sharpyuv/sharpyuv_dsp.h" + +#if defined(WEBP_USE_NEON) +#include +#include +#include + +static uint16_t clip_NEON(int v, int max) { + return (v < 0) ? 0 : (v > max) ? max : (uint16_t)v; +} + +static uint64_t SharpYuvUpdateY_NEON(const uint16_t* ref, const uint16_t* src, + uint16_t* dst, int len, int bit_depth) { + const int max_y = (1 << bit_depth) - 1; + int i; + const int16x8_t zero = vdupq_n_s16(0); + const int16x8_t max = vdupq_n_s16(max_y); + uint64x2_t sum = vdupq_n_u64(0); + uint64_t diff; + + for (i = 0; i + 8 <= len; i += 8) { + const int16x8_t A = vreinterpretq_s16_u16(vld1q_u16(ref + i)); + const int16x8_t B = vreinterpretq_s16_u16(vld1q_u16(src + i)); + const int16x8_t C = vreinterpretq_s16_u16(vld1q_u16(dst + i)); + const int16x8_t D = vsubq_s16(A, B); // diff_y + const int16x8_t F = vaddq_s16(C, D); // new_y + const uint16x8_t H = + vreinterpretq_u16_s16(vmaxq_s16(vminq_s16(F, max), zero)); + const int16x8_t I = vabsq_s16(D); // abs(diff_y) + vst1q_u16(dst + i, H); + sum = vpadalq_u32(sum, vpaddlq_u16(vreinterpretq_u16_s16(I))); + } + diff = vgetq_lane_u64(sum, 0) + vgetq_lane_u64(sum, 1); + for (; i < len; ++i) { + const int diff_y = ref[i] - src[i]; + const int new_y = (int)(dst[i]) + diff_y; + dst[i] = clip_NEON(new_y, max_y); + diff += (uint64_t)(abs(diff_y)); + } + return diff; +} + +static void SharpYuvUpdateRGB_NEON(const int16_t* ref, const int16_t* src, + int16_t* dst, int len) { + int i; + for (i = 0; i + 8 <= len; i += 8) { + const int16x8_t A = vld1q_s16(ref + i); + const int16x8_t B = vld1q_s16(src + i); + const int16x8_t C = vld1q_s16(dst + i); + const int16x8_t D = vsubq_s16(A, B); // diff_uv + const int16x8_t E = vaddq_s16(C, D); // new_uv + vst1q_s16(dst + i, E); + } + for (; i < len; ++i) { + const int diff_uv = ref[i] - src[i]; + dst[i] += diff_uv; + } +} + +static void SharpYuvFilterRow16_NEON(const int16_t* A, const int16_t* B, + int len, const uint16_t* best_y, + uint16_t* out, int bit_depth) { + const int max_y = (1 << bit_depth) - 1; + int i; + const int16x8_t max = vdupq_n_s16(max_y); + const int16x8_t zero = vdupq_n_s16(0); + for (i = 0; i + 8 <= len; i += 8) { + const int16x8_t a0 = vld1q_s16(A + i + 0); + const int16x8_t a1 = vld1q_s16(A + i + 1); + const int16x8_t b0 = vld1q_s16(B + i + 0); + const int16x8_t b1 = vld1q_s16(B + i + 1); + const int16x8_t a0b1 = vaddq_s16(a0, b1); + const int16x8_t a1b0 = vaddq_s16(a1, b0); + const int16x8_t a0a1b0b1 = vaddq_s16(a0b1, a1b0); // A0+A1+B0+B1 + const int16x8_t a0b1_2 = vaddq_s16(a0b1, a0b1); // 2*(A0+B1) + const int16x8_t a1b0_2 = vaddq_s16(a1b0, a1b0); // 2*(A1+B0) + const int16x8_t c0 = vshrq_n_s16(vaddq_s16(a0b1_2, a0a1b0b1), 3); + const int16x8_t c1 = vshrq_n_s16(vaddq_s16(a1b0_2, a0a1b0b1), 3); + const int16x8_t e0 = vrhaddq_s16(c1, a0); + const int16x8_t e1 = vrhaddq_s16(c0, a1); + const int16x8x2_t f = vzipq_s16(e0, e1); + const int16x8_t g0 = vreinterpretq_s16_u16(vld1q_u16(best_y + 2 * i + 0)); + const int16x8_t g1 = vreinterpretq_s16_u16(vld1q_u16(best_y + 2 * i + 8)); + const int16x8_t h0 = vaddq_s16(g0, f.val[0]); + const int16x8_t h1 = vaddq_s16(g1, f.val[1]); + const int16x8_t i0 = vmaxq_s16(vminq_s16(h0, max), zero); + const int16x8_t i1 = vmaxq_s16(vminq_s16(h1, max), zero); + vst1q_u16(out + 2 * i + 0, vreinterpretq_u16_s16(i0)); + vst1q_u16(out + 2 * i + 8, vreinterpretq_u16_s16(i1)); + } + for (; i < len; ++i) { + const int a0b1 = A[i + 0] + B[i + 1]; + const int a1b0 = A[i + 1] + B[i + 0]; + const int a0a1b0b1 = a0b1 + a1b0 + 8; + const int v0 = (8 * A[i + 0] + 2 * a1b0 + a0a1b0b1) >> 4; + const int v1 = (8 * A[i + 1] + 2 * a0b1 + a0a1b0b1) >> 4; + out[2 * i + 0] = clip_NEON(best_y[2 * i + 0] + v0, max_y); + out[2 * i + 1] = clip_NEON(best_y[2 * i + 1] + v1, max_y); + } +} + +static void SharpYuvFilterRow32_NEON(const int16_t* A, const int16_t* B, + int len, const uint16_t* best_y, + uint16_t* out, int bit_depth) { + const int max_y = (1 << bit_depth) - 1; + int i; + const uint16x8_t max = vdupq_n_u16(max_y); + for (i = 0; i + 4 <= len; i += 4) { + const int16x4_t a0 = vld1_s16(A + i + 0); + const int16x4_t a1 = vld1_s16(A + i + 1); + const int16x4_t b0 = vld1_s16(B + i + 0); + const int16x4_t b1 = vld1_s16(B + i + 1); + const int32x4_t a0b1 = vaddl_s16(a0, b1); + const int32x4_t a1b0 = vaddl_s16(a1, b0); + const int32x4_t a0a1b0b1 = vaddq_s32(a0b1, a1b0); // A0+A1+B0+B1 + const int32x4_t a0b1_2 = vaddq_s32(a0b1, a0b1); // 2*(A0+B1) + const int32x4_t a1b0_2 = vaddq_s32(a1b0, a1b0); // 2*(A1+B0) + const int32x4_t c0 = vshrq_n_s32(vaddq_s32(a0b1_2, a0a1b0b1), 3); + const int32x4_t c1 = vshrq_n_s32(vaddq_s32(a1b0_2, a0a1b0b1), 3); + const int32x4_t e0 = vrhaddq_s32(c1, vmovl_s16(a0)); + const int32x4_t e1 = vrhaddq_s32(c0, vmovl_s16(a1)); + const int32x4x2_t f = vzipq_s32(e0, e1); + + const int16x8_t g = vreinterpretq_s16_u16(vld1q_u16(best_y + 2 * i)); + const int32x4_t h0 = vaddw_s16(f.val[0], vget_low_s16(g)); + const int32x4_t h1 = vaddw_s16(f.val[1], vget_high_s16(g)); + const uint16x8_t i_16 = vcombine_u16(vqmovun_s32(h0), vqmovun_s32(h1)); + const uint16x8_t i_clamped = vminq_u16(i_16, max); + vst1q_u16(out + 2 * i + 0, i_clamped); + } + for (; i < len; ++i) { + const int a0b1 = A[i + 0] + B[i + 1]; + const int a1b0 = A[i + 1] + B[i + 0]; + const int a0a1b0b1 = a0b1 + a1b0 + 8; + const int v0 = (8 * A[i + 0] + 2 * a1b0 + a0a1b0b1) >> 4; + const int v1 = (8 * A[i + 1] + 2 * a0b1 + a0a1b0b1) >> 4; + out[2 * i + 0] = clip_NEON(best_y[2 * i + 0] + v0, max_y); + out[2 * i + 1] = clip_NEON(best_y[2 * i + 1] + v1, max_y); + } +} + +static void SharpYuvFilterRow_NEON(const int16_t* A, const int16_t* B, int len, + const uint16_t* best_y, uint16_t* out, + int bit_depth) { + if (bit_depth <= 10) { + SharpYuvFilterRow16_NEON(A, B, len, best_y, out, bit_depth); + } else { + SharpYuvFilterRow32_NEON(A, B, len, best_y, out, bit_depth); + } +} + +//------------------------------------------------------------------------------ + +extern void InitSharpYuvNEON(void); + +WEBP_TSAN_IGNORE_FUNCTION void InitSharpYuvNEON(void) { + SharpYuvUpdateY = SharpYuvUpdateY_NEON; + SharpYuvUpdateRGB = SharpYuvUpdateRGB_NEON; + SharpYuvFilterRow = SharpYuvFilterRow_NEON; +} + +#else // !WEBP_USE_NEON + +extern void InitSharpYuvNEON(void); + +void InitSharpYuvNEON(void) {} + +#endif // WEBP_USE_NEON diff --git a/third-party/webp/libwebp/sharpyuv/sharpyuv_sse2.c b/third-party/webp/libwebp/sharpyuv/sharpyuv_sse2.c new file mode 100644 index 0000000000..9744d1bb6c --- /dev/null +++ b/third-party/webp/libwebp/sharpyuv/sharpyuv_sse2.c @@ -0,0 +1,201 @@ +// Copyright 2022 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Speed-critical functions for Sharp YUV. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "sharpyuv/sharpyuv_dsp.h" + +#if defined(WEBP_USE_SSE2) +#include +#include + +static uint16_t clip_SSE2(int v, int max) { + return (v < 0) ? 0 : (v > max) ? max : (uint16_t)v; +} + +static uint64_t SharpYuvUpdateY_SSE2(const uint16_t* ref, const uint16_t* src, + uint16_t* dst, int len, int bit_depth) { + const int max_y = (1 << bit_depth) - 1; + uint64_t diff = 0; + uint32_t tmp[4]; + int i; + const __m128i zero = _mm_setzero_si128(); + const __m128i max = _mm_set1_epi16(max_y); + const __m128i one = _mm_set1_epi16(1); + __m128i sum = zero; + + for (i = 0; i + 8 <= len; i += 8) { + const __m128i A = _mm_loadu_si128((const __m128i*)(ref + i)); + const __m128i B = _mm_loadu_si128((const __m128i*)(src + i)); + const __m128i C = _mm_loadu_si128((const __m128i*)(dst + i)); + const __m128i D = _mm_sub_epi16(A, B); // diff_y + const __m128i E = _mm_cmpgt_epi16(zero, D); // sign (-1 or 0) + const __m128i F = _mm_add_epi16(C, D); // new_y + const __m128i G = _mm_or_si128(E, one); // -1 or 1 + const __m128i H = _mm_max_epi16(_mm_min_epi16(F, max), zero); + const __m128i I = _mm_madd_epi16(D, G); // sum(abs(...)) + _mm_storeu_si128((__m128i*)(dst + i), H); + sum = _mm_add_epi32(sum, I); + } + _mm_storeu_si128((__m128i*)tmp, sum); + diff = tmp[3] + tmp[2] + tmp[1] + tmp[0]; + for (; i < len; ++i) { + const int diff_y = ref[i] - src[i]; + const int new_y = (int)dst[i] + diff_y; + dst[i] = clip_SSE2(new_y, max_y); + diff += (uint64_t)abs(diff_y); + } + return diff; +} + +static void SharpYuvUpdateRGB_SSE2(const int16_t* ref, const int16_t* src, + int16_t* dst, int len) { + int i = 0; + for (i = 0; i + 8 <= len; i += 8) { + const __m128i A = _mm_loadu_si128((const __m128i*)(ref + i)); + const __m128i B = _mm_loadu_si128((const __m128i*)(src + i)); + const __m128i C = _mm_loadu_si128((const __m128i*)(dst + i)); + const __m128i D = _mm_sub_epi16(A, B); // diff_uv + const __m128i E = _mm_add_epi16(C, D); // new_uv + _mm_storeu_si128((__m128i*)(dst + i), E); + } + for (; i < len; ++i) { + const int diff_uv = ref[i] - src[i]; + dst[i] += diff_uv; + } +} + +static void SharpYuvFilterRow16_SSE2(const int16_t* A, const int16_t* B, + int len, const uint16_t* best_y, + uint16_t* out, int bit_depth) { + const int max_y = (1 << bit_depth) - 1; + int i; + const __m128i kCst8 = _mm_set1_epi16(8); + const __m128i max = _mm_set1_epi16(max_y); + const __m128i zero = _mm_setzero_si128(); + for (i = 0; i + 8 <= len; i += 8) { + const __m128i a0 = _mm_loadu_si128((const __m128i*)(A + i + 0)); + const __m128i a1 = _mm_loadu_si128((const __m128i*)(A + i + 1)); + const __m128i b0 = _mm_loadu_si128((const __m128i*)(B + i + 0)); + const __m128i b1 = _mm_loadu_si128((const __m128i*)(B + i + 1)); + const __m128i a0b1 = _mm_add_epi16(a0, b1); + const __m128i a1b0 = _mm_add_epi16(a1, b0); + const __m128i a0a1b0b1 = _mm_add_epi16(a0b1, a1b0); // A0+A1+B0+B1 + const __m128i a0a1b0b1_8 = _mm_add_epi16(a0a1b0b1, kCst8); + const __m128i a0b1_2 = _mm_add_epi16(a0b1, a0b1); // 2*(A0+B1) + const __m128i a1b0_2 = _mm_add_epi16(a1b0, a1b0); // 2*(A1+B0) + const __m128i c0 = _mm_srai_epi16(_mm_add_epi16(a0b1_2, a0a1b0b1_8), 3); + const __m128i c1 = _mm_srai_epi16(_mm_add_epi16(a1b0_2, a0a1b0b1_8), 3); + const __m128i d0 = _mm_add_epi16(c1, a0); + const __m128i d1 = _mm_add_epi16(c0, a1); + const __m128i e0 = _mm_srai_epi16(d0, 1); + const __m128i e1 = _mm_srai_epi16(d1, 1); + const __m128i f0 = _mm_unpacklo_epi16(e0, e1); + const __m128i f1 = _mm_unpackhi_epi16(e0, e1); + const __m128i g0 = _mm_loadu_si128((const __m128i*)(best_y + 2 * i + 0)); + const __m128i g1 = _mm_loadu_si128((const __m128i*)(best_y + 2 * i + 8)); + const __m128i h0 = _mm_add_epi16(g0, f0); + const __m128i h1 = _mm_add_epi16(g1, f1); + const __m128i i0 = _mm_max_epi16(_mm_min_epi16(h0, max), zero); + const __m128i i1 = _mm_max_epi16(_mm_min_epi16(h1, max), zero); + _mm_storeu_si128((__m128i*)(out + 2 * i + 0), i0); + _mm_storeu_si128((__m128i*)(out + 2 * i + 8), i1); + } + for (; i < len; ++i) { + // (9 * A0 + 3 * A1 + 3 * B0 + B1 + 8) >> 4 = + // = (8 * A0 + 2 * (A1 + B0) + (A0 + A1 + B0 + B1 + 8)) >> 4 + // We reuse the common sub-expressions. + const int a0b1 = A[i + 0] + B[i + 1]; + const int a1b0 = A[i + 1] + B[i + 0]; + const int a0a1b0b1 = a0b1 + a1b0 + 8; + const int v0 = (8 * A[i + 0] + 2 * a1b0 + a0a1b0b1) >> 4; + const int v1 = (8 * A[i + 1] + 2 * a0b1 + a0a1b0b1) >> 4; + out[2 * i + 0] = clip_SSE2(best_y[2 * i + 0] + v0, max_y); + out[2 * i + 1] = clip_SSE2(best_y[2 * i + 1] + v1, max_y); + } +} + +static WEBP_INLINE __m128i s16_to_s32(__m128i in) { + return _mm_srai_epi32(_mm_unpacklo_epi16(in, in), 16); +} + +static void SharpYuvFilterRow32_SSE2(const int16_t* A, const int16_t* B, + int len, const uint16_t* best_y, + uint16_t* out, int bit_depth) { + const int max_y = (1 << bit_depth) - 1; + int i; + const __m128i kCst8 = _mm_set1_epi32(8); + const __m128i max = _mm_set1_epi16(max_y); + const __m128i zero = _mm_setzero_si128(); + for (i = 0; i + 4 <= len; i += 4) { + const __m128i a0 = s16_to_s32(_mm_loadl_epi64((const __m128i*)(A + i + 0))); + const __m128i a1 = s16_to_s32(_mm_loadl_epi64((const __m128i*)(A + i + 1))); + const __m128i b0 = s16_to_s32(_mm_loadl_epi64((const __m128i*)(B + i + 0))); + const __m128i b1 = s16_to_s32(_mm_loadl_epi64((const __m128i*)(B + i + 1))); + const __m128i a0b1 = _mm_add_epi32(a0, b1); + const __m128i a1b0 = _mm_add_epi32(a1, b0); + const __m128i a0a1b0b1 = _mm_add_epi32(a0b1, a1b0); // A0+A1+B0+B1 + const __m128i a0a1b0b1_8 = _mm_add_epi32(a0a1b0b1, kCst8); + const __m128i a0b1_2 = _mm_add_epi32(a0b1, a0b1); // 2*(A0+B1) + const __m128i a1b0_2 = _mm_add_epi32(a1b0, a1b0); // 2*(A1+B0) + const __m128i c0 = _mm_srai_epi32(_mm_add_epi32(a0b1_2, a0a1b0b1_8), 3); + const __m128i c1 = _mm_srai_epi32(_mm_add_epi32(a1b0_2, a0a1b0b1_8), 3); + const __m128i d0 = _mm_add_epi32(c1, a0); + const __m128i d1 = _mm_add_epi32(c0, a1); + const __m128i e0 = _mm_srai_epi32(d0, 1); + const __m128i e1 = _mm_srai_epi32(d1, 1); + const __m128i f0 = _mm_unpacklo_epi32(e0, e1); + const __m128i f1 = _mm_unpackhi_epi32(e0, e1); + const __m128i g = _mm_loadu_si128((const __m128i*)(best_y + 2 * i + 0)); + const __m128i h_16 = _mm_add_epi16(g, _mm_packs_epi32(f0, f1)); + const __m128i final = _mm_max_epi16(_mm_min_epi16(h_16, max), zero); + _mm_storeu_si128((__m128i*)(out + 2 * i + 0), final); + } + for (; i < len; ++i) { + // (9 * A0 + 3 * A1 + 3 * B0 + B1 + 8) >> 4 = + // = (8 * A0 + 2 * (A1 + B0) + (A0 + A1 + B0 + B1 + 8)) >> 4 + // We reuse the common sub-expressions. + const int a0b1 = A[i + 0] + B[i + 1]; + const int a1b0 = A[i + 1] + B[i + 0]; + const int a0a1b0b1 = a0b1 + a1b0 + 8; + const int v0 = (8 * A[i + 0] + 2 * a1b0 + a0a1b0b1) >> 4; + const int v1 = (8 * A[i + 1] + 2 * a0b1 + a0a1b0b1) >> 4; + out[2 * i + 0] = clip_SSE2(best_y[2 * i + 0] + v0, max_y); + out[2 * i + 1] = clip_SSE2(best_y[2 * i + 1] + v1, max_y); + } +} + +static void SharpYuvFilterRow_SSE2(const int16_t* A, const int16_t* B, int len, + const uint16_t* best_y, uint16_t* out, + int bit_depth) { + if (bit_depth <= 10) { + SharpYuvFilterRow16_SSE2(A, B, len, best_y, out, bit_depth); + } else { + SharpYuvFilterRow32_SSE2(A, B, len, best_y, out, bit_depth); + } +} + +//------------------------------------------------------------------------------ + +extern void InitSharpYuvSSE2(void); + +WEBP_TSAN_IGNORE_FUNCTION void InitSharpYuvSSE2(void) { + SharpYuvUpdateY = SharpYuvUpdateY_SSE2; + SharpYuvUpdateRGB = SharpYuvUpdateRGB_SSE2; + SharpYuvFilterRow = SharpYuvFilterRow_SSE2; +} +#else // !WEBP_USE_SSE2 + +extern void InitSharpYuvSSE2(void); + +void InitSharpYuvSSE2(void) {} + +#endif // WEBP_USE_SSE2 diff --git a/third-party/webp/libwebp/src/Makefile.am b/third-party/webp/libwebp/src/Makefile.am new file mode 100644 index 0000000000..bc4a320a94 --- /dev/null +++ b/third-party/webp/libwebp/src/Makefile.am @@ -0,0 +1,55 @@ +# The mux and demux libraries depend on libwebp, thus the '.' to force +# the build order so it's available to them. +SUBDIRS = dec enc dsp utils . +if BUILD_MUX + SUBDIRS += mux +endif +if BUILD_DEMUX + SUBDIRS += demux +endif + +lib_LTLIBRARIES = libwebp.la + +if BUILD_LIBWEBPDECODER + lib_LTLIBRARIES += libwebpdecoder.la +endif + +common_HEADERS = +common_HEADERS += webp/decode.h +common_HEADERS += webp/types.h +commondir = $(includedir)/webp + +libwebp_la_SOURCES = +libwebpinclude_HEADERS = +libwebpinclude_HEADERS += webp/encode.h + +noinst_HEADERS = +noinst_HEADERS += webp/format_constants.h + +libwebp_la_LIBADD = +libwebp_la_LIBADD += dec/libwebpdecode.la +libwebp_la_LIBADD += dsp/libwebpdsp.la +libwebp_la_LIBADD += enc/libwebpencode.la +libwebp_la_LIBADD += utils/libwebputils.la + +# Use '-no-undefined' to declare that libwebp does not depend on any libraries +# other than the ones listed on the command line, i.e., after linking, it will +# not have unresolved symbols. Some platforms (Windows among them) require all +# symbols in shared libraries to be resolved at library creation. +libwebp_la_LDFLAGS = -no-undefined -version-info 8:8:1 +libwebpincludedir = $(includedir)/webp +pkgconfig_DATA = libwebp.pc + +if BUILD_LIBWEBPDECODER + libwebpdecoder_la_SOURCES = + + libwebpdecoder_la_LIBADD = + libwebpdecoder_la_LIBADD += dec/libwebpdecode.la + libwebpdecoder_la_LIBADD += dsp/libwebpdspdecode.la + libwebpdecoder_la_LIBADD += utils/libwebputilsdecode.la + + libwebpdecoder_la_LDFLAGS = -no-undefined -version-info 4:8:1 + pkgconfig_DATA += libwebpdecoder.pc +endif + +${pkgconfig_DATA}: ${top_builddir}/config.status diff --git a/third-party/webp/libwebp/src/dec/Makefile.am b/third-party/webp/libwebp/src/dec/Makefile.am new file mode 100644 index 0000000000..f8c6398d99 --- /dev/null +++ b/third-party/webp/libwebp/src/dec/Makefile.am @@ -0,0 +1,29 @@ +AM_CPPFLAGS += -I$(top_builddir) -I$(top_srcdir) +noinst_LTLIBRARIES = libwebpdecode.la + +libwebpdecode_la_SOURCES = +libwebpdecode_la_SOURCES += alpha_dec.c +libwebpdecode_la_SOURCES += alphai_dec.h +libwebpdecode_la_SOURCES += buffer_dec.c +libwebpdecode_la_SOURCES += common_dec.h +libwebpdecode_la_SOURCES += vp8_dec.h +libwebpdecode_la_SOURCES += frame_dec.c +libwebpdecode_la_SOURCES += idec_dec.c +libwebpdecode_la_SOURCES += io_dec.c +libwebpdecode_la_SOURCES += quant_dec.c +libwebpdecode_la_SOURCES += tree_dec.c +libwebpdecode_la_SOURCES += vp8_dec.c +libwebpdecode_la_SOURCES += vp8i_dec.h +libwebpdecode_la_SOURCES += vp8l_dec.c +libwebpdecode_la_SOURCES += vp8li_dec.h +libwebpdecode_la_SOURCES += webp_dec.c +libwebpdecode_la_SOURCES += webpi_dec.h + +libwebpdecodeinclude_HEADERS = +libwebpdecodeinclude_HEADERS += ../webp/decode.h +libwebpdecodeinclude_HEADERS += ../webp/types.h +noinst_HEADERS = +noinst_HEADERS += ../webp/format_constants.h + +libwebpdecode_la_CPPFLAGS = $(AM_CPPFLAGS) +libwebpdecodeincludedir = $(includedir)/webp diff --git a/third-party/webp/libwebp/src/dec/alpha_dec.c b/third-party/webp/libwebp/src/dec/alpha_dec.c new file mode 100644 index 0000000000..663255c42f --- /dev/null +++ b/third-party/webp/libwebp/src/dec/alpha_dec.c @@ -0,0 +1,233 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Alpha-plane decompression. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include "src/dec/alphai_dec.h" +#include "src/dec/vp8i_dec.h" +#include "src/dec/vp8li_dec.h" +#include "src/dsp/dsp.h" +#include "src/utils/quant_levels_dec_utils.h" +#include "src/utils/utils.h" +#include "src/webp/format_constants.h" + +//------------------------------------------------------------------------------ +// ALPHDecoder object. + +// Allocates a new alpha decoder instance. +static ALPHDecoder* ALPHNew(void) { + ALPHDecoder* const dec = (ALPHDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec)); + return dec; +} + +// Clears and deallocates an alpha decoder instance. +static void ALPHDelete(ALPHDecoder* const dec) { + if (dec != NULL) { + VP8LDelete(dec->vp8l_dec_); + dec->vp8l_dec_ = NULL; + WebPSafeFree(dec); + } +} + +//------------------------------------------------------------------------------ +// Decoding. + +// Initialize alpha decoding by parsing the alpha header and decoding the image +// header for alpha data stored using lossless compression. +// Returns false in case of error in alpha header (data too short, invalid +// compression method or filter, error in lossless header data etc). +static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data, + size_t data_size, const VP8Io* const src_io, + uint8_t* output) { + int ok = 0; + const uint8_t* const alpha_data = data + ALPHA_HEADER_LEN; + const size_t alpha_data_size = data_size - ALPHA_HEADER_LEN; + int rsrv; + VP8Io* const io = &dec->io_; + + assert(data != NULL && output != NULL && src_io != NULL); + + VP8FiltersInit(); + dec->output_ = output; + dec->width_ = src_io->width; + dec->height_ = src_io->height; + assert(dec->width_ > 0 && dec->height_ > 0); + + if (data_size <= ALPHA_HEADER_LEN) { + return 0; + } + + dec->method_ = (data[0] >> 0) & 0x03; + dec->filter_ = (WEBP_FILTER_TYPE)((data[0] >> 2) & 0x03); + dec->pre_processing_ = (data[0] >> 4) & 0x03; + rsrv = (data[0] >> 6) & 0x03; + if (dec->method_ < ALPHA_NO_COMPRESSION || + dec->method_ > ALPHA_LOSSLESS_COMPRESSION || + dec->filter_ >= WEBP_FILTER_LAST || + dec->pre_processing_ > ALPHA_PREPROCESSED_LEVELS || + rsrv != 0) { + return 0; + } + + // Copy the necessary parameters from src_io to io + VP8InitIo(io); + WebPInitCustomIo(NULL, io); + io->opaque = dec; + io->width = src_io->width; + io->height = src_io->height; + + io->use_cropping = src_io->use_cropping; + io->crop_left = src_io->crop_left; + io->crop_right = src_io->crop_right; + io->crop_top = src_io->crop_top; + io->crop_bottom = src_io->crop_bottom; + // No need to copy the scaling parameters. + + if (dec->method_ == ALPHA_NO_COMPRESSION) { + const size_t alpha_decoded_size = dec->width_ * dec->height_; + ok = (alpha_data_size >= alpha_decoded_size); + } else { + assert(dec->method_ == ALPHA_LOSSLESS_COMPRESSION); + ok = VP8LDecodeAlphaHeader(dec, alpha_data, alpha_data_size); + } + + return ok; +} + +// Decodes, unfilters and dequantizes *at least* 'num_rows' rows of alpha +// starting from row number 'row'. It assumes that rows up to (row - 1) have +// already been decoded. +// Returns false in case of bitstream error. +static int ALPHDecode(VP8Decoder* const dec, int row, int num_rows) { + ALPHDecoder* const alph_dec = dec->alph_dec_; + const int width = alph_dec->width_; + const int height = alph_dec->io_.crop_bottom; + if (alph_dec->method_ == ALPHA_NO_COMPRESSION) { + int y; + const uint8_t* prev_line = dec->alpha_prev_line_; + const uint8_t* deltas = dec->alpha_data_ + ALPHA_HEADER_LEN + row * width; + uint8_t* dst = dec->alpha_plane_ + row * width; + assert(deltas <= &dec->alpha_data_[dec->alpha_data_size_]); + assert(WebPUnfilters[alph_dec->filter_] != NULL); + for (y = 0; y < num_rows; ++y) { + WebPUnfilters[alph_dec->filter_](prev_line, deltas, dst, width); + prev_line = dst; + dst += width; + deltas += width; + } + dec->alpha_prev_line_ = prev_line; + } else { // alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION + assert(alph_dec->vp8l_dec_ != NULL); + if (!VP8LDecodeAlphaImageStream(alph_dec, row + num_rows)) { + return 0; + } + } + + if (row + num_rows >= height) { + dec->is_alpha_decoded_ = 1; + } + return 1; +} + +static int AllocateAlphaPlane(VP8Decoder* const dec, const VP8Io* const io) { + const int stride = io->width; + const int height = io->crop_bottom; + const uint64_t alpha_size = (uint64_t)stride * height; + assert(dec->alpha_plane_mem_ == NULL); + dec->alpha_plane_mem_ = + (uint8_t*)WebPSafeMalloc(alpha_size, sizeof(*dec->alpha_plane_)); + if (dec->alpha_plane_mem_ == NULL) { + return VP8SetError(dec, VP8_STATUS_OUT_OF_MEMORY, + "Alpha decoder initialization failed."); + } + dec->alpha_plane_ = dec->alpha_plane_mem_; + dec->alpha_prev_line_ = NULL; + return 1; +} + +void WebPDeallocateAlphaMemory(VP8Decoder* const dec) { + assert(dec != NULL); + WebPSafeFree(dec->alpha_plane_mem_); + dec->alpha_plane_mem_ = NULL; + dec->alpha_plane_ = NULL; + ALPHDelete(dec->alph_dec_); + dec->alph_dec_ = NULL; +} + +//------------------------------------------------------------------------------ +// Main entry point. + +const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, + const VP8Io* const io, + int row, int num_rows) { + const int width = io->width; + const int height = io->crop_bottom; + + assert(dec != NULL && io != NULL); + + if (row < 0 || num_rows <= 0 || row + num_rows > height) { + return NULL; + } + + if (!dec->is_alpha_decoded_) { + if (dec->alph_dec_ == NULL) { // Initialize decoder. + dec->alph_dec_ = ALPHNew(); + if (dec->alph_dec_ == NULL) { + VP8SetError(dec, VP8_STATUS_OUT_OF_MEMORY, + "Alpha decoder initialization failed."); + return NULL; + } + if (!AllocateAlphaPlane(dec, io)) goto Error; + if (!ALPHInit(dec->alph_dec_, dec->alpha_data_, dec->alpha_data_size_, + io, dec->alpha_plane_)) { + VP8LDecoder* const vp8l_dec = dec->alph_dec_->vp8l_dec_; + VP8SetError(dec, + (vp8l_dec == NULL) ? VP8_STATUS_OUT_OF_MEMORY + : vp8l_dec->status_, + "Alpha decoder initialization failed."); + goto Error; + } + // if we allowed use of alpha dithering, check whether it's needed at all + if (dec->alph_dec_->pre_processing_ != ALPHA_PREPROCESSED_LEVELS) { + dec->alpha_dithering_ = 0; // disable dithering + } else { + num_rows = height - row; // decode everything in one pass + } + } + + assert(dec->alph_dec_ != NULL); + assert(row + num_rows <= height); + if (!ALPHDecode(dec, row, num_rows)) goto Error; + + if (dec->is_alpha_decoded_) { // finished? + ALPHDelete(dec->alph_dec_); + dec->alph_dec_ = NULL; + if (dec->alpha_dithering_ > 0) { + uint8_t* const alpha = dec->alpha_plane_ + io->crop_top * width + + io->crop_left; + if (!WebPDequantizeLevels(alpha, + io->crop_right - io->crop_left, + io->crop_bottom - io->crop_top, + width, dec->alpha_dithering_)) { + goto Error; + } + } + } + } + + // Return a pointer to the current decoded row. + return dec->alpha_plane_ + row * width; + + Error: + WebPDeallocateAlphaMemory(dec); + return NULL; +} diff --git a/third-party/webp/libwebp/src/dec/alphai_dec.h b/third-party/webp/libwebp/src/dec/alphai_dec.h new file mode 100644 index 0000000000..a64104abeb --- /dev/null +++ b/third-party/webp/libwebp/src/dec/alphai_dec.h @@ -0,0 +1,54 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Alpha decoder: internal header. +// +// Author: Urvang (urvang@google.com) + +#ifndef WEBP_DEC_ALPHAI_DEC_H_ +#define WEBP_DEC_ALPHAI_DEC_H_ + +#include "src/dec/webpi_dec.h" +#include "src/utils/filters_utils.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct VP8LDecoder; // Defined in dec/vp8li.h. + +typedef struct ALPHDecoder ALPHDecoder; +struct ALPHDecoder { + int width_; + int height_; + int method_; + WEBP_FILTER_TYPE filter_; + int pre_processing_; + struct VP8LDecoder* vp8l_dec_; + VP8Io io_; + int use_8b_decode_; // Although alpha channel requires only 1 byte per + // pixel, sometimes VP8LDecoder may need to allocate + // 4 bytes per pixel internally during decode. + uint8_t* output_; + const uint8_t* prev_line_; // last output row (or NULL) +}; + +//------------------------------------------------------------------------------ +// internal functions. Not public. + +// Deallocate memory associated to dec->alpha_plane_ decoding +void WebPDeallocateAlphaMemory(VP8Decoder* const dec); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_DEC_ALPHAI_DEC_H_ diff --git a/third-party/webp/libwebp/src/dec/buffer_dec.c b/third-party/webp/libwebp/src/dec/buffer_dec.c new file mode 100644 index 0000000000..11ce76f19e --- /dev/null +++ b/third-party/webp/libwebp/src/dec/buffer_dec.c @@ -0,0 +1,310 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Everything about WebPDecBuffer +// +// Author: Skal (pascal.massimino@gmail.com) + +#include + +#include "src/dec/vp8i_dec.h" +#include "src/dec/webpi_dec.h" +#include "src/utils/utils.h" + +//------------------------------------------------------------------------------ +// WebPDecBuffer + +// Number of bytes per pixel for the different color-spaces. +static const uint8_t kModeBpp[MODE_LAST] = { + 3, 4, 3, 4, 4, 2, 2, + 4, 4, 4, 2, // pre-multiplied modes + 1, 1 }; + +// Check that webp_csp_mode is within the bounds of WEBP_CSP_MODE. +// Convert to an integer to handle both the unsigned/signed enum cases +// without the need for casting to remove type limit warnings. +static int IsValidColorspace(int webp_csp_mode) { + return (webp_csp_mode >= MODE_RGB && webp_csp_mode < MODE_LAST); +} + +// strictly speaking, the very last (or first, if flipped) row +// doesn't require padding. +#define MIN_BUFFER_SIZE(WIDTH, HEIGHT, STRIDE) \ + ((uint64_t)(STRIDE) * ((HEIGHT) - 1) + (WIDTH)) + +static VP8StatusCode CheckDecBuffer(const WebPDecBuffer* const buffer) { + int ok = 1; + const WEBP_CSP_MODE mode = buffer->colorspace; + const int width = buffer->width; + const int height = buffer->height; + if (!IsValidColorspace(mode)) { + ok = 0; + } else if (!WebPIsRGBMode(mode)) { // YUV checks + const WebPYUVABuffer* const buf = &buffer->u.YUVA; + const int uv_width = (width + 1) / 2; + const int uv_height = (height + 1) / 2; + const int y_stride = abs(buf->y_stride); + const int u_stride = abs(buf->u_stride); + const int v_stride = abs(buf->v_stride); + const int a_stride = abs(buf->a_stride); + const uint64_t y_size = MIN_BUFFER_SIZE(width, height, y_stride); + const uint64_t u_size = MIN_BUFFER_SIZE(uv_width, uv_height, u_stride); + const uint64_t v_size = MIN_BUFFER_SIZE(uv_width, uv_height, v_stride); + const uint64_t a_size = MIN_BUFFER_SIZE(width, height, a_stride); + ok &= (y_size <= buf->y_size); + ok &= (u_size <= buf->u_size); + ok &= (v_size <= buf->v_size); + ok &= (y_stride >= width); + ok &= (u_stride >= uv_width); + ok &= (v_stride >= uv_width); + ok &= (buf->y != NULL); + ok &= (buf->u != NULL); + ok &= (buf->v != NULL); + if (mode == MODE_YUVA) { + ok &= (a_stride >= width); + ok &= (a_size <= buf->a_size); + ok &= (buf->a != NULL); + } + } else { // RGB checks + const WebPRGBABuffer* const buf = &buffer->u.RGBA; + const int stride = abs(buf->stride); + const uint64_t size = + MIN_BUFFER_SIZE((uint64_t)width * kModeBpp[mode], height, stride); + ok &= (size <= buf->size); + ok &= (stride >= width * kModeBpp[mode]); + ok &= (buf->rgba != NULL); + } + return ok ? VP8_STATUS_OK : VP8_STATUS_INVALID_PARAM; +} +#undef MIN_BUFFER_SIZE + +static VP8StatusCode AllocateBuffer(WebPDecBuffer* const buffer) { + const int w = buffer->width; + const int h = buffer->height; + const WEBP_CSP_MODE mode = buffer->colorspace; + + if (w <= 0 || h <= 0 || !IsValidColorspace(mode)) { + return VP8_STATUS_INVALID_PARAM; + } + + if (buffer->is_external_memory <= 0 && buffer->private_memory == NULL) { + uint8_t* output; + int uv_stride = 0, a_stride = 0; + uint64_t uv_size = 0, a_size = 0, total_size; + // We need memory and it hasn't been allocated yet. + // => initialize output buffer, now that dimensions are known. + int stride; + uint64_t size; + + if ((uint64_t)w * kModeBpp[mode] >= (1ull << 31)) { + return VP8_STATUS_INVALID_PARAM; + } + stride = w * kModeBpp[mode]; + size = (uint64_t)stride * h; + if (!WebPIsRGBMode(mode)) { + uv_stride = (w + 1) / 2; + uv_size = (uint64_t)uv_stride * ((h + 1) / 2); + if (mode == MODE_YUVA) { + a_stride = w; + a_size = (uint64_t)a_stride * h; + } + } + total_size = size + 2 * uv_size + a_size; + + output = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*output)); + if (output == NULL) { + return VP8_STATUS_OUT_OF_MEMORY; + } + buffer->private_memory = output; + + if (!WebPIsRGBMode(mode)) { // YUVA initialization + WebPYUVABuffer* const buf = &buffer->u.YUVA; + buf->y = output; + buf->y_stride = stride; + buf->y_size = (size_t)size; + buf->u = output + size; + buf->u_stride = uv_stride; + buf->u_size = (size_t)uv_size; + buf->v = output + size + uv_size; + buf->v_stride = uv_stride; + buf->v_size = (size_t)uv_size; + if (mode == MODE_YUVA) { + buf->a = output + size + 2 * uv_size; + } + buf->a_size = (size_t)a_size; + buf->a_stride = a_stride; + } else { // RGBA initialization + WebPRGBABuffer* const buf = &buffer->u.RGBA; + buf->rgba = output; + buf->stride = stride; + buf->size = (size_t)size; + } + } + return CheckDecBuffer(buffer); +} + +VP8StatusCode WebPFlipBuffer(WebPDecBuffer* const buffer) { + if (buffer == NULL) { + return VP8_STATUS_INVALID_PARAM; + } + if (WebPIsRGBMode(buffer->colorspace)) { + WebPRGBABuffer* const buf = &buffer->u.RGBA; + buf->rgba += (int64_t)(buffer->height - 1) * buf->stride; + buf->stride = -buf->stride; + } else { + WebPYUVABuffer* const buf = &buffer->u.YUVA; + const int64_t H = buffer->height; + buf->y += (H - 1) * buf->y_stride; + buf->y_stride = -buf->y_stride; + buf->u += ((H - 1) >> 1) * buf->u_stride; + buf->u_stride = -buf->u_stride; + buf->v += ((H - 1) >> 1) * buf->v_stride; + buf->v_stride = -buf->v_stride; + if (buf->a != NULL) { + buf->a += (H - 1) * buf->a_stride; + buf->a_stride = -buf->a_stride; + } + } + return VP8_STATUS_OK; +} + +VP8StatusCode WebPAllocateDecBuffer(int width, int height, + const WebPDecoderOptions* const options, + WebPDecBuffer* const buffer) { + VP8StatusCode status; + if (buffer == NULL || width <= 0 || height <= 0) { + return VP8_STATUS_INVALID_PARAM; + } + if (options != NULL) { // First, apply options if there is any. + if (options->use_cropping) { + const int cw = options->crop_width; + const int ch = options->crop_height; + const int x = options->crop_left & ~1; + const int y = options->crop_top & ~1; + if (!WebPCheckCropDimensions(width, height, x, y, cw, ch)) { + return VP8_STATUS_INVALID_PARAM; // out of frame boundary. + } + width = cw; + height = ch; + } + + if (options->use_scaling) { +#if !defined(WEBP_REDUCE_SIZE) + int scaled_width = options->scaled_width; + int scaled_height = options->scaled_height; + if (!WebPRescalerGetScaledDimensions( + width, height, &scaled_width, &scaled_height)) { + return VP8_STATUS_INVALID_PARAM; + } + width = scaled_width; + height = scaled_height; +#else + return VP8_STATUS_INVALID_PARAM; // rescaling not supported +#endif + } + } + buffer->width = width; + buffer->height = height; + + // Then, allocate buffer for real. + status = AllocateBuffer(buffer); + if (status != VP8_STATUS_OK) return status; + + // Use the stride trick if vertical flip is needed. + if (options != NULL && options->flip) { + status = WebPFlipBuffer(buffer); + } + return status; +} + +//------------------------------------------------------------------------------ +// constructors / destructors + +int WebPInitDecBufferInternal(WebPDecBuffer* buffer, int version) { + if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) { + return 0; // version mismatch + } + if (buffer == NULL) return 0; + memset(buffer, 0, sizeof(*buffer)); + return 1; +} + +void WebPFreeDecBuffer(WebPDecBuffer* buffer) { + if (buffer != NULL) { + if (buffer->is_external_memory <= 0) { + WebPSafeFree(buffer->private_memory); + } + buffer->private_memory = NULL; + } +} + +void WebPCopyDecBuffer(const WebPDecBuffer* const src, + WebPDecBuffer* const dst) { + if (src != NULL && dst != NULL) { + *dst = *src; + if (src->private_memory != NULL) { + dst->is_external_memory = 1; // dst buffer doesn't own the memory. + dst->private_memory = NULL; + } + } +} + +// Copy and transfer ownership from src to dst (beware of parameter order!) +void WebPGrabDecBuffer(WebPDecBuffer* const src, WebPDecBuffer* const dst) { + if (src != NULL && dst != NULL) { + *dst = *src; + if (src->private_memory != NULL) { + src->is_external_memory = 1; // src relinquishes ownership + src->private_memory = NULL; + } + } +} + +VP8StatusCode WebPCopyDecBufferPixels(const WebPDecBuffer* const src_buf, + WebPDecBuffer* const dst_buf) { + assert(src_buf != NULL && dst_buf != NULL); + assert(src_buf->colorspace == dst_buf->colorspace); + + dst_buf->width = src_buf->width; + dst_buf->height = src_buf->height; + if (CheckDecBuffer(dst_buf) != VP8_STATUS_OK) { + return VP8_STATUS_INVALID_PARAM; + } + if (WebPIsRGBMode(src_buf->colorspace)) { + const WebPRGBABuffer* const src = &src_buf->u.RGBA; + const WebPRGBABuffer* const dst = &dst_buf->u.RGBA; + WebPCopyPlane(src->rgba, src->stride, dst->rgba, dst->stride, + src_buf->width * kModeBpp[src_buf->colorspace], + src_buf->height); + } else { + const WebPYUVABuffer* const src = &src_buf->u.YUVA; + const WebPYUVABuffer* const dst = &dst_buf->u.YUVA; + WebPCopyPlane(src->y, src->y_stride, dst->y, dst->y_stride, + src_buf->width, src_buf->height); + WebPCopyPlane(src->u, src->u_stride, dst->u, dst->u_stride, + (src_buf->width + 1) / 2, (src_buf->height + 1) / 2); + WebPCopyPlane(src->v, src->v_stride, dst->v, dst->v_stride, + (src_buf->width + 1) / 2, (src_buf->height + 1) / 2); + if (WebPIsAlphaMode(src_buf->colorspace)) { + WebPCopyPlane(src->a, src->a_stride, dst->a, dst->a_stride, + src_buf->width, src_buf->height); + } + } + return VP8_STATUS_OK; +} + +int WebPAvoidSlowMemory(const WebPDecBuffer* const output, + const WebPBitstreamFeatures* const features) { + assert(output != NULL); + return (output->is_external_memory >= 2) && + WebPIsPremultipliedMode(output->colorspace) && + (features != NULL && features->has_alpha); +} + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/src/dec/common_dec.h b/third-party/webp/libwebp/src/dec/common_dec.h new file mode 100644 index 0000000000..b158550a80 --- /dev/null +++ b/third-party/webp/libwebp/src/dec/common_dec.h @@ -0,0 +1,54 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Definitions and macros common to encoding and decoding +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_DEC_COMMON_DEC_H_ +#define WEBP_DEC_COMMON_DEC_H_ + +// intra prediction modes +enum { B_DC_PRED = 0, // 4x4 modes + B_TM_PRED = 1, + B_VE_PRED = 2, + B_HE_PRED = 3, + B_RD_PRED = 4, + B_VR_PRED = 5, + B_LD_PRED = 6, + B_VL_PRED = 7, + B_HD_PRED = 8, + B_HU_PRED = 9, + NUM_BMODES = B_HU_PRED + 1 - B_DC_PRED, // = 10 + + // Luma16 or UV modes + DC_PRED = B_DC_PRED, V_PRED = B_VE_PRED, + H_PRED = B_HE_PRED, TM_PRED = B_TM_PRED, + B_PRED = NUM_BMODES, // refined I4x4 mode + NUM_PRED_MODES = 4, + + // special modes + B_DC_PRED_NOTOP = 4, + B_DC_PRED_NOLEFT = 5, + B_DC_PRED_NOTOPLEFT = 6, + NUM_B_DC_MODES = 7 }; + +enum { MB_FEATURE_TREE_PROBS = 3, + NUM_MB_SEGMENTS = 4, + NUM_REF_LF_DELTAS = 4, + NUM_MODE_LF_DELTAS = 4, // I4x4, ZERO, *, SPLIT + MAX_NUM_PARTITIONS = 8, + // Probabilities + NUM_TYPES = 4, // 0: i16-AC, 1: i16-DC, 2:chroma-AC, 3:i4-AC + NUM_BANDS = 8, + NUM_CTX = 3, + NUM_PROBAS = 11 + }; + +#endif // WEBP_DEC_COMMON_DEC_H_ diff --git a/third-party/webp/libwebp/src/dec/frame_dec.c b/third-party/webp/libwebp/src/dec/frame_dec.c new file mode 100644 index 0000000000..91ca1f8609 --- /dev/null +++ b/third-party/webp/libwebp/src/dec/frame_dec.c @@ -0,0 +1,803 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Frame-reconstruction function. Memory allocation. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include "src/dec/vp8i_dec.h" +#include "src/utils/utils.h" + +//------------------------------------------------------------------------------ +// Main reconstruction function. + +static const uint16_t kScan[16] = { + 0 + 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS, + 0 + 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS, + 0 + 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS, + 0 + 12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS +}; + +static int CheckMode(int mb_x, int mb_y, int mode) { + if (mode == B_DC_PRED) { + if (mb_x == 0) { + return (mb_y == 0) ? B_DC_PRED_NOTOPLEFT : B_DC_PRED_NOLEFT; + } else { + return (mb_y == 0) ? B_DC_PRED_NOTOP : B_DC_PRED; + } + } + return mode; +} + +static void Copy32b(uint8_t* const dst, const uint8_t* const src) { + memcpy(dst, src, 4); +} + +static WEBP_INLINE void DoTransform(uint32_t bits, const int16_t* const src, + uint8_t* const dst) { + switch (bits >> 30) { + case 3: + VP8Transform(src, dst, 0); + break; + case 2: + VP8TransformAC3(src, dst); + break; + case 1: + VP8TransformDC(src, dst); + break; + default: + break; + } +} + +static void DoUVTransform(uint32_t bits, const int16_t* const src, + uint8_t* const dst) { + if (bits & 0xff) { // any non-zero coeff at all? + if (bits & 0xaa) { // any non-zero AC coefficient? + VP8TransformUV(src, dst); // note we don't use the AC3 variant for U/V + } else { + VP8TransformDCUV(src, dst); + } + } +} + +static void ReconstructRow(const VP8Decoder* const dec, + const VP8ThreadContext* ctx) { + int j; + int mb_x; + const int mb_y = ctx->mb_y_; + const int cache_id = ctx->id_; + uint8_t* const y_dst = dec->yuv_b_ + Y_OFF; + uint8_t* const u_dst = dec->yuv_b_ + U_OFF; + uint8_t* const v_dst = dec->yuv_b_ + V_OFF; + + // Initialize left-most block. + for (j = 0; j < 16; ++j) { + y_dst[j * BPS - 1] = 129; + } + for (j = 0; j < 8; ++j) { + u_dst[j * BPS - 1] = 129; + v_dst[j * BPS - 1] = 129; + } + + // Init top-left sample on left column too. + if (mb_y > 0) { + y_dst[-1 - BPS] = u_dst[-1 - BPS] = v_dst[-1 - BPS] = 129; + } else { + // we only need to do this init once at block (0,0). + // Afterward, it remains valid for the whole topmost row. + memset(y_dst - BPS - 1, 127, 16 + 4 + 1); + memset(u_dst - BPS - 1, 127, 8 + 1); + memset(v_dst - BPS - 1, 127, 8 + 1); + } + + // Reconstruct one row. + for (mb_x = 0; mb_x < dec->mb_w_; ++mb_x) { + const VP8MBData* const block = ctx->mb_data_ + mb_x; + + // Rotate in the left samples from previously decoded block. We move four + // pixels at a time for alignment reason, and because of in-loop filter. + if (mb_x > 0) { + for (j = -1; j < 16; ++j) { + Copy32b(&y_dst[j * BPS - 4], &y_dst[j * BPS + 12]); + } + for (j = -1; j < 8; ++j) { + Copy32b(&u_dst[j * BPS - 4], &u_dst[j * BPS + 4]); + Copy32b(&v_dst[j * BPS - 4], &v_dst[j * BPS + 4]); + } + } + { + // bring top samples into the cache + VP8TopSamples* const top_yuv = dec->yuv_t_ + mb_x; + const int16_t* const coeffs = block->coeffs_; + uint32_t bits = block->non_zero_y_; + int n; + + if (mb_y > 0) { + memcpy(y_dst - BPS, top_yuv[0].y, 16); + memcpy(u_dst - BPS, top_yuv[0].u, 8); + memcpy(v_dst - BPS, top_yuv[0].v, 8); + } + + // predict and add residuals + if (block->is_i4x4_) { // 4x4 + uint32_t* const top_right = (uint32_t*)(y_dst - BPS + 16); + + if (mb_y > 0) { + if (mb_x >= dec->mb_w_ - 1) { // on rightmost border + memset(top_right, top_yuv[0].y[15], sizeof(*top_right)); + } else { + memcpy(top_right, top_yuv[1].y, sizeof(*top_right)); + } + } + // replicate the top-right pixels below + top_right[BPS] = top_right[2 * BPS] = top_right[3 * BPS] = top_right[0]; + + // predict and add residuals for all 4x4 blocks in turn. + for (n = 0; n < 16; ++n, bits <<= 2) { + uint8_t* const dst = y_dst + kScan[n]; + VP8PredLuma4[block->imodes_[n]](dst); + DoTransform(bits, coeffs + n * 16, dst); + } + } else { // 16x16 + const int pred_func = CheckMode(mb_x, mb_y, block->imodes_[0]); + VP8PredLuma16[pred_func](y_dst); + if (bits != 0) { + for (n = 0; n < 16; ++n, bits <<= 2) { + DoTransform(bits, coeffs + n * 16, y_dst + kScan[n]); + } + } + } + { + // Chroma + const uint32_t bits_uv = block->non_zero_uv_; + const int pred_func = CheckMode(mb_x, mb_y, block->uvmode_); + VP8PredChroma8[pred_func](u_dst); + VP8PredChroma8[pred_func](v_dst); + DoUVTransform(bits_uv >> 0, coeffs + 16 * 16, u_dst); + DoUVTransform(bits_uv >> 8, coeffs + 20 * 16, v_dst); + } + + // stash away top samples for next block + if (mb_y < dec->mb_h_ - 1) { + memcpy(top_yuv[0].y, y_dst + 15 * BPS, 16); + memcpy(top_yuv[0].u, u_dst + 7 * BPS, 8); + memcpy(top_yuv[0].v, v_dst + 7 * BPS, 8); + } + } + // Transfer reconstructed samples from yuv_b_ cache to final destination. + { + const int y_offset = cache_id * 16 * dec->cache_y_stride_; + const int uv_offset = cache_id * 8 * dec->cache_uv_stride_; + uint8_t* const y_out = dec->cache_y_ + mb_x * 16 + y_offset; + uint8_t* const u_out = dec->cache_u_ + mb_x * 8 + uv_offset; + uint8_t* const v_out = dec->cache_v_ + mb_x * 8 + uv_offset; + for (j = 0; j < 16; ++j) { + memcpy(y_out + j * dec->cache_y_stride_, y_dst + j * BPS, 16); + } + for (j = 0; j < 8; ++j) { + memcpy(u_out + j * dec->cache_uv_stride_, u_dst + j * BPS, 8); + memcpy(v_out + j * dec->cache_uv_stride_, v_dst + j * BPS, 8); + } + } + } +} + +//------------------------------------------------------------------------------ +// Filtering + +// kFilterExtraRows[] = How many extra lines are needed on the MB boundary +// for caching, given a filtering level. +// Simple filter: up to 2 luma samples are read and 1 is written. +// Complex filter: up to 4 luma samples are read and 3 are written. Same for +// U/V, so it's 8 samples total (because of the 2x upsampling). +static const uint8_t kFilterExtraRows[3] = { 0, 2, 8 }; + +static void DoFilter(const VP8Decoder* const dec, int mb_x, int mb_y) { + const VP8ThreadContext* const ctx = &dec->thread_ctx_; + const int cache_id = ctx->id_; + const int y_bps = dec->cache_y_stride_; + const VP8FInfo* const f_info = ctx->f_info_ + mb_x; + uint8_t* const y_dst = dec->cache_y_ + cache_id * 16 * y_bps + mb_x * 16; + const int ilevel = f_info->f_ilevel_; + const int limit = f_info->f_limit_; + if (limit == 0) { + return; + } + assert(limit >= 3); + if (dec->filter_type_ == 1) { // simple + if (mb_x > 0) { + VP8SimpleHFilter16(y_dst, y_bps, limit + 4); + } + if (f_info->f_inner_) { + VP8SimpleHFilter16i(y_dst, y_bps, limit); + } + if (mb_y > 0) { + VP8SimpleVFilter16(y_dst, y_bps, limit + 4); + } + if (f_info->f_inner_) { + VP8SimpleVFilter16i(y_dst, y_bps, limit); + } + } else { // complex + const int uv_bps = dec->cache_uv_stride_; + uint8_t* const u_dst = dec->cache_u_ + cache_id * 8 * uv_bps + mb_x * 8; + uint8_t* const v_dst = dec->cache_v_ + cache_id * 8 * uv_bps + mb_x * 8; + const int hev_thresh = f_info->hev_thresh_; + if (mb_x > 0) { + VP8HFilter16(y_dst, y_bps, limit + 4, ilevel, hev_thresh); + VP8HFilter8(u_dst, v_dst, uv_bps, limit + 4, ilevel, hev_thresh); + } + if (f_info->f_inner_) { + VP8HFilter16i(y_dst, y_bps, limit, ilevel, hev_thresh); + VP8HFilter8i(u_dst, v_dst, uv_bps, limit, ilevel, hev_thresh); + } + if (mb_y > 0) { + VP8VFilter16(y_dst, y_bps, limit + 4, ilevel, hev_thresh); + VP8VFilter8(u_dst, v_dst, uv_bps, limit + 4, ilevel, hev_thresh); + } + if (f_info->f_inner_) { + VP8VFilter16i(y_dst, y_bps, limit, ilevel, hev_thresh); + VP8VFilter8i(u_dst, v_dst, uv_bps, limit, ilevel, hev_thresh); + } + } +} + +// Filter the decoded macroblock row (if needed) +static void FilterRow(const VP8Decoder* const dec) { + int mb_x; + const int mb_y = dec->thread_ctx_.mb_y_; + assert(dec->thread_ctx_.filter_row_); + for (mb_x = dec->tl_mb_x_; mb_x < dec->br_mb_x_; ++mb_x) { + DoFilter(dec, mb_x, mb_y); + } +} + +//------------------------------------------------------------------------------ +// Precompute the filtering strength for each segment and each i4x4/i16x16 mode. + +static void PrecomputeFilterStrengths(VP8Decoder* const dec) { + if (dec->filter_type_ > 0) { + int s; + const VP8FilterHeader* const hdr = &dec->filter_hdr_; + for (s = 0; s < NUM_MB_SEGMENTS; ++s) { + int i4x4; + // First, compute the initial level + int base_level; + if (dec->segment_hdr_.use_segment_) { + base_level = dec->segment_hdr_.filter_strength_[s]; + if (!dec->segment_hdr_.absolute_delta_) { + base_level += hdr->level_; + } + } else { + base_level = hdr->level_; + } + for (i4x4 = 0; i4x4 <= 1; ++i4x4) { + VP8FInfo* const info = &dec->fstrengths_[s][i4x4]; + int level = base_level; + if (hdr->use_lf_delta_) { + level += hdr->ref_lf_delta_[0]; + if (i4x4) { + level += hdr->mode_lf_delta_[0]; + } + } + level = (level < 0) ? 0 : (level > 63) ? 63 : level; + if (level > 0) { + int ilevel = level; + if (hdr->sharpness_ > 0) { + if (hdr->sharpness_ > 4) { + ilevel >>= 2; + } else { + ilevel >>= 1; + } + if (ilevel > 9 - hdr->sharpness_) { + ilevel = 9 - hdr->sharpness_; + } + } + if (ilevel < 1) ilevel = 1; + info->f_ilevel_ = ilevel; + info->f_limit_ = 2 * level + ilevel; + info->hev_thresh_ = (level >= 40) ? 2 : (level >= 15) ? 1 : 0; + } else { + info->f_limit_ = 0; // no filtering + } + info->f_inner_ = i4x4; + } + } + } +} + +//------------------------------------------------------------------------------ +// Dithering + +// minimal amp that will provide a non-zero dithering effect +#define MIN_DITHER_AMP 4 + +#define DITHER_AMP_TAB_SIZE 12 +static const uint8_t kQuantToDitherAmp[DITHER_AMP_TAB_SIZE] = { + // roughly, it's dqm->uv_mat_[1] + 8, 7, 6, 4, 4, 2, 2, 2, 1, 1, 1, 1 +}; + +void VP8InitDithering(const WebPDecoderOptions* const options, + VP8Decoder* const dec) { + assert(dec != NULL); + if (options != NULL) { + const int d = options->dithering_strength; + const int max_amp = (1 << VP8_RANDOM_DITHER_FIX) - 1; + const int f = (d < 0) ? 0 : (d > 100) ? max_amp : (d * max_amp / 100); + if (f > 0) { + int s; + int all_amp = 0; + for (s = 0; s < NUM_MB_SEGMENTS; ++s) { + VP8QuantMatrix* const dqm = &dec->dqm_[s]; + if (dqm->uv_quant_ < DITHER_AMP_TAB_SIZE) { + const int idx = (dqm->uv_quant_ < 0) ? 0 : dqm->uv_quant_; + dqm->dither_ = (f * kQuantToDitherAmp[idx]) >> 3; + } + all_amp |= dqm->dither_; + } + if (all_amp != 0) { + VP8InitRandom(&dec->dithering_rg_, 1.0f); + dec->dither_ = 1; + } + } + // potentially allow alpha dithering + dec->alpha_dithering_ = options->alpha_dithering_strength; + if (dec->alpha_dithering_ > 100) { + dec->alpha_dithering_ = 100; + } else if (dec->alpha_dithering_ < 0) { + dec->alpha_dithering_ = 0; + } + } +} + +// Convert to range: [-2,2] for dither=50, [-4,4] for dither=100 +static void Dither8x8(VP8Random* const rg, uint8_t* dst, int bps, int amp) { + uint8_t dither[64]; + int i; + for (i = 0; i < 8 * 8; ++i) { + dither[i] = VP8RandomBits2(rg, VP8_DITHER_AMP_BITS + 1, amp); + } + VP8DitherCombine8x8(dither, dst, bps); +} + +static void DitherRow(VP8Decoder* const dec) { + int mb_x; + assert(dec->dither_); + for (mb_x = dec->tl_mb_x_; mb_x < dec->br_mb_x_; ++mb_x) { + const VP8ThreadContext* const ctx = &dec->thread_ctx_; + const VP8MBData* const data = ctx->mb_data_ + mb_x; + const int cache_id = ctx->id_; + const int uv_bps = dec->cache_uv_stride_; + if (data->dither_ >= MIN_DITHER_AMP) { + uint8_t* const u_dst = dec->cache_u_ + cache_id * 8 * uv_bps + mb_x * 8; + uint8_t* const v_dst = dec->cache_v_ + cache_id * 8 * uv_bps + mb_x * 8; + Dither8x8(&dec->dithering_rg_, u_dst, uv_bps, data->dither_); + Dither8x8(&dec->dithering_rg_, v_dst, uv_bps, data->dither_); + } + } +} + +//------------------------------------------------------------------------------ +// This function is called after a row of macroblocks is finished decoding. +// It also takes into account the following restrictions: +// * In case of in-loop filtering, we must hold off sending some of the bottom +// pixels as they are yet unfiltered. They will be when the next macroblock +// row is decoded. Meanwhile, we must preserve them by rotating them in the +// cache area. This doesn't hold for the very bottom row of the uncropped +// picture of course. +// * we must clip the remaining pixels against the cropping area. The VP8Io +// struct must have the following fields set correctly before calling put(): + +#define MACROBLOCK_VPOS(mb_y) ((mb_y) * 16) // vertical position of a MB + +// Finalize and transmit a complete row. Return false in case of user-abort. +static int FinishRow(void* arg1, void* arg2) { + VP8Decoder* const dec = (VP8Decoder*)arg1; + VP8Io* const io = (VP8Io*)arg2; + int ok = 1; + const VP8ThreadContext* const ctx = &dec->thread_ctx_; + const int cache_id = ctx->id_; + const int extra_y_rows = kFilterExtraRows[dec->filter_type_]; + const int ysize = extra_y_rows * dec->cache_y_stride_; + const int uvsize = (extra_y_rows / 2) * dec->cache_uv_stride_; + const int y_offset = cache_id * 16 * dec->cache_y_stride_; + const int uv_offset = cache_id * 8 * dec->cache_uv_stride_; + uint8_t* const ydst = dec->cache_y_ - ysize + y_offset; + uint8_t* const udst = dec->cache_u_ - uvsize + uv_offset; + uint8_t* const vdst = dec->cache_v_ - uvsize + uv_offset; + const int mb_y = ctx->mb_y_; + const int is_first_row = (mb_y == 0); + const int is_last_row = (mb_y >= dec->br_mb_y_ - 1); + + if (dec->mt_method_ == 2) { + ReconstructRow(dec, ctx); + } + + if (ctx->filter_row_) { + FilterRow(dec); + } + + if (dec->dither_) { + DitherRow(dec); + } + + if (io->put != NULL) { + int y_start = MACROBLOCK_VPOS(mb_y); + int y_end = MACROBLOCK_VPOS(mb_y + 1); + if (!is_first_row) { + y_start -= extra_y_rows; + io->y = ydst; + io->u = udst; + io->v = vdst; + } else { + io->y = dec->cache_y_ + y_offset; + io->u = dec->cache_u_ + uv_offset; + io->v = dec->cache_v_ + uv_offset; + } + + if (!is_last_row) { + y_end -= extra_y_rows; + } + if (y_end > io->crop_bottom) { + y_end = io->crop_bottom; // make sure we don't overflow on last row. + } + // If dec->alpha_data_ is not NULL, we have some alpha plane present. + io->a = NULL; + if (dec->alpha_data_ != NULL && y_start < y_end) { + io->a = VP8DecompressAlphaRows(dec, io, y_start, y_end - y_start); + if (io->a == NULL) { + return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, + "Could not decode alpha data."); + } + } + if (y_start < io->crop_top) { + const int delta_y = io->crop_top - y_start; + y_start = io->crop_top; + assert(!(delta_y & 1)); + io->y += dec->cache_y_stride_ * delta_y; + io->u += dec->cache_uv_stride_ * (delta_y >> 1); + io->v += dec->cache_uv_stride_ * (delta_y >> 1); + if (io->a != NULL) { + io->a += io->width * delta_y; + } + } + if (y_start < y_end) { + io->y += io->crop_left; + io->u += io->crop_left >> 1; + io->v += io->crop_left >> 1; + if (io->a != NULL) { + io->a += io->crop_left; + } + io->mb_y = y_start - io->crop_top; + io->mb_w = io->crop_right - io->crop_left; + io->mb_h = y_end - y_start; + ok = io->put(io); + } + } + // rotate top samples if needed + if (cache_id + 1 == dec->num_caches_) { + if (!is_last_row) { + memcpy(dec->cache_y_ - ysize, ydst + 16 * dec->cache_y_stride_, ysize); + memcpy(dec->cache_u_ - uvsize, udst + 8 * dec->cache_uv_stride_, uvsize); + memcpy(dec->cache_v_ - uvsize, vdst + 8 * dec->cache_uv_stride_, uvsize); + } + } + + return ok; +} + +#undef MACROBLOCK_VPOS + +//------------------------------------------------------------------------------ + +int VP8ProcessRow(VP8Decoder* const dec, VP8Io* const io) { + int ok = 1; + VP8ThreadContext* const ctx = &dec->thread_ctx_; + const int filter_row = + (dec->filter_type_ > 0) && + (dec->mb_y_ >= dec->tl_mb_y_) && (dec->mb_y_ <= dec->br_mb_y_); + if (dec->mt_method_ == 0) { + // ctx->id_ and ctx->f_info_ are already set + ctx->mb_y_ = dec->mb_y_; + ctx->filter_row_ = filter_row; + ReconstructRow(dec, ctx); + ok = FinishRow(dec, io); + } else { + WebPWorker* const worker = &dec->worker_; + // Finish previous job *before* updating context + ok &= WebPGetWorkerInterface()->Sync(worker); + assert(worker->status_ == OK); + if (ok) { // spawn a new deblocking/output job + ctx->io_ = *io; + ctx->id_ = dec->cache_id_; + ctx->mb_y_ = dec->mb_y_; + ctx->filter_row_ = filter_row; + if (dec->mt_method_ == 2) { // swap macroblock data + VP8MBData* const tmp = ctx->mb_data_; + ctx->mb_data_ = dec->mb_data_; + dec->mb_data_ = tmp; + } else { + // perform reconstruction directly in main thread + ReconstructRow(dec, ctx); + } + if (filter_row) { // swap filter info + VP8FInfo* const tmp = ctx->f_info_; + ctx->f_info_ = dec->f_info_; + dec->f_info_ = tmp; + } + // (reconstruct)+filter in parallel + WebPGetWorkerInterface()->Launch(worker); + if (++dec->cache_id_ == dec->num_caches_) { + dec->cache_id_ = 0; + } + } + } + return ok; +} + +//------------------------------------------------------------------------------ +// Finish setting up the decoding parameter once user's setup() is called. + +VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io) { + // Call setup() first. This may trigger additional decoding features on 'io'. + // Note: Afterward, we must call teardown() no matter what. + if (io->setup != NULL && !io->setup(io)) { + VP8SetError(dec, VP8_STATUS_USER_ABORT, "Frame setup failed"); + return dec->status_; + } + + // Disable filtering per user request + if (io->bypass_filtering) { + dec->filter_type_ = 0; + } + + // Define the area where we can skip in-loop filtering, in case of cropping. + // + // 'Simple' filter reads two luma samples outside of the macroblock + // and filters one. It doesn't filter the chroma samples. Hence, we can + // avoid doing the in-loop filtering before crop_top/crop_left position. + // For the 'Complex' filter, 3 samples are read and up to 3 are filtered. + // Means: there's a dependency chain that goes all the way up to the + // top-left corner of the picture (MB #0). We must filter all the previous + // macroblocks. + { + const int extra_pixels = kFilterExtraRows[dec->filter_type_]; + if (dec->filter_type_ == 2) { + // For complex filter, we need to preserve the dependency chain. + dec->tl_mb_x_ = 0; + dec->tl_mb_y_ = 0; + } else { + // For simple filter, we can filter only the cropped region. + // We include 'extra_pixels' on the other side of the boundary, since + // vertical or horizontal filtering of the previous macroblock can + // modify some abutting pixels. + dec->tl_mb_x_ = (io->crop_left - extra_pixels) >> 4; + dec->tl_mb_y_ = (io->crop_top - extra_pixels) >> 4; + if (dec->tl_mb_x_ < 0) dec->tl_mb_x_ = 0; + if (dec->tl_mb_y_ < 0) dec->tl_mb_y_ = 0; + } + // We need some 'extra' pixels on the right/bottom. + dec->br_mb_y_ = (io->crop_bottom + 15 + extra_pixels) >> 4; + dec->br_mb_x_ = (io->crop_right + 15 + extra_pixels) >> 4; + if (dec->br_mb_x_ > dec->mb_w_) { + dec->br_mb_x_ = dec->mb_w_; + } + if (dec->br_mb_y_ > dec->mb_h_) { + dec->br_mb_y_ = dec->mb_h_; + } + } + PrecomputeFilterStrengths(dec); + return VP8_STATUS_OK; +} + +int VP8ExitCritical(VP8Decoder* const dec, VP8Io* const io) { + int ok = 1; + if (dec->mt_method_ > 0) { + ok = WebPGetWorkerInterface()->Sync(&dec->worker_); + } + + if (io->teardown != NULL) { + io->teardown(io); + } + return ok; +} + +//------------------------------------------------------------------------------ +// For multi-threaded decoding we need to use 3 rows of 16 pixels as delay line. +// +// Reason is: the deblocking filter cannot deblock the bottom horizontal edges +// immediately, and needs to wait for first few rows of the next macroblock to +// be decoded. Hence, deblocking is lagging behind by 4 or 8 pixels (depending +// on strength). +// With two threads, the vertical positions of the rows being decoded are: +// Decode: [ 0..15][16..31][32..47][48..63][64..79][... +// Deblock: [ 0..11][12..27][28..43][44..59][... +// If we use two threads and two caches of 16 pixels, the sequence would be: +// Decode: [ 0..15][16..31][ 0..15!!][16..31][ 0..15][... +// Deblock: [ 0..11][12..27!!][-4..11][12..27][... +// The problem occurs during row [12..15!!] that both the decoding and +// deblocking threads are writing simultaneously. +// With 3 cache lines, one get a safe write pattern: +// Decode: [ 0..15][16..31][32..47][ 0..15][16..31][32..47][0.. +// Deblock: [ 0..11][12..27][28..43][-4..11][12..27][28... +// Note that multi-threaded output _without_ deblocking can make use of two +// cache lines of 16 pixels only, since there's no lagging behind. The decoding +// and output process have non-concurrent writing: +// Decode: [ 0..15][16..31][ 0..15][16..31][... +// io->put: [ 0..15][16..31][ 0..15][... + +#define MT_CACHE_LINES 3 +#define ST_CACHE_LINES 1 // 1 cache row only for single-threaded case + +// Initialize multi/single-thread worker +static int InitThreadContext(VP8Decoder* const dec) { + dec->cache_id_ = 0; + if (dec->mt_method_ > 0) { + WebPWorker* const worker = &dec->worker_; + if (!WebPGetWorkerInterface()->Reset(worker)) { + return VP8SetError(dec, VP8_STATUS_OUT_OF_MEMORY, + "thread initialization failed."); + } + worker->data1 = dec; + worker->data2 = (void*)&dec->thread_ctx_.io_; + worker->hook = FinishRow; + dec->num_caches_ = + (dec->filter_type_ > 0) ? MT_CACHE_LINES : MT_CACHE_LINES - 1; + } else { + dec->num_caches_ = ST_CACHE_LINES; + } + return 1; +} + +int VP8GetThreadMethod(const WebPDecoderOptions* const options, + const WebPHeaderStructure* const headers, + int width, int height) { + if (options == NULL || options->use_threads == 0) { + return 0; + } + (void)headers; + (void)width; + (void)height; + assert(headers == NULL || !headers->is_lossless); +#if defined(WEBP_USE_THREAD) + if (width >= MIN_WIDTH_FOR_THREADS) return 2; +#endif + return 0; +} + +#undef MT_CACHE_LINES +#undef ST_CACHE_LINES + +//------------------------------------------------------------------------------ +// Memory setup + +static int AllocateMemory(VP8Decoder* const dec) { + const int num_caches = dec->num_caches_; + const int mb_w = dec->mb_w_; + // Note: we use 'size_t' when there's no overflow risk, uint64_t otherwise. + const size_t intra_pred_mode_size = 4 * mb_w * sizeof(uint8_t); + const size_t top_size = sizeof(VP8TopSamples) * mb_w; + const size_t mb_info_size = (mb_w + 1) * sizeof(VP8MB); + const size_t f_info_size = + (dec->filter_type_ > 0) ? + mb_w * (dec->mt_method_ > 0 ? 2 : 1) * sizeof(VP8FInfo) + : 0; + const size_t yuv_size = YUV_SIZE * sizeof(*dec->yuv_b_); + const size_t mb_data_size = + (dec->mt_method_ == 2 ? 2 : 1) * mb_w * sizeof(*dec->mb_data_); + const size_t cache_height = (16 * num_caches + + kFilterExtraRows[dec->filter_type_]) * 3 / 2; + const size_t cache_size = top_size * cache_height; + // alpha_size is the only one that scales as width x height. + const uint64_t alpha_size = (dec->alpha_data_ != NULL) ? + (uint64_t)dec->pic_hdr_.width_ * dec->pic_hdr_.height_ : 0ULL; + const uint64_t needed = (uint64_t)intra_pred_mode_size + + top_size + mb_info_size + f_info_size + + yuv_size + mb_data_size + + cache_size + alpha_size + WEBP_ALIGN_CST; + uint8_t* mem; + + if (!CheckSizeOverflow(needed)) return 0; // check for overflow + if (needed > dec->mem_size_) { + WebPSafeFree(dec->mem_); + dec->mem_size_ = 0; + dec->mem_ = WebPSafeMalloc(needed, sizeof(uint8_t)); + if (dec->mem_ == NULL) { + return VP8SetError(dec, VP8_STATUS_OUT_OF_MEMORY, + "no memory during frame initialization."); + } + // down-cast is ok, thanks to WebPSafeMalloc() above. + dec->mem_size_ = (size_t)needed; + } + + mem = (uint8_t*)dec->mem_; + dec->intra_t_ = mem; + mem += intra_pred_mode_size; + + dec->yuv_t_ = (VP8TopSamples*)mem; + mem += top_size; + + dec->mb_info_ = ((VP8MB*)mem) + 1; + mem += mb_info_size; + + dec->f_info_ = f_info_size ? (VP8FInfo*)mem : NULL; + mem += f_info_size; + dec->thread_ctx_.id_ = 0; + dec->thread_ctx_.f_info_ = dec->f_info_; + if (dec->filter_type_ > 0 && dec->mt_method_ > 0) { + // secondary cache line. The deblocking process need to make use of the + // filtering strength from previous macroblock row, while the new ones + // are being decoded in parallel. We'll just swap the pointers. + dec->thread_ctx_.f_info_ += mb_w; + } + + mem = (uint8_t*)WEBP_ALIGN(mem); + assert((yuv_size & WEBP_ALIGN_CST) == 0); + dec->yuv_b_ = mem; + mem += yuv_size; + + dec->mb_data_ = (VP8MBData*)mem; + dec->thread_ctx_.mb_data_ = (VP8MBData*)mem; + if (dec->mt_method_ == 2) { + dec->thread_ctx_.mb_data_ += mb_w; + } + mem += mb_data_size; + + dec->cache_y_stride_ = 16 * mb_w; + dec->cache_uv_stride_ = 8 * mb_w; + { + const int extra_rows = kFilterExtraRows[dec->filter_type_]; + const int extra_y = extra_rows * dec->cache_y_stride_; + const int extra_uv = (extra_rows / 2) * dec->cache_uv_stride_; + dec->cache_y_ = mem + extra_y; + dec->cache_u_ = dec->cache_y_ + + 16 * num_caches * dec->cache_y_stride_ + extra_uv; + dec->cache_v_ = dec->cache_u_ + + 8 * num_caches * dec->cache_uv_stride_ + extra_uv; + dec->cache_id_ = 0; + } + mem += cache_size; + + // alpha plane + dec->alpha_plane_ = alpha_size ? mem : NULL; + mem += alpha_size; + assert(mem <= (uint8_t*)dec->mem_ + dec->mem_size_); + + // note: left/top-info is initialized once for all. + memset(dec->mb_info_ - 1, 0, mb_info_size); + VP8InitScanline(dec); // initialize left too. + + // initialize top + memset(dec->intra_t_, B_DC_PRED, intra_pred_mode_size); + + return 1; +} + +static void InitIo(VP8Decoder* const dec, VP8Io* io) { + // prepare 'io' + io->mb_y = 0; + io->y = dec->cache_y_; + io->u = dec->cache_u_; + io->v = dec->cache_v_; + io->y_stride = dec->cache_y_stride_; + io->uv_stride = dec->cache_uv_stride_; + io->a = NULL; +} + +int VP8InitFrame(VP8Decoder* const dec, VP8Io* const io) { + if (!InitThreadContext(dec)) return 0; // call first. Sets dec->num_caches_. + if (!AllocateMemory(dec)) return 0; + InitIo(dec, io); + VP8DspInit(); // Init critical function pointers and look-up tables. + return 1; +} + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/src/dec/idec_dec.c b/third-party/webp/libwebp/src/dec/idec_dec.c new file mode 100644 index 0000000000..9035df5659 --- /dev/null +++ b/third-party/webp/libwebp/src/dec/idec_dec.c @@ -0,0 +1,908 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Incremental decoding +// +// Author: somnath@google.com (Somnath Banerjee) + +#include +#include +#include + +#include "src/dec/alphai_dec.h" +#include "src/dec/webpi_dec.h" +#include "src/dec/vp8i_dec.h" +#include "src/utils/utils.h" + +// In append mode, buffer allocations increase as multiples of this value. +// Needs to be a power of 2. +#define CHUNK_SIZE 4096 +#define MAX_MB_SIZE 4096 + +//------------------------------------------------------------------------------ +// Data structures for memory and states + +// Decoding states. State normally flows as: +// WEBP_HEADER->VP8_HEADER->VP8_PARTS0->VP8_DATA->DONE for a lossy image, and +// WEBP_HEADER->VP8L_HEADER->VP8L_DATA->DONE for a lossless image. +// If there is any error the decoder goes into state ERROR. +typedef enum { + STATE_WEBP_HEADER, // All the data before that of the VP8/VP8L chunk. + STATE_VP8_HEADER, // The VP8 Frame header (within the VP8 chunk). + STATE_VP8_PARTS0, + STATE_VP8_DATA, + STATE_VP8L_HEADER, + STATE_VP8L_DATA, + STATE_DONE, + STATE_ERROR +} DecState; + +// Operating state for the MemBuffer +typedef enum { + MEM_MODE_NONE = 0, + MEM_MODE_APPEND, + MEM_MODE_MAP +} MemBufferMode; + +// storage for partition #0 and partial data (in a rolling fashion) +typedef struct { + MemBufferMode mode_; // Operation mode + size_t start_; // start location of the data to be decoded + size_t end_; // end location + size_t buf_size_; // size of the allocated buffer + uint8_t* buf_; // We don't own this buffer in case WebPIUpdate() + + size_t part0_size_; // size of partition #0 + const uint8_t* part0_buf_; // buffer to store partition #0 +} MemBuffer; + +struct WebPIDecoder { + DecState state_; // current decoding state + WebPDecParams params_; // Params to store output info + int is_lossless_; // for down-casting 'dec_'. + void* dec_; // either a VP8Decoder or a VP8LDecoder instance + VP8Io io_; + + MemBuffer mem_; // input memory buffer. + WebPDecBuffer output_; // output buffer (when no external one is supplied, + // or if the external one has slow-memory) + WebPDecBuffer* final_output_; // Slow-memory output to copy to eventually. + size_t chunk_size_; // Compressed VP8/VP8L size extracted from Header. + + int last_mb_y_; // last row reached for intra-mode decoding +}; + +// MB context to restore in case VP8DecodeMB() fails +typedef struct { + VP8MB left_; + VP8MB info_; + VP8BitReader token_br_; +} MBContext; + +//------------------------------------------------------------------------------ +// MemBuffer: incoming data handling + +static WEBP_INLINE size_t MemDataSize(const MemBuffer* mem) { + return (mem->end_ - mem->start_); +} + +// Check if we need to preserve the compressed alpha data, as it may not have +// been decoded yet. +static int NeedCompressedAlpha(const WebPIDecoder* const idec) { + if (idec->state_ == STATE_WEBP_HEADER) { + // We haven't parsed the headers yet, so we don't know whether the image is + // lossy or lossless. This also means that we haven't parsed the ALPH chunk. + return 0; + } + if (idec->is_lossless_) { + return 0; // ALPH chunk is not present for lossless images. + } else { + const VP8Decoder* const dec = (VP8Decoder*)idec->dec_; + assert(dec != NULL); // Must be true as idec->state_ != STATE_WEBP_HEADER. + return (dec->alpha_data_ != NULL) && !dec->is_alpha_decoded_; + } +} + +static void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) { + MemBuffer* const mem = &idec->mem_; + const uint8_t* const new_base = mem->buf_ + mem->start_; + // note: for VP8, setting up idec->io_ is only really needed at the beginning + // of the decoding, till partition #0 is complete. + idec->io_.data = new_base; + idec->io_.data_size = MemDataSize(mem); + + if (idec->dec_ != NULL) { + if (!idec->is_lossless_) { + VP8Decoder* const dec = (VP8Decoder*)idec->dec_; + const uint32_t last_part = dec->num_parts_minus_one_; + if (offset != 0) { + uint32_t p; + for (p = 0; p <= last_part; ++p) { + VP8RemapBitReader(dec->parts_ + p, offset); + } + // Remap partition #0 data pointer to new offset, but only in MAP + // mode (in APPEND mode, partition #0 is copied into a fixed memory). + if (mem->mode_ == MEM_MODE_MAP) { + VP8RemapBitReader(&dec->br_, offset); + } + } + { + const uint8_t* const last_start = dec->parts_[last_part].buf_; + VP8BitReaderSetBuffer(&dec->parts_[last_part], last_start, + mem->buf_ + mem->end_ - last_start); + } + if (NeedCompressedAlpha(idec)) { + ALPHDecoder* const alph_dec = dec->alph_dec_; + dec->alpha_data_ += offset; + if (alph_dec != NULL && alph_dec->vp8l_dec_ != NULL) { + if (alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION) { + VP8LDecoder* const alph_vp8l_dec = alph_dec->vp8l_dec_; + assert(dec->alpha_data_size_ >= ALPHA_HEADER_LEN); + VP8LBitReaderSetBuffer(&alph_vp8l_dec->br_, + dec->alpha_data_ + ALPHA_HEADER_LEN, + dec->alpha_data_size_ - ALPHA_HEADER_LEN); + } else { // alph_dec->method_ == ALPHA_NO_COMPRESSION + // Nothing special to do in this case. + } + } + } + } else { // Resize lossless bitreader + VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_; + VP8LBitReaderSetBuffer(&dec->br_, new_base, MemDataSize(mem)); + } + } +} + +// Appends data to the end of MemBuffer->buf_. It expands the allocated memory +// size if required and also updates VP8BitReader's if new memory is allocated. +static int AppendToMemBuffer(WebPIDecoder* const idec, + const uint8_t* const data, size_t data_size) { + VP8Decoder* const dec = (VP8Decoder*)idec->dec_; + MemBuffer* const mem = &idec->mem_; + const int need_compressed_alpha = NeedCompressedAlpha(idec); + const uint8_t* const old_start = + (mem->buf_ == NULL) ? NULL : mem->buf_ + mem->start_; + const uint8_t* const old_base = + need_compressed_alpha ? dec->alpha_data_ : old_start; + assert(mem->buf_ != NULL || mem->start_ == 0); + assert(mem->mode_ == MEM_MODE_APPEND); + if (data_size > MAX_CHUNK_PAYLOAD) { + // security safeguard: trying to allocate more than what the format + // allows for a chunk should be considered a smoke smell. + return 0; + } + + if (mem->end_ + data_size > mem->buf_size_) { // Need some free memory + const size_t new_mem_start = old_start - old_base; + const size_t current_size = MemDataSize(mem) + new_mem_start; + const uint64_t new_size = (uint64_t)current_size + data_size; + const uint64_t extra_size = (new_size + CHUNK_SIZE - 1) & ~(CHUNK_SIZE - 1); + uint8_t* const new_buf = + (uint8_t*)WebPSafeMalloc(extra_size, sizeof(*new_buf)); + if (new_buf == NULL) return 0; + if (old_base != NULL) memcpy(new_buf, old_base, current_size); + WebPSafeFree(mem->buf_); + mem->buf_ = new_buf; + mem->buf_size_ = (size_t)extra_size; + mem->start_ = new_mem_start; + mem->end_ = current_size; + } + + assert(mem->buf_ != NULL); + memcpy(mem->buf_ + mem->end_, data, data_size); + mem->end_ += data_size; + assert(mem->end_ <= mem->buf_size_); + + DoRemap(idec, mem->buf_ + mem->start_ - old_start); + return 1; +} + +static int RemapMemBuffer(WebPIDecoder* const idec, + const uint8_t* const data, size_t data_size) { + MemBuffer* const mem = &idec->mem_; + const uint8_t* const old_buf = mem->buf_; + const uint8_t* const old_start = + (old_buf == NULL) ? NULL : old_buf + mem->start_; + assert(old_buf != NULL || mem->start_ == 0); + assert(mem->mode_ == MEM_MODE_MAP); + + if (data_size < mem->buf_size_) return 0; // can't remap to a shorter buffer! + + mem->buf_ = (uint8_t*)data; + mem->end_ = mem->buf_size_ = data_size; + + DoRemap(idec, mem->buf_ + mem->start_ - old_start); + return 1; +} + +static void InitMemBuffer(MemBuffer* const mem) { + mem->mode_ = MEM_MODE_NONE; + mem->buf_ = NULL; + mem->buf_size_ = 0; + mem->part0_buf_ = NULL; + mem->part0_size_ = 0; +} + +static void ClearMemBuffer(MemBuffer* const mem) { + assert(mem); + if (mem->mode_ == MEM_MODE_APPEND) { + WebPSafeFree(mem->buf_); + WebPSafeFree((void*)mem->part0_buf_); + } +} + +static int CheckMemBufferMode(MemBuffer* const mem, MemBufferMode expected) { + if (mem->mode_ == MEM_MODE_NONE) { + mem->mode_ = expected; // switch to the expected mode + } else if (mem->mode_ != expected) { + return 0; // we mixed the modes => error + } + assert(mem->mode_ == expected); // mode is ok + return 1; +} + +// To be called last. +static VP8StatusCode FinishDecoding(WebPIDecoder* const idec) { + const WebPDecoderOptions* const options = idec->params_.options; + WebPDecBuffer* const output = idec->params_.output; + + idec->state_ = STATE_DONE; + if (options != NULL && options->flip) { + const VP8StatusCode status = WebPFlipBuffer(output); + if (status != VP8_STATUS_OK) return status; + } + if (idec->final_output_ != NULL) { + WebPCopyDecBufferPixels(output, idec->final_output_); // do the slow-copy + WebPFreeDecBuffer(&idec->output_); + *output = *idec->final_output_; + idec->final_output_ = NULL; + } + return VP8_STATUS_OK; +} + +//------------------------------------------------------------------------------ +// Macroblock-decoding contexts + +static void SaveContext(const VP8Decoder* dec, const VP8BitReader* token_br, + MBContext* const context) { + context->left_ = dec->mb_info_[-1]; + context->info_ = dec->mb_info_[dec->mb_x_]; + context->token_br_ = *token_br; +} + +static void RestoreContext(const MBContext* context, VP8Decoder* const dec, + VP8BitReader* const token_br) { + dec->mb_info_[-1] = context->left_; + dec->mb_info_[dec->mb_x_] = context->info_; + *token_br = context->token_br_; +} + +//------------------------------------------------------------------------------ + +static VP8StatusCode IDecError(WebPIDecoder* const idec, VP8StatusCode error) { + if (idec->state_ == STATE_VP8_DATA) { + // Synchronize the thread, clean-up and check for errors. + VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_); + } + idec->state_ = STATE_ERROR; + return error; +} + +static void ChangeState(WebPIDecoder* const idec, DecState new_state, + size_t consumed_bytes) { + MemBuffer* const mem = &idec->mem_; + idec->state_ = new_state; + mem->start_ += consumed_bytes; + assert(mem->start_ <= mem->end_); + idec->io_.data = mem->buf_ + mem->start_; + idec->io_.data_size = MemDataSize(mem); +} + +// Headers +static VP8StatusCode DecodeWebPHeaders(WebPIDecoder* const idec) { + MemBuffer* const mem = &idec->mem_; + const uint8_t* data = mem->buf_ + mem->start_; + size_t curr_size = MemDataSize(mem); + VP8StatusCode status; + WebPHeaderStructure headers; + + headers.data = data; + headers.data_size = curr_size; + headers.have_all_data = 0; + status = WebPParseHeaders(&headers); + if (status == VP8_STATUS_NOT_ENOUGH_DATA) { + return VP8_STATUS_SUSPENDED; // We haven't found a VP8 chunk yet. + } else if (status != VP8_STATUS_OK) { + return IDecError(idec, status); + } + + idec->chunk_size_ = headers.compressed_size; + idec->is_lossless_ = headers.is_lossless; + if (!idec->is_lossless_) { + VP8Decoder* const dec = VP8New(); + if (dec == NULL) { + return VP8_STATUS_OUT_OF_MEMORY; + } + idec->dec_ = dec; + dec->alpha_data_ = headers.alpha_data; + dec->alpha_data_size_ = headers.alpha_data_size; + ChangeState(idec, STATE_VP8_HEADER, headers.offset); + } else { + VP8LDecoder* const dec = VP8LNew(); + if (dec == NULL) { + return VP8_STATUS_OUT_OF_MEMORY; + } + idec->dec_ = dec; + ChangeState(idec, STATE_VP8L_HEADER, headers.offset); + } + return VP8_STATUS_OK; +} + +static VP8StatusCode DecodeVP8FrameHeader(WebPIDecoder* const idec) { + const uint8_t* data = idec->mem_.buf_ + idec->mem_.start_; + const size_t curr_size = MemDataSize(&idec->mem_); + int width, height; + uint32_t bits; + + if (curr_size < VP8_FRAME_HEADER_SIZE) { + // Not enough data bytes to extract VP8 Frame Header. + return VP8_STATUS_SUSPENDED; + } + if (!VP8GetInfo(data, curr_size, idec->chunk_size_, &width, &height)) { + return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); + } + + bits = data[0] | (data[1] << 8) | (data[2] << 16); + idec->mem_.part0_size_ = (bits >> 5) + VP8_FRAME_HEADER_SIZE; + + idec->io_.data = data; + idec->io_.data_size = curr_size; + idec->state_ = STATE_VP8_PARTS0; + return VP8_STATUS_OK; +} + +// Partition #0 +static VP8StatusCode CopyParts0Data(WebPIDecoder* const idec) { + VP8Decoder* const dec = (VP8Decoder*)idec->dec_; + VP8BitReader* const br = &dec->br_; + const size_t part_size = br->buf_end_ - br->buf_; + MemBuffer* const mem = &idec->mem_; + assert(!idec->is_lossless_); + assert(mem->part0_buf_ == NULL); + // the following is a format limitation, no need for runtime check: + assert(part_size <= mem->part0_size_); + if (part_size == 0) { // can't have zero-size partition #0 + return VP8_STATUS_BITSTREAM_ERROR; + } + if (mem->mode_ == MEM_MODE_APPEND) { + // We copy and grab ownership of the partition #0 data. + uint8_t* const part0_buf = (uint8_t*)WebPSafeMalloc(1ULL, part_size); + if (part0_buf == NULL) { + return VP8_STATUS_OUT_OF_MEMORY; + } + memcpy(part0_buf, br->buf_, part_size); + mem->part0_buf_ = part0_buf; + VP8BitReaderSetBuffer(br, part0_buf, part_size); + } else { + // Else: just keep pointers to the partition #0's data in dec_->br_. + } + mem->start_ += part_size; + return VP8_STATUS_OK; +} + +static VP8StatusCode DecodePartition0(WebPIDecoder* const idec) { + VP8Decoder* const dec = (VP8Decoder*)idec->dec_; + VP8Io* const io = &idec->io_; + const WebPDecParams* const params = &idec->params_; + WebPDecBuffer* const output = params->output; + + // Wait till we have enough data for the whole partition #0 + if (MemDataSize(&idec->mem_) < idec->mem_.part0_size_) { + return VP8_STATUS_SUSPENDED; + } + + if (!VP8GetHeaders(dec, io)) { + const VP8StatusCode status = dec->status_; + if (status == VP8_STATUS_SUSPENDED || + status == VP8_STATUS_NOT_ENOUGH_DATA) { + // treating NOT_ENOUGH_DATA as SUSPENDED state + return VP8_STATUS_SUSPENDED; + } + return IDecError(idec, status); + } + + // Allocate/Verify output buffer now + dec->status_ = WebPAllocateDecBuffer(io->width, io->height, params->options, + output); + if (dec->status_ != VP8_STATUS_OK) { + return IDecError(idec, dec->status_); + } + // This change must be done before calling VP8InitFrame() + dec->mt_method_ = VP8GetThreadMethod(params->options, NULL, + io->width, io->height); + VP8InitDithering(params->options, dec); + + dec->status_ = CopyParts0Data(idec); + if (dec->status_ != VP8_STATUS_OK) { + return IDecError(idec, dec->status_); + } + + // Finish setting up the decoding parameters. Will call io->setup(). + if (VP8EnterCritical(dec, io) != VP8_STATUS_OK) { + return IDecError(idec, dec->status_); + } + + // Note: past this point, teardown() must always be called + // in case of error. + idec->state_ = STATE_VP8_DATA; + // Allocate memory and prepare everything. + if (!VP8InitFrame(dec, io)) { + return IDecError(idec, dec->status_); + } + return VP8_STATUS_OK; +} + +// Remaining partitions +static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) { + VP8Decoder* const dec = (VP8Decoder*)idec->dec_; + VP8Io* const io = &idec->io_; + + // Make sure partition #0 has been read before, to set dec to ready_. + if (!dec->ready_) { + return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); + } + for (; dec->mb_y_ < dec->mb_h_; ++dec->mb_y_) { + if (idec->last_mb_y_ != dec->mb_y_) { + if (!VP8ParseIntraModeRow(&dec->br_, dec)) { + // note: normally, error shouldn't occur since we already have the whole + // partition0 available here in DecodeRemaining(). Reaching EOF while + // reading intra modes really means a BITSTREAM_ERROR. + return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); + } + idec->last_mb_y_ = dec->mb_y_; + } + for (; dec->mb_x_ < dec->mb_w_; ++dec->mb_x_) { + VP8BitReader* const token_br = + &dec->parts_[dec->mb_y_ & dec->num_parts_minus_one_]; + MBContext context; + SaveContext(dec, token_br, &context); + if (!VP8DecodeMB(dec, token_br)) { + // We shouldn't fail when MAX_MB data was available + if (dec->num_parts_minus_one_ == 0 && + MemDataSize(&idec->mem_) > MAX_MB_SIZE) { + return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); + } + // Synchronize the threads. + if (dec->mt_method_ > 0) { + if (!WebPGetWorkerInterface()->Sync(&dec->worker_)) { + return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); + } + } + RestoreContext(&context, dec, token_br); + return VP8_STATUS_SUSPENDED; + } + // Release buffer only if there is only one partition + if (dec->num_parts_minus_one_ == 0) { + idec->mem_.start_ = token_br->buf_ - idec->mem_.buf_; + assert(idec->mem_.start_ <= idec->mem_.end_); + } + } + VP8InitScanline(dec); // Prepare for next scanline + + // Reconstruct, filter and emit the row. + if (!VP8ProcessRow(dec, io)) { + return IDecError(idec, VP8_STATUS_USER_ABORT); + } + } + // Synchronize the thread and check for errors. + if (!VP8ExitCritical(dec, io)) { + idec->state_ = STATE_ERROR; // prevent re-entry in IDecError + return IDecError(idec, VP8_STATUS_USER_ABORT); + } + dec->ready_ = 0; + return FinishDecoding(idec); +} + +static VP8StatusCode ErrorStatusLossless(WebPIDecoder* const idec, + VP8StatusCode status) { + if (status == VP8_STATUS_SUSPENDED || status == VP8_STATUS_NOT_ENOUGH_DATA) { + return VP8_STATUS_SUSPENDED; + } + return IDecError(idec, status); +} + +static VP8StatusCode DecodeVP8LHeader(WebPIDecoder* const idec) { + VP8Io* const io = &idec->io_; + VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_; + const WebPDecParams* const params = &idec->params_; + WebPDecBuffer* const output = params->output; + size_t curr_size = MemDataSize(&idec->mem_); + assert(idec->is_lossless_); + + // Wait until there's enough data for decoding header. + if (curr_size < (idec->chunk_size_ >> 3)) { + dec->status_ = VP8_STATUS_SUSPENDED; + return ErrorStatusLossless(idec, dec->status_); + } + + if (!VP8LDecodeHeader(dec, io)) { + if (dec->status_ == VP8_STATUS_BITSTREAM_ERROR && + curr_size < idec->chunk_size_) { + dec->status_ = VP8_STATUS_SUSPENDED; + } + return ErrorStatusLossless(idec, dec->status_); + } + // Allocate/verify output buffer now. + dec->status_ = WebPAllocateDecBuffer(io->width, io->height, params->options, + output); + if (dec->status_ != VP8_STATUS_OK) { + return IDecError(idec, dec->status_); + } + + idec->state_ = STATE_VP8L_DATA; + return VP8_STATUS_OK; +} + +static VP8StatusCode DecodeVP8LData(WebPIDecoder* const idec) { + VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_; + const size_t curr_size = MemDataSize(&idec->mem_); + assert(idec->is_lossless_); + + // Switch to incremental decoding if we don't have all the bytes available. + dec->incremental_ = (curr_size < idec->chunk_size_); + + if (!VP8LDecodeImage(dec)) { + return ErrorStatusLossless(idec, dec->status_); + } + assert(dec->status_ == VP8_STATUS_OK || dec->status_ == VP8_STATUS_SUSPENDED); + return (dec->status_ == VP8_STATUS_SUSPENDED) ? dec->status_ + : FinishDecoding(idec); +} + + // Main decoding loop +static VP8StatusCode IDecode(WebPIDecoder* idec) { + VP8StatusCode status = VP8_STATUS_SUSPENDED; + + if (idec->state_ == STATE_WEBP_HEADER) { + status = DecodeWebPHeaders(idec); + } else { + if (idec->dec_ == NULL) { + return VP8_STATUS_SUSPENDED; // can't continue if we have no decoder. + } + } + if (idec->state_ == STATE_VP8_HEADER) { + status = DecodeVP8FrameHeader(idec); + } + if (idec->state_ == STATE_VP8_PARTS0) { + status = DecodePartition0(idec); + } + if (idec->state_ == STATE_VP8_DATA) { + const VP8Decoder* const dec = (VP8Decoder*)idec->dec_; + if (dec == NULL) { + return VP8_STATUS_SUSPENDED; // can't continue if we have no decoder. + } + status = DecodeRemaining(idec); + } + if (idec->state_ == STATE_VP8L_HEADER) { + status = DecodeVP8LHeader(idec); + } + if (idec->state_ == STATE_VP8L_DATA) { + status = DecodeVP8LData(idec); + } + return status; +} + +//------------------------------------------------------------------------------ +// Internal constructor + +static WebPIDecoder* NewDecoder(WebPDecBuffer* const output_buffer, + const WebPBitstreamFeatures* const features) { + WebPIDecoder* idec = (WebPIDecoder*)WebPSafeCalloc(1ULL, sizeof(*idec)); + if (idec == NULL) { + return NULL; + } + + idec->state_ = STATE_WEBP_HEADER; + idec->chunk_size_ = 0; + + idec->last_mb_y_ = -1; + + InitMemBuffer(&idec->mem_); + WebPInitDecBuffer(&idec->output_); + VP8InitIo(&idec->io_); + + WebPResetDecParams(&idec->params_); + if (output_buffer == NULL || WebPAvoidSlowMemory(output_buffer, features)) { + idec->params_.output = &idec->output_; + idec->final_output_ = output_buffer; + if (output_buffer != NULL) { + idec->params_.output->colorspace = output_buffer->colorspace; + } + } else { + idec->params_.output = output_buffer; + idec->final_output_ = NULL; + } + WebPInitCustomIo(&idec->params_, &idec->io_); // Plug the I/O functions. + + return idec; +} + +//------------------------------------------------------------------------------ +// Public functions + +WebPIDecoder* WebPINewDecoder(WebPDecBuffer* output_buffer) { + return NewDecoder(output_buffer, NULL); +} + +WebPIDecoder* WebPIDecode(const uint8_t* data, size_t data_size, + WebPDecoderConfig* config) { + WebPIDecoder* idec; + WebPBitstreamFeatures tmp_features; + WebPBitstreamFeatures* const features = + (config == NULL) ? &tmp_features : &config->input; + memset(&tmp_features, 0, sizeof(tmp_features)); + + // Parse the bitstream's features, if requested: + if (data != NULL && data_size > 0) { + if (WebPGetFeatures(data, data_size, features) != VP8_STATUS_OK) { + return NULL; + } + } + + // Create an instance of the incremental decoder + idec = (config != NULL) ? NewDecoder(&config->output, features) + : NewDecoder(NULL, features); + if (idec == NULL) { + return NULL; + } + // Finish initialization + if (config != NULL) { + idec->params_.options = &config->options; + } + return idec; +} + +void WebPIDelete(WebPIDecoder* idec) { + if (idec == NULL) return; + if (idec->dec_ != NULL) { + if (!idec->is_lossless_) { + if (idec->state_ == STATE_VP8_DATA) { + // Synchronize the thread, clean-up and check for errors. + VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_); + } + VP8Delete((VP8Decoder*)idec->dec_); + } else { + VP8LDelete((VP8LDecoder*)idec->dec_); + } + } + ClearMemBuffer(&idec->mem_); + WebPFreeDecBuffer(&idec->output_); + WebPSafeFree(idec); +} + +//------------------------------------------------------------------------------ +// Wrapper toward WebPINewDecoder + +WebPIDecoder* WebPINewRGB(WEBP_CSP_MODE csp, uint8_t* output_buffer, + size_t output_buffer_size, int output_stride) { + const int is_external_memory = (output_buffer != NULL) ? 1 : 0; + WebPIDecoder* idec; + + if (csp >= MODE_YUV) return NULL; + if (is_external_memory == 0) { // Overwrite parameters to sane values. + output_buffer_size = 0; + output_stride = 0; + } else { // A buffer was passed. Validate the other params. + if (output_stride == 0 || output_buffer_size == 0) { + return NULL; // invalid parameter. + } + } + idec = WebPINewDecoder(NULL); + if (idec == NULL) return NULL; + idec->output_.colorspace = csp; + idec->output_.is_external_memory = is_external_memory; + idec->output_.u.RGBA.rgba = output_buffer; + idec->output_.u.RGBA.stride = output_stride; + idec->output_.u.RGBA.size = output_buffer_size; + return idec; +} + +WebPIDecoder* WebPINewYUVA(uint8_t* luma, size_t luma_size, int luma_stride, + uint8_t* u, size_t u_size, int u_stride, + uint8_t* v, size_t v_size, int v_stride, + uint8_t* a, size_t a_size, int a_stride) { + const int is_external_memory = (luma != NULL) ? 1 : 0; + WebPIDecoder* idec; + WEBP_CSP_MODE colorspace; + + if (is_external_memory == 0) { // Overwrite parameters to sane values. + luma_size = u_size = v_size = a_size = 0; + luma_stride = u_stride = v_stride = a_stride = 0; + u = v = a = NULL; + colorspace = MODE_YUVA; + } else { // A luma buffer was passed. Validate the other parameters. + if (u == NULL || v == NULL) return NULL; + if (luma_size == 0 || u_size == 0 || v_size == 0) return NULL; + if (luma_stride == 0 || u_stride == 0 || v_stride == 0) return NULL; + if (a != NULL) { + if (a_size == 0 || a_stride == 0) return NULL; + } + colorspace = (a == NULL) ? MODE_YUV : MODE_YUVA; + } + + idec = WebPINewDecoder(NULL); + if (idec == NULL) return NULL; + + idec->output_.colorspace = colorspace; + idec->output_.is_external_memory = is_external_memory; + idec->output_.u.YUVA.y = luma; + idec->output_.u.YUVA.y_stride = luma_stride; + idec->output_.u.YUVA.y_size = luma_size; + idec->output_.u.YUVA.u = u; + idec->output_.u.YUVA.u_stride = u_stride; + idec->output_.u.YUVA.u_size = u_size; + idec->output_.u.YUVA.v = v; + idec->output_.u.YUVA.v_stride = v_stride; + idec->output_.u.YUVA.v_size = v_size; + idec->output_.u.YUVA.a = a; + idec->output_.u.YUVA.a_stride = a_stride; + idec->output_.u.YUVA.a_size = a_size; + return idec; +} + +WebPIDecoder* WebPINewYUV(uint8_t* luma, size_t luma_size, int luma_stride, + uint8_t* u, size_t u_size, int u_stride, + uint8_t* v, size_t v_size, int v_stride) { + return WebPINewYUVA(luma, luma_size, luma_stride, + u, u_size, u_stride, + v, v_size, v_stride, + NULL, 0, 0); +} + +//------------------------------------------------------------------------------ + +static VP8StatusCode IDecCheckStatus(const WebPIDecoder* const idec) { + assert(idec); + if (idec->state_ == STATE_ERROR) { + return VP8_STATUS_BITSTREAM_ERROR; + } + if (idec->state_ == STATE_DONE) { + return VP8_STATUS_OK; + } + return VP8_STATUS_SUSPENDED; +} + +VP8StatusCode WebPIAppend(WebPIDecoder* idec, + const uint8_t* data, size_t data_size) { + VP8StatusCode status; + if (idec == NULL || data == NULL) { + return VP8_STATUS_INVALID_PARAM; + } + status = IDecCheckStatus(idec); + if (status != VP8_STATUS_SUSPENDED) { + return status; + } + // Check mixed calls between RemapMemBuffer and AppendToMemBuffer. + if (!CheckMemBufferMode(&idec->mem_, MEM_MODE_APPEND)) { + return VP8_STATUS_INVALID_PARAM; + } + // Append data to memory buffer + if (!AppendToMemBuffer(idec, data, data_size)) { + return VP8_STATUS_OUT_OF_MEMORY; + } + return IDecode(idec); +} + +VP8StatusCode WebPIUpdate(WebPIDecoder* idec, + const uint8_t* data, size_t data_size) { + VP8StatusCode status; + if (idec == NULL || data == NULL) { + return VP8_STATUS_INVALID_PARAM; + } + status = IDecCheckStatus(idec); + if (status != VP8_STATUS_SUSPENDED) { + return status; + } + // Check mixed calls between RemapMemBuffer and AppendToMemBuffer. + if (!CheckMemBufferMode(&idec->mem_, MEM_MODE_MAP)) { + return VP8_STATUS_INVALID_PARAM; + } + // Make the memory buffer point to the new buffer + if (!RemapMemBuffer(idec, data, data_size)) { + return VP8_STATUS_INVALID_PARAM; + } + return IDecode(idec); +} + +//------------------------------------------------------------------------------ + +static const WebPDecBuffer* GetOutputBuffer(const WebPIDecoder* const idec) { + if (idec == NULL || idec->dec_ == NULL) { + return NULL; + } + if (idec->state_ <= STATE_VP8_PARTS0) { + return NULL; + } + if (idec->final_output_ != NULL) { + return NULL; // not yet slow-copied + } + return idec->params_.output; +} + +const WebPDecBuffer* WebPIDecodedArea(const WebPIDecoder* idec, + int* left, int* top, + int* width, int* height) { + const WebPDecBuffer* const src = GetOutputBuffer(idec); + if (left != NULL) *left = 0; + if (top != NULL) *top = 0; + if (src != NULL) { + if (width != NULL) *width = src->width; + if (height != NULL) *height = idec->params_.last_y; + } else { + if (width != NULL) *width = 0; + if (height != NULL) *height = 0; + } + return src; +} + +uint8_t* WebPIDecGetRGB(const WebPIDecoder* idec, int* last_y, + int* width, int* height, int* stride) { + const WebPDecBuffer* const src = GetOutputBuffer(idec); + if (src == NULL) return NULL; + if (src->colorspace >= MODE_YUV) { + return NULL; + } + + if (last_y != NULL) *last_y = idec->params_.last_y; + if (width != NULL) *width = src->width; + if (height != NULL) *height = src->height; + if (stride != NULL) *stride = src->u.RGBA.stride; + + return src->u.RGBA.rgba; +} + +uint8_t* WebPIDecGetYUVA(const WebPIDecoder* idec, int* last_y, + uint8_t** u, uint8_t** v, uint8_t** a, + int* width, int* height, + int* stride, int* uv_stride, int* a_stride) { + const WebPDecBuffer* const src = GetOutputBuffer(idec); + if (src == NULL) return NULL; + if (src->colorspace < MODE_YUV) { + return NULL; + } + + if (last_y != NULL) *last_y = idec->params_.last_y; + if (u != NULL) *u = src->u.YUVA.u; + if (v != NULL) *v = src->u.YUVA.v; + if (a != NULL) *a = src->u.YUVA.a; + if (width != NULL) *width = src->width; + if (height != NULL) *height = src->height; + if (stride != NULL) *stride = src->u.YUVA.y_stride; + if (uv_stride != NULL) *uv_stride = src->u.YUVA.u_stride; + if (a_stride != NULL) *a_stride = src->u.YUVA.a_stride; + + return src->u.YUVA.y; +} + +int WebPISetIOHooks(WebPIDecoder* const idec, + VP8IoPutHook put, + VP8IoSetupHook setup, + VP8IoTeardownHook teardown, + void* user_data) { + if (idec == NULL || idec->state_ > STATE_WEBP_HEADER) { + return 0; + } + + idec->io_.put = put; + idec->io_.setup = setup; + idec->io_.teardown = teardown; + idec->io_.opaque = user_data; + + return 1; +} diff --git a/third-party/webp/libwebp/src/dec/io_dec.c b/third-party/webp/libwebp/src/dec/io_dec.c new file mode 100644 index 0000000000..5ef6298886 --- /dev/null +++ b/third-party/webp/libwebp/src/dec/io_dec.c @@ -0,0 +1,662 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// functions for sample output. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include +#include "src/dec/vp8i_dec.h" +#include "src/dec/webpi_dec.h" +#include "src/dsp/dsp.h" +#include "src/dsp/yuv.h" +#include "src/utils/utils.h" + +//------------------------------------------------------------------------------ +// Main YUV<->RGB conversion functions + +static int EmitYUV(const VP8Io* const io, WebPDecParams* const p) { + WebPDecBuffer* output = p->output; + const WebPYUVABuffer* const buf = &output->u.YUVA; + uint8_t* const y_dst = buf->y + (size_t)io->mb_y * buf->y_stride; + uint8_t* const u_dst = buf->u + (size_t)(io->mb_y >> 1) * buf->u_stride; + uint8_t* const v_dst = buf->v + (size_t)(io->mb_y >> 1) * buf->v_stride; + const int mb_w = io->mb_w; + const int mb_h = io->mb_h; + const int uv_w = (mb_w + 1) / 2; + const int uv_h = (mb_h + 1) / 2; + WebPCopyPlane(io->y, io->y_stride, y_dst, buf->y_stride, mb_w, mb_h); + WebPCopyPlane(io->u, io->uv_stride, u_dst, buf->u_stride, uv_w, uv_h); + WebPCopyPlane(io->v, io->uv_stride, v_dst, buf->v_stride, uv_w, uv_h); + return io->mb_h; +} + +// Point-sampling U/V sampler. +static int EmitSampledRGB(const VP8Io* const io, WebPDecParams* const p) { + WebPDecBuffer* const output = p->output; + WebPRGBABuffer* const buf = &output->u.RGBA; + uint8_t* const dst = buf->rgba + (size_t)io->mb_y * buf->stride; + WebPSamplerProcessPlane(io->y, io->y_stride, + io->u, io->v, io->uv_stride, + dst, buf->stride, io->mb_w, io->mb_h, + WebPSamplers[output->colorspace]); + return io->mb_h; +} + +//------------------------------------------------------------------------------ +// Fancy upsampling + +#ifdef FANCY_UPSAMPLING +static int EmitFancyRGB(const VP8Io* const io, WebPDecParams* const p) { + int num_lines_out = io->mb_h; // a priori guess + const WebPRGBABuffer* const buf = &p->output->u.RGBA; + uint8_t* dst = buf->rgba + (size_t)io->mb_y * buf->stride; + WebPUpsampleLinePairFunc upsample = WebPUpsamplers[p->output->colorspace]; + const uint8_t* cur_y = io->y; + const uint8_t* cur_u = io->u; + const uint8_t* cur_v = io->v; + const uint8_t* top_u = p->tmp_u; + const uint8_t* top_v = p->tmp_v; + int y = io->mb_y; + const int y_end = io->mb_y + io->mb_h; + const int mb_w = io->mb_w; + const int uv_w = (mb_w + 1) / 2; + + if (y == 0) { + // First line is special cased. We mirror the u/v samples at boundary. + upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, mb_w); + } else { + // We can finish the left-over line from previous call. + upsample(p->tmp_y, cur_y, top_u, top_v, cur_u, cur_v, + dst - buf->stride, dst, mb_w); + ++num_lines_out; + } + // Loop over each output pairs of row. + for (; y + 2 < y_end; y += 2) { + top_u = cur_u; + top_v = cur_v; + cur_u += io->uv_stride; + cur_v += io->uv_stride; + dst += 2 * buf->stride; + cur_y += 2 * io->y_stride; + upsample(cur_y - io->y_stride, cur_y, + top_u, top_v, cur_u, cur_v, + dst - buf->stride, dst, mb_w); + } + // move to last row + cur_y += io->y_stride; + if (io->crop_top + y_end < io->crop_bottom) { + // Save the unfinished samples for next call (as we're not done yet). + memcpy(p->tmp_y, cur_y, mb_w * sizeof(*p->tmp_y)); + memcpy(p->tmp_u, cur_u, uv_w * sizeof(*p->tmp_u)); + memcpy(p->tmp_v, cur_v, uv_w * sizeof(*p->tmp_v)); + // The fancy upsampler leaves a row unfinished behind + // (except for the very last row) + num_lines_out--; + } else { + // Process the very last row of even-sized picture + if (!(y_end & 1)) { + upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, + dst + buf->stride, NULL, mb_w); + } + } + return num_lines_out; +} + +#endif /* FANCY_UPSAMPLING */ + +//------------------------------------------------------------------------------ + +static void FillAlphaPlane(uint8_t* dst, int w, int h, int stride) { + int j; + for (j = 0; j < h; ++j) { + memset(dst, 0xff, w * sizeof(*dst)); + dst += stride; + } +} + +static int EmitAlphaYUV(const VP8Io* const io, WebPDecParams* const p, + int expected_num_lines_out) { + const uint8_t* alpha = io->a; + const WebPYUVABuffer* const buf = &p->output->u.YUVA; + const int mb_w = io->mb_w; + const int mb_h = io->mb_h; + uint8_t* dst = buf->a + (size_t)io->mb_y * buf->a_stride; + int j; + (void)expected_num_lines_out; + assert(expected_num_lines_out == mb_h); + if (alpha != NULL) { + for (j = 0; j < mb_h; ++j) { + memcpy(dst, alpha, mb_w * sizeof(*dst)); + alpha += io->width; + dst += buf->a_stride; + } + } else if (buf->a != NULL) { + // the user requested alpha, but there is none, set it to opaque. + FillAlphaPlane(dst, mb_w, mb_h, buf->a_stride); + } + return 0; +} + +static int GetAlphaSourceRow(const VP8Io* const io, + const uint8_t** alpha, int* const num_rows) { + int start_y = io->mb_y; + *num_rows = io->mb_h; + + // Compensate for the 1-line delay of the fancy upscaler. + // This is similar to EmitFancyRGB(). + if (io->fancy_upsampling) { + if (start_y == 0) { + // We don't process the last row yet. It'll be done during the next call. + --*num_rows; + } else { + --start_y; + // Fortunately, *alpha data is persistent, so we can go back + // one row and finish alpha blending, now that the fancy upscaler + // completed the YUV->RGB interpolation. + *alpha -= io->width; + } + if (io->crop_top + io->mb_y + io->mb_h == io->crop_bottom) { + // If it's the very last call, we process all the remaining rows! + *num_rows = io->crop_bottom - io->crop_top - start_y; + } + } + return start_y; +} + +static int EmitAlphaRGB(const VP8Io* const io, WebPDecParams* const p, + int expected_num_lines_out) { + const uint8_t* alpha = io->a; + if (alpha != NULL) { + const int mb_w = io->mb_w; + const WEBP_CSP_MODE colorspace = p->output->colorspace; + const int alpha_first = + (colorspace == MODE_ARGB || colorspace == MODE_Argb); + const WebPRGBABuffer* const buf = &p->output->u.RGBA; + int num_rows; + const size_t start_y = GetAlphaSourceRow(io, &alpha, &num_rows); + uint8_t* const base_rgba = buf->rgba + start_y * buf->stride; + uint8_t* const dst = base_rgba + (alpha_first ? 0 : 3); + const int has_alpha = WebPDispatchAlpha(alpha, io->width, mb_w, + num_rows, dst, buf->stride); + (void)expected_num_lines_out; + assert(expected_num_lines_out == num_rows); + // has_alpha is true if there's non-trivial alpha to premultiply with. + if (has_alpha && WebPIsPremultipliedMode(colorspace)) { + WebPApplyAlphaMultiply(base_rgba, alpha_first, + mb_w, num_rows, buf->stride); + } + } + return 0; +} + +static int EmitAlphaRGBA4444(const VP8Io* const io, WebPDecParams* const p, + int expected_num_lines_out) { + const uint8_t* alpha = io->a; + if (alpha != NULL) { + const int mb_w = io->mb_w; + const WEBP_CSP_MODE colorspace = p->output->colorspace; + const WebPRGBABuffer* const buf = &p->output->u.RGBA; + int num_rows; + const size_t start_y = GetAlphaSourceRow(io, &alpha, &num_rows); + uint8_t* const base_rgba = buf->rgba + start_y * buf->stride; +#if (WEBP_SWAP_16BIT_CSP == 1) + uint8_t* alpha_dst = base_rgba; +#else + uint8_t* alpha_dst = base_rgba + 1; +#endif + uint32_t alpha_mask = 0x0f; + int i, j; + for (j = 0; j < num_rows; ++j) { + for (i = 0; i < mb_w; ++i) { + // Fill in the alpha value (converted to 4 bits). + const uint32_t alpha_value = alpha[i] >> 4; + alpha_dst[2 * i] = (alpha_dst[2 * i] & 0xf0) | alpha_value; + alpha_mask &= alpha_value; + } + alpha += io->width; + alpha_dst += buf->stride; + } + (void)expected_num_lines_out; + assert(expected_num_lines_out == num_rows); + if (alpha_mask != 0x0f && WebPIsPremultipliedMode(colorspace)) { + WebPApplyAlphaMultiply4444(base_rgba, mb_w, num_rows, buf->stride); + } + } + return 0; +} + +//------------------------------------------------------------------------------ +// YUV rescaling (no final RGB conversion needed) + +#if !defined(WEBP_REDUCE_SIZE) +static int Rescale(const uint8_t* src, int src_stride, + int new_lines, WebPRescaler* const wrk) { + int num_lines_out = 0; + while (new_lines > 0) { // import new contributions of source rows. + const int lines_in = WebPRescalerImport(wrk, new_lines, src, src_stride); + src += lines_in * src_stride; + new_lines -= lines_in; + num_lines_out += WebPRescalerExport(wrk); // emit output row(s) + } + return num_lines_out; +} + +static int EmitRescaledYUV(const VP8Io* const io, WebPDecParams* const p) { + const int mb_h = io->mb_h; + const int uv_mb_h = (mb_h + 1) >> 1; + WebPRescaler* const scaler = p->scaler_y; + int num_lines_out = 0; + if (WebPIsAlphaMode(p->output->colorspace) && io->a != NULL) { + // Before rescaling, we premultiply the luma directly into the io->y + // internal buffer. This is OK since these samples are not used for + // intra-prediction (the top samples are saved in cache_y_/u_/v_). + // But we need to cast the const away, though. + WebPMultRows((uint8_t*)io->y, io->y_stride, + io->a, io->width, io->mb_w, mb_h, 0); + } + num_lines_out = Rescale(io->y, io->y_stride, mb_h, scaler); + Rescale(io->u, io->uv_stride, uv_mb_h, p->scaler_u); + Rescale(io->v, io->uv_stride, uv_mb_h, p->scaler_v); + return num_lines_out; +} + +static int EmitRescaledAlphaYUV(const VP8Io* const io, WebPDecParams* const p, + int expected_num_lines_out) { + const WebPYUVABuffer* const buf = &p->output->u.YUVA; + uint8_t* const dst_a = buf->a + (size_t)p->last_y * buf->a_stride; + if (io->a != NULL) { + uint8_t* const dst_y = buf->y + (size_t)p->last_y * buf->y_stride; + const int num_lines_out = Rescale(io->a, io->width, io->mb_h, p->scaler_a); + assert(expected_num_lines_out == num_lines_out); + if (num_lines_out > 0) { // unmultiply the Y + WebPMultRows(dst_y, buf->y_stride, dst_a, buf->a_stride, + p->scaler_a->dst_width, num_lines_out, 1); + } + } else if (buf->a != NULL) { + // the user requested alpha, but there is none, set it to opaque. + assert(p->last_y + expected_num_lines_out <= io->scaled_height); + FillAlphaPlane(dst_a, io->scaled_width, expected_num_lines_out, + buf->a_stride); + } + return 0; +} + +static int InitYUVRescaler(const VP8Io* const io, WebPDecParams* const p) { + const int has_alpha = WebPIsAlphaMode(p->output->colorspace); + const WebPYUVABuffer* const buf = &p->output->u.YUVA; + const int out_width = io->scaled_width; + const int out_height = io->scaled_height; + const int uv_out_width = (out_width + 1) >> 1; + const int uv_out_height = (out_height + 1) >> 1; + const int uv_in_width = (io->mb_w + 1) >> 1; + const int uv_in_height = (io->mb_h + 1) >> 1; + // scratch memory for luma rescaler + const size_t work_size = 2 * (size_t)out_width; + const size_t uv_work_size = 2 * uv_out_width; // and for each u/v ones + uint64_t total_size; + size_t rescaler_size; + rescaler_t* work; + WebPRescaler* scalers; + const int num_rescalers = has_alpha ? 4 : 3; + + total_size = ((uint64_t)work_size + 2 * uv_work_size) * sizeof(*work); + if (has_alpha) { + total_size += (uint64_t)work_size * sizeof(*work); + } + rescaler_size = num_rescalers * sizeof(*p->scaler_y) + WEBP_ALIGN_CST; + total_size += rescaler_size; + if (!CheckSizeOverflow(total_size)) { + return 0; + } + + p->memory = WebPSafeMalloc(1ULL, (size_t)total_size); + if (p->memory == NULL) { + return 0; // memory error + } + work = (rescaler_t*)p->memory; + + scalers = (WebPRescaler*)WEBP_ALIGN( + (const uint8_t*)work + total_size - rescaler_size); + p->scaler_y = &scalers[0]; + p->scaler_u = &scalers[1]; + p->scaler_v = &scalers[2]; + p->scaler_a = has_alpha ? &scalers[3] : NULL; + + if (!WebPRescalerInit(p->scaler_y, io->mb_w, io->mb_h, + buf->y, out_width, out_height, buf->y_stride, 1, + work) || + !WebPRescalerInit(p->scaler_u, uv_in_width, uv_in_height, + buf->u, uv_out_width, uv_out_height, buf->u_stride, 1, + work + work_size) || + !WebPRescalerInit(p->scaler_v, uv_in_width, uv_in_height, + buf->v, uv_out_width, uv_out_height, buf->v_stride, 1, + work + work_size + uv_work_size)) { + return 0; + } + p->emit = EmitRescaledYUV; + + if (has_alpha) { + if (!WebPRescalerInit(p->scaler_a, io->mb_w, io->mb_h, + buf->a, out_width, out_height, buf->a_stride, 1, + work + work_size + 2 * uv_work_size)) { + return 0; + } + p->emit_alpha = EmitRescaledAlphaYUV; + WebPInitAlphaProcessing(); + } + return 1; +} + +//------------------------------------------------------------------------------ +// RGBA rescaling + +static int ExportRGB(WebPDecParams* const p, int y_pos) { + const WebPYUV444Converter convert = + WebPYUV444Converters[p->output->colorspace]; + const WebPRGBABuffer* const buf = &p->output->u.RGBA; + uint8_t* dst = buf->rgba + (size_t)y_pos * buf->stride; + int num_lines_out = 0; + // For RGB rescaling, because of the YUV420, current scan position + // U/V can be +1/-1 line from the Y one. Hence the double test. + while (WebPRescalerHasPendingOutput(p->scaler_y) && + WebPRescalerHasPendingOutput(p->scaler_u)) { + assert(y_pos + num_lines_out < p->output->height); + assert(p->scaler_u->y_accum == p->scaler_v->y_accum); + WebPRescalerExportRow(p->scaler_y); + WebPRescalerExportRow(p->scaler_u); + WebPRescalerExportRow(p->scaler_v); + convert(p->scaler_y->dst, p->scaler_u->dst, p->scaler_v->dst, + dst, p->scaler_y->dst_width); + dst += buf->stride; + ++num_lines_out; + } + return num_lines_out; +} + +static int EmitRescaledRGB(const VP8Io* const io, WebPDecParams* const p) { + const int mb_h = io->mb_h; + const int uv_mb_h = (mb_h + 1) >> 1; + int j = 0, uv_j = 0; + int num_lines_out = 0; + while (j < mb_h) { + const int y_lines_in = + WebPRescalerImport(p->scaler_y, mb_h - j, + io->y + (size_t)j * io->y_stride, io->y_stride); + j += y_lines_in; + if (WebPRescaleNeededLines(p->scaler_u, uv_mb_h - uv_j)) { + const int u_lines_in = WebPRescalerImport( + p->scaler_u, uv_mb_h - uv_j, io->u + (size_t)uv_j * io->uv_stride, + io->uv_stride); + const int v_lines_in = WebPRescalerImport( + p->scaler_v, uv_mb_h - uv_j, io->v + (size_t)uv_j * io->uv_stride, + io->uv_stride); + (void)v_lines_in; // remove a gcc warning + assert(u_lines_in == v_lines_in); + uv_j += u_lines_in; + } + num_lines_out += ExportRGB(p, p->last_y + num_lines_out); + } + return num_lines_out; +} + +static int ExportAlpha(WebPDecParams* const p, int y_pos, int max_lines_out) { + const WebPRGBABuffer* const buf = &p->output->u.RGBA; + uint8_t* const base_rgba = buf->rgba + (size_t)y_pos * buf->stride; + const WEBP_CSP_MODE colorspace = p->output->colorspace; + const int alpha_first = + (colorspace == MODE_ARGB || colorspace == MODE_Argb); + uint8_t* dst = base_rgba + (alpha_first ? 0 : 3); + int num_lines_out = 0; + const int is_premult_alpha = WebPIsPremultipliedMode(colorspace); + uint32_t non_opaque = 0; + const int width = p->scaler_a->dst_width; + + while (WebPRescalerHasPendingOutput(p->scaler_a) && + num_lines_out < max_lines_out) { + assert(y_pos + num_lines_out < p->output->height); + WebPRescalerExportRow(p->scaler_a); + non_opaque |= WebPDispatchAlpha(p->scaler_a->dst, 0, width, 1, dst, 0); + dst += buf->stride; + ++num_lines_out; + } + if (is_premult_alpha && non_opaque) { + WebPApplyAlphaMultiply(base_rgba, alpha_first, + width, num_lines_out, buf->stride); + } + return num_lines_out; +} + +static int ExportAlphaRGBA4444(WebPDecParams* const p, int y_pos, + int max_lines_out) { + const WebPRGBABuffer* const buf = &p->output->u.RGBA; + uint8_t* const base_rgba = buf->rgba + (size_t)y_pos * buf->stride; +#if (WEBP_SWAP_16BIT_CSP == 1) + uint8_t* alpha_dst = base_rgba; +#else + uint8_t* alpha_dst = base_rgba + 1; +#endif + int num_lines_out = 0; + const WEBP_CSP_MODE colorspace = p->output->colorspace; + const int width = p->scaler_a->dst_width; + const int is_premult_alpha = WebPIsPremultipliedMode(colorspace); + uint32_t alpha_mask = 0x0f; + + while (WebPRescalerHasPendingOutput(p->scaler_a) && + num_lines_out < max_lines_out) { + int i; + assert(y_pos + num_lines_out < p->output->height); + WebPRescalerExportRow(p->scaler_a); + for (i = 0; i < width; ++i) { + // Fill in the alpha value (converted to 4 bits). + const uint32_t alpha_value = p->scaler_a->dst[i] >> 4; + alpha_dst[2 * i] = (alpha_dst[2 * i] & 0xf0) | alpha_value; + alpha_mask &= alpha_value; + } + alpha_dst += buf->stride; + ++num_lines_out; + } + if (is_premult_alpha && alpha_mask != 0x0f) { + WebPApplyAlphaMultiply4444(base_rgba, width, num_lines_out, buf->stride); + } + return num_lines_out; +} + +static int EmitRescaledAlphaRGB(const VP8Io* const io, WebPDecParams* const p, + int expected_num_out_lines) { + if (io->a != NULL) { + WebPRescaler* const scaler = p->scaler_a; + int lines_left = expected_num_out_lines; + const int y_end = p->last_y + lines_left; + while (lines_left > 0) { + const int64_t row_offset = (int64_t)scaler->src_y - io->mb_y; + WebPRescalerImport(scaler, io->mb_h + io->mb_y - scaler->src_y, + io->a + row_offset * io->width, io->width); + lines_left -= p->emit_alpha_row(p, y_end - lines_left, lines_left); + } + } + return 0; +} + +static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) { + const int has_alpha = WebPIsAlphaMode(p->output->colorspace); + const int out_width = io->scaled_width; + const int out_height = io->scaled_height; + const int uv_in_width = (io->mb_w + 1) >> 1; + const int uv_in_height = (io->mb_h + 1) >> 1; + // scratch memory for one rescaler + const size_t work_size = 2 * (size_t)out_width; + rescaler_t* work; // rescalers work area + uint8_t* tmp; // tmp storage for scaled YUV444 samples before RGB conversion + uint64_t tmp_size1, tmp_size2, total_size; + size_t rescaler_size; + WebPRescaler* scalers; + const int num_rescalers = has_alpha ? 4 : 3; + + tmp_size1 = (uint64_t)num_rescalers * work_size; + tmp_size2 = (uint64_t)num_rescalers * out_width; + total_size = tmp_size1 * sizeof(*work) + tmp_size2 * sizeof(*tmp); + rescaler_size = num_rescalers * sizeof(*p->scaler_y) + WEBP_ALIGN_CST; + total_size += rescaler_size; + if (!CheckSizeOverflow(total_size)) { + return 0; + } + + p->memory = WebPSafeMalloc(1ULL, (size_t)total_size); + if (p->memory == NULL) { + return 0; // memory error + } + work = (rescaler_t*)p->memory; + tmp = (uint8_t*)(work + tmp_size1); + + scalers = (WebPRescaler*)WEBP_ALIGN( + (const uint8_t*)work + total_size - rescaler_size); + p->scaler_y = &scalers[0]; + p->scaler_u = &scalers[1]; + p->scaler_v = &scalers[2]; + p->scaler_a = has_alpha ? &scalers[3] : NULL; + + if (!WebPRescalerInit(p->scaler_y, io->mb_w, io->mb_h, + tmp + 0 * out_width, out_width, out_height, 0, 1, + work + 0 * work_size) || + !WebPRescalerInit(p->scaler_u, uv_in_width, uv_in_height, + tmp + 1 * out_width, out_width, out_height, 0, 1, + work + 1 * work_size) || + !WebPRescalerInit(p->scaler_v, uv_in_width, uv_in_height, + tmp + 2 * out_width, out_width, out_height, 0, 1, + work + 2 * work_size)) { + return 0; + } + p->emit = EmitRescaledRGB; + WebPInitYUV444Converters(); + + if (has_alpha) { + if (!WebPRescalerInit(p->scaler_a, io->mb_w, io->mb_h, + tmp + 3 * out_width, out_width, out_height, 0, 1, + work + 3 * work_size)) { + return 0; + } + p->emit_alpha = EmitRescaledAlphaRGB; + if (p->output->colorspace == MODE_RGBA_4444 || + p->output->colorspace == MODE_rgbA_4444) { + p->emit_alpha_row = ExportAlphaRGBA4444; + } else { + p->emit_alpha_row = ExportAlpha; + } + WebPInitAlphaProcessing(); + } + return 1; +} + +#endif // WEBP_REDUCE_SIZE + +//------------------------------------------------------------------------------ +// Default custom functions + +static int CustomSetup(VP8Io* io) { + WebPDecParams* const p = (WebPDecParams*)io->opaque; + const WEBP_CSP_MODE colorspace = p->output->colorspace; + const int is_rgb = WebPIsRGBMode(colorspace); + const int is_alpha = WebPIsAlphaMode(colorspace); + + p->memory = NULL; + p->emit = NULL; + p->emit_alpha = NULL; + p->emit_alpha_row = NULL; + if (!WebPIoInitFromOptions(p->options, io, is_alpha ? MODE_YUV : MODE_YUVA)) { + return 0; + } + if (is_alpha && WebPIsPremultipliedMode(colorspace)) { + WebPInitUpsamplers(); + } + if (io->use_scaling) { +#if !defined(WEBP_REDUCE_SIZE) + const int ok = is_rgb ? InitRGBRescaler(io, p) : InitYUVRescaler(io, p); + if (!ok) { + return 0; // memory error + } +#else + return 0; // rescaling support not compiled +#endif + } else { + if (is_rgb) { + WebPInitSamplers(); + p->emit = EmitSampledRGB; // default + if (io->fancy_upsampling) { +#ifdef FANCY_UPSAMPLING + const int uv_width = (io->mb_w + 1) >> 1; + p->memory = WebPSafeMalloc(1ULL, (size_t)(io->mb_w + 2 * uv_width)); + if (p->memory == NULL) { + return 0; // memory error. + } + p->tmp_y = (uint8_t*)p->memory; + p->tmp_u = p->tmp_y + io->mb_w; + p->tmp_v = p->tmp_u + uv_width; + p->emit = EmitFancyRGB; + WebPInitUpsamplers(); +#endif + } + } else { + p->emit = EmitYUV; + } + if (is_alpha) { // need transparency output + p->emit_alpha = + (colorspace == MODE_RGBA_4444 || colorspace == MODE_rgbA_4444) ? + EmitAlphaRGBA4444 + : is_rgb ? EmitAlphaRGB + : EmitAlphaYUV; + if (is_rgb) { + WebPInitAlphaProcessing(); + } + } + } + + return 1; +} + +//------------------------------------------------------------------------------ + +static int CustomPut(const VP8Io* io) { + WebPDecParams* const p = (WebPDecParams*)io->opaque; + const int mb_w = io->mb_w; + const int mb_h = io->mb_h; + int num_lines_out; + assert(!(io->mb_y & 1)); + + if (mb_w <= 0 || mb_h <= 0) { + return 0; + } + num_lines_out = p->emit(io, p); + if (p->emit_alpha != NULL) { + p->emit_alpha(io, p, num_lines_out); + } + p->last_y += num_lines_out; + return 1; +} + +//------------------------------------------------------------------------------ + +static void CustomTeardown(const VP8Io* io) { + WebPDecParams* const p = (WebPDecParams*)io->opaque; + WebPSafeFree(p->memory); + p->memory = NULL; +} + +//------------------------------------------------------------------------------ +// Main entry point + +void WebPInitCustomIo(WebPDecParams* const params, VP8Io* const io) { + io->put = CustomPut; + io->setup = CustomSetup; + io->teardown = CustomTeardown; + io->opaque = params; +} + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/src/dec/quant_dec.c b/third-party/webp/libwebp/src/dec/quant_dec.c new file mode 100644 index 0000000000..a0ac018b0f --- /dev/null +++ b/third-party/webp/libwebp/src/dec/quant_dec.c @@ -0,0 +1,115 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Quantizer initialization +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dec/vp8i_dec.h" + +static WEBP_INLINE int clip(int v, int M) { + return v < 0 ? 0 : v > M ? M : v; +} + +// Paragraph 14.1 +static const uint8_t kDcTable[128] = { + 4, 5, 6, 7, 8, 9, 10, 10, + 11, 12, 13, 14, 15, 16, 17, 17, + 18, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 25, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, + 37, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 76, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, 88, 89, + 91, 93, 95, 96, 98, 100, 101, 102, + 104, 106, 108, 110, 112, 114, 116, 118, + 122, 124, 126, 128, 130, 132, 134, 136, + 138, 140, 143, 145, 148, 151, 154, 157 +}; + +static const uint16_t kAcTable[128] = { + 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 60, + 62, 64, 66, 68, 70, 72, 74, 76, + 78, 80, 82, 84, 86, 88, 90, 92, + 94, 96, 98, 100, 102, 104, 106, 108, + 110, 112, 114, 116, 119, 122, 125, 128, + 131, 134, 137, 140, 143, 146, 149, 152, + 155, 158, 161, 164, 167, 170, 173, 177, + 181, 185, 189, 193, 197, 201, 205, 209, + 213, 217, 221, 225, 229, 234, 239, 245, + 249, 254, 259, 264, 269, 274, 279, 284 +}; + +//------------------------------------------------------------------------------ +// Paragraph 9.6 + +void VP8ParseQuant(VP8Decoder* const dec) { + VP8BitReader* const br = &dec->br_; + const int base_q0 = VP8GetValue(br, 7, "global-header"); + const int dqy1_dc = VP8Get(br, "global-header") ? + VP8GetSignedValue(br, 4, "global-header") : 0; + const int dqy2_dc = VP8Get(br, "global-header") ? + VP8GetSignedValue(br, 4, "global-header") : 0; + const int dqy2_ac = VP8Get(br, "global-header") ? + VP8GetSignedValue(br, 4, "global-header") : 0; + const int dquv_dc = VP8Get(br, "global-header") ? + VP8GetSignedValue(br, 4, "global-header") : 0; + const int dquv_ac = VP8Get(br, "global-header") ? + VP8GetSignedValue(br, 4, "global-header") : 0; + + const VP8SegmentHeader* const hdr = &dec->segment_hdr_; + int i; + + for (i = 0; i < NUM_MB_SEGMENTS; ++i) { + int q; + if (hdr->use_segment_) { + q = hdr->quantizer_[i]; + if (!hdr->absolute_delta_) { + q += base_q0; + } + } else { + if (i > 0) { + dec->dqm_[i] = dec->dqm_[0]; + continue; + } else { + q = base_q0; + } + } + { + VP8QuantMatrix* const m = &dec->dqm_[i]; + m->y1_mat_[0] = kDcTable[clip(q + dqy1_dc, 127)]; + m->y1_mat_[1] = kAcTable[clip(q + 0, 127)]; + + m->y2_mat_[0] = kDcTable[clip(q + dqy2_dc, 127)] * 2; + // For all x in [0..284], x*155/100 is bitwise equal to (x*101581) >> 16. + // The smallest precision for that is '(x*6349) >> 12' but 16 is a good + // word size. + m->y2_mat_[1] = (kAcTable[clip(q + dqy2_ac, 127)] * 101581) >> 16; + if (m->y2_mat_[1] < 8) m->y2_mat_[1] = 8; + + m->uv_mat_[0] = kDcTable[clip(q + dquv_dc, 117)]; + m->uv_mat_[1] = kAcTable[clip(q + dquv_ac, 127)]; + + m->uv_quant_ = q + dquv_ac; // for dithering strength evaluation + } + } +} + +//------------------------------------------------------------------------------ + diff --git a/third-party/webp/libwebp/src/dec/tree_dec.c b/third-party/webp/libwebp/src/dec/tree_dec.c new file mode 100644 index 0000000000..2434605953 --- /dev/null +++ b/third-party/webp/libwebp/src/dec/tree_dec.c @@ -0,0 +1,538 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Coding trees and probas +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dec/vp8i_dec.h" +#include "src/dsp/cpu.h" +#include "src/utils/bit_reader_inl_utils.h" + +#if !defined(USE_GENERIC_TREE) +#if !defined(__arm__) && !defined(_M_ARM) && !WEBP_AARCH64 +// using a table is ~1-2% slower on ARM. Prefer the coded-tree approach then. +#define USE_GENERIC_TREE 1 // ALTERNATE_CODE +#else +#define USE_GENERIC_TREE 0 +#endif +#endif // USE_GENERIC_TREE + +#if (USE_GENERIC_TREE == 1) +static const int8_t kYModesIntra4[18] = { + -B_DC_PRED, 1, + -B_TM_PRED, 2, + -B_VE_PRED, 3, + 4, 6, + -B_HE_PRED, 5, + -B_RD_PRED, -B_VR_PRED, + -B_LD_PRED, 7, + -B_VL_PRED, 8, + -B_HD_PRED, -B_HU_PRED +}; +#endif + +//------------------------------------------------------------------------------ +// Default probabilities + +// Paragraph 13.5 +static const uint8_t + CoeffsProba0[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = { + { { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } + }, + { { 253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128 }, + { 189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128 }, + { 106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128 } + }, + { { 1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128 }, + { 181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128 }, + { 78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128 }, + }, + { { 1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128 }, + { 184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128 }, + { 77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128 }, + }, + { { 1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128 }, + { 170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128 }, + { 37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128 } + }, + { { 1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128 }, + { 207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128 }, + { 102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128 } + }, + { { 1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128 }, + { 177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128 }, + { 80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128 } + }, + { { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } + } + }, + { { { 198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62 }, + { 131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1 }, + { 68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128 } + }, + { { 1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128 }, + { 184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128 }, + { 81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128 } + }, + { { 1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128 }, + { 99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128 }, + { 23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128 } + }, + { { 1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128 }, + { 109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128 }, + { 44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128 } + }, + { { 1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128 }, + { 94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128 }, + { 22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128 } + }, + { { 1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128 }, + { 124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128 }, + { 35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128 } + }, + { { 1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128 }, + { 121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128 }, + { 45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128 } + }, + { { 1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128 }, + { 203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128 } + } + }, + { { { 253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128 }, + { 175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128 }, + { 73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128 } + }, + { { 1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128 }, + { 239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128 }, + { 155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128 } + }, + { { 1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128 }, + { 201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128 }, + { 69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128 } + }, + { { 1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128 }, + { 141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128 } + }, + { { 1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128 }, + { 149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 } + }, + { { 1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128 } + }, + { { 1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 55, 93, 255, 128, 128, 128, 128, 128, 128, 128, 128 } + }, + { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } + } + }, + { { { 202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255 }, + { 126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128 }, + { 61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128 } + }, + { { 1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128 }, + { 166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128 }, + { 39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128 } + }, + { { 1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128 }, + { 124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128 }, + { 24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128 } + }, + { { 1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128 }, + { 149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128 }, + { 28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128 } + }, + { { 1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128 }, + { 123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128 }, + { 20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128 } + }, + { { 1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128 }, + { 168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128 }, + { 47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128 } + }, + { { 1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128 }, + { 141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128 }, + { 42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128 } + }, + { { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 } + } + } +}; + +// Paragraph 11.5 +static const uint8_t kBModesProba[NUM_BMODES][NUM_BMODES][NUM_BMODES - 1] = { + { { 231, 120, 48, 89, 115, 113, 120, 152, 112 }, + { 152, 179, 64, 126, 170, 118, 46, 70, 95 }, + { 175, 69, 143, 80, 85, 82, 72, 155, 103 }, + { 56, 58, 10, 171, 218, 189, 17, 13, 152 }, + { 114, 26, 17, 163, 44, 195, 21, 10, 173 }, + { 121, 24, 80, 195, 26, 62, 44, 64, 85 }, + { 144, 71, 10, 38, 171, 213, 144, 34, 26 }, + { 170, 46, 55, 19, 136, 160, 33, 206, 71 }, + { 63, 20, 8, 114, 114, 208, 12, 9, 226 }, + { 81, 40, 11, 96, 182, 84, 29, 16, 36 } }, + { { 134, 183, 89, 137, 98, 101, 106, 165, 148 }, + { 72, 187, 100, 130, 157, 111, 32, 75, 80 }, + { 66, 102, 167, 99, 74, 62, 40, 234, 128 }, + { 41, 53, 9, 178, 241, 141, 26, 8, 107 }, + { 74, 43, 26, 146, 73, 166, 49, 23, 157 }, + { 65, 38, 105, 160, 51, 52, 31, 115, 128 }, + { 104, 79, 12, 27, 217, 255, 87, 17, 7 }, + { 87, 68, 71, 44, 114, 51, 15, 186, 23 }, + { 47, 41, 14, 110, 182, 183, 21, 17, 194 }, + { 66, 45, 25, 102, 197, 189, 23, 18, 22 } }, + { { 88, 88, 147, 150, 42, 46, 45, 196, 205 }, + { 43, 97, 183, 117, 85, 38, 35, 179, 61 }, + { 39, 53, 200, 87, 26, 21, 43, 232, 171 }, + { 56, 34, 51, 104, 114, 102, 29, 93, 77 }, + { 39, 28, 85, 171, 58, 165, 90, 98, 64 }, + { 34, 22, 116, 206, 23, 34, 43, 166, 73 }, + { 107, 54, 32, 26, 51, 1, 81, 43, 31 }, + { 68, 25, 106, 22, 64, 171, 36, 225, 114 }, + { 34, 19, 21, 102, 132, 188, 16, 76, 124 }, + { 62, 18, 78, 95, 85, 57, 50, 48, 51 } }, + { { 193, 101, 35, 159, 215, 111, 89, 46, 111 }, + { 60, 148, 31, 172, 219, 228, 21, 18, 111 }, + { 112, 113, 77, 85, 179, 255, 38, 120, 114 }, + { 40, 42, 1, 196, 245, 209, 10, 25, 109 }, + { 88, 43, 29, 140, 166, 213, 37, 43, 154 }, + { 61, 63, 30, 155, 67, 45, 68, 1, 209 }, + { 100, 80, 8, 43, 154, 1, 51, 26, 71 }, + { 142, 78, 78, 16, 255, 128, 34, 197, 171 }, + { 41, 40, 5, 102, 211, 183, 4, 1, 221 }, + { 51, 50, 17, 168, 209, 192, 23, 25, 82 } }, + { { 138, 31, 36, 171, 27, 166, 38, 44, 229 }, + { 67, 87, 58, 169, 82, 115, 26, 59, 179 }, + { 63, 59, 90, 180, 59, 166, 93, 73, 154 }, + { 40, 40, 21, 116, 143, 209, 34, 39, 175 }, + { 47, 15, 16, 183, 34, 223, 49, 45, 183 }, + { 46, 17, 33, 183, 6, 98, 15, 32, 183 }, + { 57, 46, 22, 24, 128, 1, 54, 17, 37 }, + { 65, 32, 73, 115, 28, 128, 23, 128, 205 }, + { 40, 3, 9, 115, 51, 192, 18, 6, 223 }, + { 87, 37, 9, 115, 59, 77, 64, 21, 47 } }, + { { 104, 55, 44, 218, 9, 54, 53, 130, 226 }, + { 64, 90, 70, 205, 40, 41, 23, 26, 57 }, + { 54, 57, 112, 184, 5, 41, 38, 166, 213 }, + { 30, 34, 26, 133, 152, 116, 10, 32, 134 }, + { 39, 19, 53, 221, 26, 114, 32, 73, 255 }, + { 31, 9, 65, 234, 2, 15, 1, 118, 73 }, + { 75, 32, 12, 51, 192, 255, 160, 43, 51 }, + { 88, 31, 35, 67, 102, 85, 55, 186, 85 }, + { 56, 21, 23, 111, 59, 205, 45, 37, 192 }, + { 55, 38, 70, 124, 73, 102, 1, 34, 98 } }, + { { 125, 98, 42, 88, 104, 85, 117, 175, 82 }, + { 95, 84, 53, 89, 128, 100, 113, 101, 45 }, + { 75, 79, 123, 47, 51, 128, 81, 171, 1 }, + { 57, 17, 5, 71, 102, 57, 53, 41, 49 }, + { 38, 33, 13, 121, 57, 73, 26, 1, 85 }, + { 41, 10, 67, 138, 77, 110, 90, 47, 114 }, + { 115, 21, 2, 10, 102, 255, 166, 23, 6 }, + { 101, 29, 16, 10, 85, 128, 101, 196, 26 }, + { 57, 18, 10, 102, 102, 213, 34, 20, 43 }, + { 117, 20, 15, 36, 163, 128, 68, 1, 26 } }, + { { 102, 61, 71, 37, 34, 53, 31, 243, 192 }, + { 69, 60, 71, 38, 73, 119, 28, 222, 37 }, + { 68, 45, 128, 34, 1, 47, 11, 245, 171 }, + { 62, 17, 19, 70, 146, 85, 55, 62, 70 }, + { 37, 43, 37, 154, 100, 163, 85, 160, 1 }, + { 63, 9, 92, 136, 28, 64, 32, 201, 85 }, + { 75, 15, 9, 9, 64, 255, 184, 119, 16 }, + { 86, 6, 28, 5, 64, 255, 25, 248, 1 }, + { 56, 8, 17, 132, 137, 255, 55, 116, 128 }, + { 58, 15, 20, 82, 135, 57, 26, 121, 40 } }, + { { 164, 50, 31, 137, 154, 133, 25, 35, 218 }, + { 51, 103, 44, 131, 131, 123, 31, 6, 158 }, + { 86, 40, 64, 135, 148, 224, 45, 183, 128 }, + { 22, 26, 17, 131, 240, 154, 14, 1, 209 }, + { 45, 16, 21, 91, 64, 222, 7, 1, 197 }, + { 56, 21, 39, 155, 60, 138, 23, 102, 213 }, + { 83, 12, 13, 54, 192, 255, 68, 47, 28 }, + { 85, 26, 85, 85, 128, 128, 32, 146, 171 }, + { 18, 11, 7, 63, 144, 171, 4, 4, 246 }, + { 35, 27, 10, 146, 174, 171, 12, 26, 128 } }, + { { 190, 80, 35, 99, 180, 80, 126, 54, 45 }, + { 85, 126, 47, 87, 176, 51, 41, 20, 32 }, + { 101, 75, 128, 139, 118, 146, 116, 128, 85 }, + { 56, 41, 15, 176, 236, 85, 37, 9, 62 }, + { 71, 30, 17, 119, 118, 255, 17, 18, 138 }, + { 101, 38, 60, 138, 55, 70, 43, 26, 142 }, + { 146, 36, 19, 30, 171, 255, 97, 27, 20 }, + { 138, 45, 61, 62, 219, 1, 81, 188, 64 }, + { 32, 41, 20, 117, 151, 142, 20, 21, 163 }, + { 112, 19, 12, 61, 195, 128, 48, 4, 24 } } +}; + +void VP8ResetProba(VP8Proba* const proba) { + memset(proba->segments_, 255u, sizeof(proba->segments_)); + // proba->bands_[][] is initialized later +} + +static void ParseIntraMode(VP8BitReader* const br, + VP8Decoder* const dec, int mb_x) { + uint8_t* const top = dec->intra_t_ + 4 * mb_x; + uint8_t* const left = dec->intra_l_; + VP8MBData* const block = dec->mb_data_ + mb_x; + + // Note: we don't save segment map (yet), as we don't expect + // to decode more than 1 keyframe. + if (dec->segment_hdr_.update_map_) { + // Hardcoded tree parsing + block->segment_ = !VP8GetBit(br, dec->proba_.segments_[0], "segments") + ? VP8GetBit(br, dec->proba_.segments_[1], "segments") + : VP8GetBit(br, dec->proba_.segments_[2], "segments") + 2; + } else { + block->segment_ = 0; // default for intra + } + if (dec->use_skip_proba_) block->skip_ = VP8GetBit(br, dec->skip_p_, "skip"); + + block->is_i4x4_ = !VP8GetBit(br, 145, "block-size"); + if (!block->is_i4x4_) { + // Hardcoded 16x16 intra-mode decision tree. + const int ymode = + VP8GetBit(br, 156, "pred-modes") ? + (VP8GetBit(br, 128, "pred-modes") ? TM_PRED : H_PRED) : + (VP8GetBit(br, 163, "pred-modes") ? V_PRED : DC_PRED); + block->imodes_[0] = ymode; + memset(top, ymode, 4 * sizeof(*top)); + memset(left, ymode, 4 * sizeof(*left)); + } else { + uint8_t* modes = block->imodes_; + int y; + for (y = 0; y < 4; ++y) { + int ymode = left[y]; + int x; + for (x = 0; x < 4; ++x) { + const uint8_t* const prob = kBModesProba[top[x]][ymode]; +#if (USE_GENERIC_TREE == 1) + // Generic tree-parsing + int i = kYModesIntra4[VP8GetBit(br, prob[0], "pred-modes")]; + while (i > 0) { + i = kYModesIntra4[2 * i + VP8GetBit(br, prob[i], "pred-modes")]; + } + ymode = -i; +#else + // Hardcoded tree parsing + ymode = !VP8GetBit(br, prob[0], "pred-modes") ? B_DC_PRED : + !VP8GetBit(br, prob[1], "pred-modes") ? B_TM_PRED : + !VP8GetBit(br, prob[2], "pred-modes") ? B_VE_PRED : + !VP8GetBit(br, prob[3], "pred-modes") ? + (!VP8GetBit(br, prob[4], "pred-modes") ? B_HE_PRED : + (!VP8GetBit(br, prob[5], "pred-modes") ? B_RD_PRED + : B_VR_PRED)) : + (!VP8GetBit(br, prob[6], "pred-modes") ? B_LD_PRED : + (!VP8GetBit(br, prob[7], "pred-modes") ? B_VL_PRED : + (!VP8GetBit(br, prob[8], "pred-modes") ? B_HD_PRED + : B_HU_PRED)) + ); +#endif // USE_GENERIC_TREE + top[x] = ymode; + } + memcpy(modes, top, 4 * sizeof(*top)); + modes += 4; + left[y] = ymode; + } + } + // Hardcoded UVMode decision tree + block->uvmode_ = !VP8GetBit(br, 142, "pred-modes-uv") ? DC_PRED + : !VP8GetBit(br, 114, "pred-modes-uv") ? V_PRED + : VP8GetBit(br, 183, "pred-modes-uv") ? TM_PRED : H_PRED; +} + +int VP8ParseIntraModeRow(VP8BitReader* const br, VP8Decoder* const dec) { + int mb_x; + for (mb_x = 0; mb_x < dec->mb_w_; ++mb_x) { + ParseIntraMode(br, dec, mb_x); + } + return !dec->br_.eof_; +} + +//------------------------------------------------------------------------------ +// Paragraph 13 + +static const uint8_t + CoeffsUpdateProba[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = { + { { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255 }, + { 250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + } + }, + { { { 217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255 }, + { 234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255 } + }, + { { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + } + }, + { { { 186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255 }, + { 251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255 } + }, + { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + } + }, + { { { 248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255 }, + { 248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + } + } +}; + +// Paragraph 9.9 + +static const uint8_t kBands[16 + 1] = { + 0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, + 0 // extra entry as sentinel +}; + +void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec) { + VP8Proba* const proba = &dec->proba_; + int t, b, c, p; + for (t = 0; t < NUM_TYPES; ++t) { + for (b = 0; b < NUM_BANDS; ++b) { + for (c = 0; c < NUM_CTX; ++c) { + for (p = 0; p < NUM_PROBAS; ++p) { + const int v = + VP8GetBit(br, CoeffsUpdateProba[t][b][c][p], "global-header") ? + VP8GetValue(br, 8, "global-header") : + CoeffsProba0[t][b][c][p]; + proba->bands_[t][b].probas_[c][p] = v; + } + } + } + for (b = 0; b < 16 + 1; ++b) { + proba->bands_ptr_[t][b] = &proba->bands_[t][kBands[b]]; + } + } + dec->use_skip_proba_ = VP8Get(br, "global-header"); + if (dec->use_skip_proba_) { + dec->skip_p_ = VP8GetValue(br, 8, "global-header"); + } +} diff --git a/third-party/webp/libwebp/src/dec/vp8_dec.c b/third-party/webp/libwebp/src/dec/vp8_dec.c new file mode 100644 index 0000000000..20b92e84c4 --- /dev/null +++ b/third-party/webp/libwebp/src/dec/vp8_dec.c @@ -0,0 +1,724 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// main entry for the decoder +// +// Author: Skal (pascal.massimino@gmail.com) + +#include + +#include "src/dec/alphai_dec.h" +#include "src/dec/vp8i_dec.h" +#include "src/dec/vp8li_dec.h" +#include "src/dec/webpi_dec.h" +#include "src/utils/bit_reader_inl_utils.h" +#include "src/utils/utils.h" + +//------------------------------------------------------------------------------ + +int WebPGetDecoderVersion(void) { + return (DEC_MAJ_VERSION << 16) | (DEC_MIN_VERSION << 8) | DEC_REV_VERSION; +} + +//------------------------------------------------------------------------------ +// Signature and pointer-to-function for GetCoeffs() variants below. + +typedef int (*GetCoeffsFunc)(VP8BitReader* const br, + const VP8BandProbas* const prob[], + int ctx, const quant_t dq, int n, int16_t* out); +static volatile GetCoeffsFunc GetCoeffs = NULL; + +static void InitGetCoeffs(void); + +//------------------------------------------------------------------------------ +// VP8Decoder + +static void SetOk(VP8Decoder* const dec) { + dec->status_ = VP8_STATUS_OK; + dec->error_msg_ = "OK"; +} + +int VP8InitIoInternal(VP8Io* const io, int version) { + if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) { + return 0; // mismatch error + } + if (io != NULL) { + memset(io, 0, sizeof(*io)); + } + return 1; +} + +VP8Decoder* VP8New(void) { + VP8Decoder* const dec = (VP8Decoder*)WebPSafeCalloc(1ULL, sizeof(*dec)); + if (dec != NULL) { + SetOk(dec); + WebPGetWorkerInterface()->Init(&dec->worker_); + dec->ready_ = 0; + dec->num_parts_minus_one_ = 0; + InitGetCoeffs(); + } + return dec; +} + +VP8StatusCode VP8Status(VP8Decoder* const dec) { + if (!dec) return VP8_STATUS_INVALID_PARAM; + return dec->status_; +} + +const char* VP8StatusMessage(VP8Decoder* const dec) { + if (dec == NULL) return "no object"; + if (!dec->error_msg_) return "OK"; + return dec->error_msg_; +} + +void VP8Delete(VP8Decoder* const dec) { + if (dec != NULL) { + VP8Clear(dec); + WebPSafeFree(dec); + } +} + +int VP8SetError(VP8Decoder* const dec, + VP8StatusCode error, const char* const msg) { + // The oldest error reported takes precedence over the new one. + if (dec->status_ == VP8_STATUS_OK) { + dec->status_ = error; + dec->error_msg_ = msg; + dec->ready_ = 0; + } + return 0; +} + +//------------------------------------------------------------------------------ + +int VP8CheckSignature(const uint8_t* const data, size_t data_size) { + return (data_size >= 3 && + data[0] == 0x9d && data[1] == 0x01 && data[2] == 0x2a); +} + +int VP8GetInfo(const uint8_t* data, size_t data_size, size_t chunk_size, + int* const width, int* const height) { + if (data == NULL || data_size < VP8_FRAME_HEADER_SIZE) { + return 0; // not enough data + } + // check signature + if (!VP8CheckSignature(data + 3, data_size - 3)) { + return 0; // Wrong signature. + } else { + const uint32_t bits = data[0] | (data[1] << 8) | (data[2] << 16); + const int key_frame = !(bits & 1); + const int w = ((data[7] << 8) | data[6]) & 0x3fff; + const int h = ((data[9] << 8) | data[8]) & 0x3fff; + + if (!key_frame) { // Not a keyframe. + return 0; + } + + if (((bits >> 1) & 7) > 3) { + return 0; // unknown profile + } + if (!((bits >> 4) & 1)) { + return 0; // first frame is invisible! + } + if (((bits >> 5)) >= chunk_size) { // partition_length + return 0; // inconsistent size information. + } + if (w == 0 || h == 0) { + return 0; // We don't support both width and height to be zero. + } + + if (width) { + *width = w; + } + if (height) { + *height = h; + } + + return 1; + } +} + +//------------------------------------------------------------------------------ +// Header parsing + +static void ResetSegmentHeader(VP8SegmentHeader* const hdr) { + assert(hdr != NULL); + hdr->use_segment_ = 0; + hdr->update_map_ = 0; + hdr->absolute_delta_ = 1; + memset(hdr->quantizer_, 0, sizeof(hdr->quantizer_)); + memset(hdr->filter_strength_, 0, sizeof(hdr->filter_strength_)); +} + +// Paragraph 9.3 +static int ParseSegmentHeader(VP8BitReader* br, + VP8SegmentHeader* hdr, VP8Proba* proba) { + assert(br != NULL); + assert(hdr != NULL); + hdr->use_segment_ = VP8Get(br, "global-header"); + if (hdr->use_segment_) { + hdr->update_map_ = VP8Get(br, "global-header"); + if (VP8Get(br, "global-header")) { // update data + int s; + hdr->absolute_delta_ = VP8Get(br, "global-header"); + for (s = 0; s < NUM_MB_SEGMENTS; ++s) { + hdr->quantizer_[s] = VP8Get(br, "global-header") ? + VP8GetSignedValue(br, 7, "global-header") : 0; + } + for (s = 0; s < NUM_MB_SEGMENTS; ++s) { + hdr->filter_strength_[s] = VP8Get(br, "global-header") ? + VP8GetSignedValue(br, 6, "global-header") : 0; + } + } + if (hdr->update_map_) { + int s; + for (s = 0; s < MB_FEATURE_TREE_PROBS; ++s) { + proba->segments_[s] = VP8Get(br, "global-header") ? + VP8GetValue(br, 8, "global-header") : 255u; + } + } + } else { + hdr->update_map_ = 0; + } + return !br->eof_; +} + +// Paragraph 9.5 +// This function returns VP8_STATUS_SUSPENDED if we don't have all the +// necessary data in 'buf'. +// This case is not necessarily an error (for incremental decoding). +// Still, no bitreader is ever initialized to make it possible to read +// unavailable memory. +// If we don't even have the partitions' sizes, than VP8_STATUS_NOT_ENOUGH_DATA +// is returned, and this is an unrecoverable error. +// If the partitions were positioned ok, VP8_STATUS_OK is returned. +static VP8StatusCode ParsePartitions(VP8Decoder* const dec, + const uint8_t* buf, size_t size) { + VP8BitReader* const br = &dec->br_; + const uint8_t* sz = buf; + const uint8_t* buf_end = buf + size; + const uint8_t* part_start; + size_t size_left = size; + size_t last_part; + size_t p; + + dec->num_parts_minus_one_ = (1 << VP8GetValue(br, 2, "global-header")) - 1; + last_part = dec->num_parts_minus_one_; + if (size < 3 * last_part) { + // we can't even read the sizes with sz[]! That's a failure. + return VP8_STATUS_NOT_ENOUGH_DATA; + } + part_start = buf + last_part * 3; + size_left -= last_part * 3; + for (p = 0; p < last_part; ++p) { + size_t psize = sz[0] | (sz[1] << 8) | (sz[2] << 16); + if (psize > size_left) psize = size_left; + VP8InitBitReader(dec->parts_ + p, part_start, psize); + part_start += psize; + size_left -= psize; + sz += 3; + } + VP8InitBitReader(dec->parts_ + last_part, part_start, size_left); + return (part_start < buf_end) ? VP8_STATUS_OK : + VP8_STATUS_SUSPENDED; // Init is ok, but there's not enough data +} + +// Paragraph 9.4 +static int ParseFilterHeader(VP8BitReader* br, VP8Decoder* const dec) { + VP8FilterHeader* const hdr = &dec->filter_hdr_; + hdr->simple_ = VP8Get(br, "global-header"); + hdr->level_ = VP8GetValue(br, 6, "global-header"); + hdr->sharpness_ = VP8GetValue(br, 3, "global-header"); + hdr->use_lf_delta_ = VP8Get(br, "global-header"); + if (hdr->use_lf_delta_) { + if (VP8Get(br, "global-header")) { // update lf-delta? + int i; + for (i = 0; i < NUM_REF_LF_DELTAS; ++i) { + if (VP8Get(br, "global-header")) { + hdr->ref_lf_delta_[i] = VP8GetSignedValue(br, 6, "global-header"); + } + } + for (i = 0; i < NUM_MODE_LF_DELTAS; ++i) { + if (VP8Get(br, "global-header")) { + hdr->mode_lf_delta_[i] = VP8GetSignedValue(br, 6, "global-header"); + } + } + } + } + dec->filter_type_ = (hdr->level_ == 0) ? 0 : hdr->simple_ ? 1 : 2; + return !br->eof_; +} + +// Topmost call +int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) { + const uint8_t* buf; + size_t buf_size; + VP8FrameHeader* frm_hdr; + VP8PictureHeader* pic_hdr; + VP8BitReader* br; + VP8StatusCode status; + + if (dec == NULL) { + return 0; + } + SetOk(dec); + if (io == NULL) { + return VP8SetError(dec, VP8_STATUS_INVALID_PARAM, + "null VP8Io passed to VP8GetHeaders()"); + } + buf = io->data; + buf_size = io->data_size; + if (buf_size < 4) { + return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA, + "Truncated header."); + } + + // Paragraph 9.1 + { + const uint32_t bits = buf[0] | (buf[1] << 8) | (buf[2] << 16); + frm_hdr = &dec->frm_hdr_; + frm_hdr->key_frame_ = !(bits & 1); + frm_hdr->profile_ = (bits >> 1) & 7; + frm_hdr->show_ = (bits >> 4) & 1; + frm_hdr->partition_length_ = (bits >> 5); + if (frm_hdr->profile_ > 3) { + return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, + "Incorrect keyframe parameters."); + } + if (!frm_hdr->show_) { + return VP8SetError(dec, VP8_STATUS_UNSUPPORTED_FEATURE, + "Frame not displayable."); + } + buf += 3; + buf_size -= 3; + } + + pic_hdr = &dec->pic_hdr_; + if (frm_hdr->key_frame_) { + // Paragraph 9.2 + if (buf_size < 7) { + return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA, + "cannot parse picture header"); + } + if (!VP8CheckSignature(buf, buf_size)) { + return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, + "Bad code word"); + } + pic_hdr->width_ = ((buf[4] << 8) | buf[3]) & 0x3fff; + pic_hdr->xscale_ = buf[4] >> 6; // ratio: 1, 5/4 5/3 or 2 + pic_hdr->height_ = ((buf[6] << 8) | buf[5]) & 0x3fff; + pic_hdr->yscale_ = buf[6] >> 6; + buf += 7; + buf_size -= 7; + + dec->mb_w_ = (pic_hdr->width_ + 15) >> 4; + dec->mb_h_ = (pic_hdr->height_ + 15) >> 4; + + // Setup default output area (can be later modified during io->setup()) + io->width = pic_hdr->width_; + io->height = pic_hdr->height_; + // IMPORTANT! use some sane dimensions in crop_* and scaled_* fields. + // So they can be used interchangeably without always testing for + // 'use_cropping'. + io->use_cropping = 0; + io->crop_top = 0; + io->crop_left = 0; + io->crop_right = io->width; + io->crop_bottom = io->height; + io->use_scaling = 0; + io->scaled_width = io->width; + io->scaled_height = io->height; + + io->mb_w = io->width; // for soundness + io->mb_h = io->height; // ditto + + VP8ResetProba(&dec->proba_); + ResetSegmentHeader(&dec->segment_hdr_); + } + + // Check if we have all the partition #0 available, and initialize dec->br_ + // to read this partition (and this partition only). + if (frm_hdr->partition_length_ > buf_size) { + return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA, + "bad partition length"); + } + + br = &dec->br_; + VP8InitBitReader(br, buf, frm_hdr->partition_length_); + buf += frm_hdr->partition_length_; + buf_size -= frm_hdr->partition_length_; + + if (frm_hdr->key_frame_) { + pic_hdr->colorspace_ = VP8Get(br, "global-header"); + pic_hdr->clamp_type_ = VP8Get(br, "global-header"); + } + if (!ParseSegmentHeader(br, &dec->segment_hdr_, &dec->proba_)) { + return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, + "cannot parse segment header"); + } + // Filter specs + if (!ParseFilterHeader(br, dec)) { + return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, + "cannot parse filter header"); + } + status = ParsePartitions(dec, buf, buf_size); + if (status != VP8_STATUS_OK) { + return VP8SetError(dec, status, "cannot parse partitions"); + } + + // quantizer change + VP8ParseQuant(dec); + + // Frame buffer marking + if (!frm_hdr->key_frame_) { + return VP8SetError(dec, VP8_STATUS_UNSUPPORTED_FEATURE, + "Not a key frame."); + } + + VP8Get(br, "global-header"); // ignore the value of update_proba_ + + VP8ParseProba(br, dec); + + // sanitized state + dec->ready_ = 1; + return 1; +} + +//------------------------------------------------------------------------------ +// Residual decoding (Paragraph 13.2 / 13.3) + +static const uint8_t kCat3[] = { 173, 148, 140, 0 }; +static const uint8_t kCat4[] = { 176, 155, 140, 135, 0 }; +static const uint8_t kCat5[] = { 180, 157, 141, 134, 130, 0 }; +static const uint8_t kCat6[] = + { 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0 }; +static const uint8_t* const kCat3456[] = { kCat3, kCat4, kCat5, kCat6 }; +static const uint8_t kZigzag[16] = { + 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15 +}; + +// See section 13-2: https://datatracker.ietf.org/doc/html/rfc6386#section-13.2 +static int GetLargeValue(VP8BitReader* const br, const uint8_t* const p) { + int v; + if (!VP8GetBit(br, p[3], "coeffs")) { + if (!VP8GetBit(br, p[4], "coeffs")) { + v = 2; + } else { + v = 3 + VP8GetBit(br, p[5], "coeffs"); + } + } else { + if (!VP8GetBit(br, p[6], "coeffs")) { + if (!VP8GetBit(br, p[7], "coeffs")) { + v = 5 + VP8GetBit(br, 159, "coeffs"); + } else { + v = 7 + 2 * VP8GetBit(br, 165, "coeffs"); + v += VP8GetBit(br, 145, "coeffs"); + } + } else { + const uint8_t* tab; + const int bit1 = VP8GetBit(br, p[8], "coeffs"); + const int bit0 = VP8GetBit(br, p[9 + bit1], "coeffs"); + const int cat = 2 * bit1 + bit0; + v = 0; + for (tab = kCat3456[cat]; *tab; ++tab) { + v += v + VP8GetBit(br, *tab, "coeffs"); + } + v += 3 + (8 << cat); + } + } + return v; +} + +// Returns the position of the last non-zero coeff plus one +static int GetCoeffsFast(VP8BitReader* const br, + const VP8BandProbas* const prob[], + int ctx, const quant_t dq, int n, int16_t* out) { + const uint8_t* p = prob[n]->probas_[ctx]; + for (; n < 16; ++n) { + if (!VP8GetBit(br, p[0], "coeffs")) { + return n; // previous coeff was last non-zero coeff + } + while (!VP8GetBit(br, p[1], "coeffs")) { // sequence of zero coeffs + p = prob[++n]->probas_[0]; + if (n == 16) return 16; + } + { // non zero coeff + const VP8ProbaArray* const p_ctx = &prob[n + 1]->probas_[0]; + int v; + if (!VP8GetBit(br, p[2], "coeffs")) { + v = 1; + p = p_ctx[1]; + } else { + v = GetLargeValue(br, p); + p = p_ctx[2]; + } + out[kZigzag[n]] = VP8GetSigned(br, v, "coeffs") * dq[n > 0]; + } + } + return 16; +} + +// This version of GetCoeffs() uses VP8GetBitAlt() which is an alternate version +// of VP8GetBitAlt() targeting specific platforms. +static int GetCoeffsAlt(VP8BitReader* const br, + const VP8BandProbas* const prob[], + int ctx, const quant_t dq, int n, int16_t* out) { + const uint8_t* p = prob[n]->probas_[ctx]; + for (; n < 16; ++n) { + if (!VP8GetBitAlt(br, p[0], "coeffs")) { + return n; // previous coeff was last non-zero coeff + } + while (!VP8GetBitAlt(br, p[1], "coeffs")) { // sequence of zero coeffs + p = prob[++n]->probas_[0]; + if (n == 16) return 16; + } + { // non zero coeff + const VP8ProbaArray* const p_ctx = &prob[n + 1]->probas_[0]; + int v; + if (!VP8GetBitAlt(br, p[2], "coeffs")) { + v = 1; + p = p_ctx[1]; + } else { + v = GetLargeValue(br, p); + p = p_ctx[2]; + } + out[kZigzag[n]] = VP8GetSigned(br, v, "coeffs") * dq[n > 0]; + } + } + return 16; +} + +extern VP8CPUInfo VP8GetCPUInfo; + +WEBP_DSP_INIT_FUNC(InitGetCoeffs) { + if (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kSlowSSSE3)) { + GetCoeffs = GetCoeffsAlt; + } else { + GetCoeffs = GetCoeffsFast; + } +} + +static WEBP_INLINE uint32_t NzCodeBits(uint32_t nz_coeffs, int nz, int dc_nz) { + nz_coeffs <<= 2; + nz_coeffs |= (nz > 3) ? 3 : (nz > 1) ? 2 : dc_nz; + return nz_coeffs; +} + +static int ParseResiduals(VP8Decoder* const dec, + VP8MB* const mb, VP8BitReader* const token_br) { + const VP8BandProbas* (* const bands)[16 + 1] = dec->proba_.bands_ptr_; + const VP8BandProbas* const * ac_proba; + VP8MBData* const block = dec->mb_data_ + dec->mb_x_; + const VP8QuantMatrix* const q = &dec->dqm_[block->segment_]; + int16_t* dst = block->coeffs_; + VP8MB* const left_mb = dec->mb_info_ - 1; + uint8_t tnz, lnz; + uint32_t non_zero_y = 0; + uint32_t non_zero_uv = 0; + int x, y, ch; + uint32_t out_t_nz, out_l_nz; + int first; + + memset(dst, 0, 384 * sizeof(*dst)); + if (!block->is_i4x4_) { // parse DC + int16_t dc[16] = { 0 }; + const int ctx = mb->nz_dc_ + left_mb->nz_dc_; + const int nz = GetCoeffs(token_br, bands[1], ctx, q->y2_mat_, 0, dc); + mb->nz_dc_ = left_mb->nz_dc_ = (nz > 0); + if (nz > 1) { // more than just the DC -> perform the full transform + VP8TransformWHT(dc, dst); + } else { // only DC is non-zero -> inlined simplified transform + int i; + const int dc0 = (dc[0] + 3) >> 3; + for (i = 0; i < 16 * 16; i += 16) dst[i] = dc0; + } + first = 1; + ac_proba = bands[0]; + } else { + first = 0; + ac_proba = bands[3]; + } + + tnz = mb->nz_ & 0x0f; + lnz = left_mb->nz_ & 0x0f; + for (y = 0; y < 4; ++y) { + int l = lnz & 1; + uint32_t nz_coeffs = 0; + for (x = 0; x < 4; ++x) { + const int ctx = l + (tnz & 1); + const int nz = GetCoeffs(token_br, ac_proba, ctx, q->y1_mat_, first, dst); + l = (nz > first); + tnz = (tnz >> 1) | (l << 7); + nz_coeffs = NzCodeBits(nz_coeffs, nz, dst[0] != 0); + dst += 16; + } + tnz >>= 4; + lnz = (lnz >> 1) | (l << 7); + non_zero_y = (non_zero_y << 8) | nz_coeffs; + } + out_t_nz = tnz; + out_l_nz = lnz >> 4; + + for (ch = 0; ch < 4; ch += 2) { + uint32_t nz_coeffs = 0; + tnz = mb->nz_ >> (4 + ch); + lnz = left_mb->nz_ >> (4 + ch); + for (y = 0; y < 2; ++y) { + int l = lnz & 1; + for (x = 0; x < 2; ++x) { + const int ctx = l + (tnz & 1); + const int nz = GetCoeffs(token_br, bands[2], ctx, q->uv_mat_, 0, dst); + l = (nz > 0); + tnz = (tnz >> 1) | (l << 3); + nz_coeffs = NzCodeBits(nz_coeffs, nz, dst[0] != 0); + dst += 16; + } + tnz >>= 2; + lnz = (lnz >> 1) | (l << 5); + } + // Note: we don't really need the per-4x4 details for U/V blocks. + non_zero_uv |= nz_coeffs << (4 * ch); + out_t_nz |= (tnz << 4) << ch; + out_l_nz |= (lnz & 0xf0) << ch; + } + mb->nz_ = out_t_nz; + left_mb->nz_ = out_l_nz; + + block->non_zero_y_ = non_zero_y; + block->non_zero_uv_ = non_zero_uv; + + // We look at the mode-code of each block and check if some blocks have less + // than three non-zero coeffs (code < 2). This is to avoid dithering flat and + // empty blocks. + block->dither_ = (non_zero_uv & 0xaaaa) ? 0 : q->dither_; + + return !(non_zero_y | non_zero_uv); // will be used for further optimization +} + +//------------------------------------------------------------------------------ +// Main loop + +int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br) { + VP8MB* const left = dec->mb_info_ - 1; + VP8MB* const mb = dec->mb_info_ + dec->mb_x_; + VP8MBData* const block = dec->mb_data_ + dec->mb_x_; + int skip = dec->use_skip_proba_ ? block->skip_ : 0; + + if (!skip) { + skip = ParseResiduals(dec, mb, token_br); + } else { + left->nz_ = mb->nz_ = 0; + if (!block->is_i4x4_) { + left->nz_dc_ = mb->nz_dc_ = 0; + } + block->non_zero_y_ = 0; + block->non_zero_uv_ = 0; + block->dither_ = 0; + } + + if (dec->filter_type_ > 0) { // store filter info + VP8FInfo* const finfo = dec->f_info_ + dec->mb_x_; + *finfo = dec->fstrengths_[block->segment_][block->is_i4x4_]; + finfo->f_inner_ |= !skip; + } + + return !token_br->eof_; +} + +void VP8InitScanline(VP8Decoder* const dec) { + VP8MB* const left = dec->mb_info_ - 1; + left->nz_ = 0; + left->nz_dc_ = 0; + memset(dec->intra_l_, B_DC_PRED, sizeof(dec->intra_l_)); + dec->mb_x_ = 0; +} + +static int ParseFrame(VP8Decoder* const dec, VP8Io* io) { + for (dec->mb_y_ = 0; dec->mb_y_ < dec->br_mb_y_; ++dec->mb_y_) { + // Parse bitstream for this row. + VP8BitReader* const token_br = + &dec->parts_[dec->mb_y_ & dec->num_parts_minus_one_]; + if (!VP8ParseIntraModeRow(&dec->br_, dec)) { + return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA, + "Premature end-of-partition0 encountered."); + } + for (; dec->mb_x_ < dec->mb_w_; ++dec->mb_x_) { + if (!VP8DecodeMB(dec, token_br)) { + return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA, + "Premature end-of-file encountered."); + } + } + VP8InitScanline(dec); // Prepare for next scanline + + // Reconstruct, filter and emit the row. + if (!VP8ProcessRow(dec, io)) { + return VP8SetError(dec, VP8_STATUS_USER_ABORT, "Output aborted."); + } + } + if (dec->mt_method_ > 0) { + if (!WebPGetWorkerInterface()->Sync(&dec->worker_)) return 0; + } + + return 1; +} + +// Main entry point +int VP8Decode(VP8Decoder* const dec, VP8Io* const io) { + int ok = 0; + if (dec == NULL) { + return 0; + } + if (io == NULL) { + return VP8SetError(dec, VP8_STATUS_INVALID_PARAM, + "NULL VP8Io parameter in VP8Decode()."); + } + + if (!dec->ready_) { + if (!VP8GetHeaders(dec, io)) { + return 0; + } + } + assert(dec->ready_); + + // Finish setting up the decoding parameter. Will call io->setup(). + ok = (VP8EnterCritical(dec, io) == VP8_STATUS_OK); + if (ok) { // good to go. + // Will allocate memory and prepare everything. + if (ok) ok = VP8InitFrame(dec, io); + + // Main decoding loop + if (ok) ok = ParseFrame(dec, io); + + // Exit. + ok &= VP8ExitCritical(dec, io); + } + + if (!ok) { + VP8Clear(dec); + return 0; + } + + dec->ready_ = 0; + return ok; +} + +void VP8Clear(VP8Decoder* const dec) { + if (dec == NULL) { + return; + } + WebPGetWorkerInterface()->End(&dec->worker_); + WebPDeallocateAlphaMemory(dec); + WebPSafeFree(dec->mem_); + dec->mem_ = NULL; + dec->mem_size_ = 0; + memset(&dec->br_, 0, sizeof(dec->br_)); + dec->ready_ = 0; +} + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/src/dec/vp8_dec.h b/third-party/webp/libwebp/src/dec/vp8_dec.h new file mode 100644 index 0000000000..a05405df72 --- /dev/null +++ b/third-party/webp/libwebp/src/dec/vp8_dec.h @@ -0,0 +1,185 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Low-level API for VP8 decoder +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_DEC_VP8_DEC_H_ +#define WEBP_DEC_VP8_DEC_H_ + +#include "src/webp/decode.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//------------------------------------------------------------------------------ +// Lower-level API +// +// These functions provide fine-grained control of the decoding process. +// The call flow should resemble: +// +// VP8Io io; +// VP8InitIo(&io); +// io.data = data; +// io.data_size = size; +// /* customize io's functions (setup()/put()/teardown()) if needed. */ +// +// VP8Decoder* dec = VP8New(); +// int ok = VP8Decode(dec, &io); +// if (!ok) printf("Error: %s\n", VP8StatusMessage(dec)); +// VP8Delete(dec); +// return ok; + +// Input / Output +typedef struct VP8Io VP8Io; +typedef int (*VP8IoPutHook)(const VP8Io* io); +typedef int (*VP8IoSetupHook)(VP8Io* io); +typedef void (*VP8IoTeardownHook)(const VP8Io* io); + +struct VP8Io { + // set by VP8GetHeaders() + int width, height; // picture dimensions, in pixels (invariable). + // These are the original, uncropped dimensions. + // The actual area passed to put() is stored + // in mb_w / mb_h fields. + + // set before calling put() + int mb_y; // position of the current rows (in pixels) + int mb_w; // number of columns in the sample + int mb_h; // number of rows in the sample + const uint8_t* y, *u, *v; // rows to copy (in yuv420 format) + int y_stride; // row stride for luma + int uv_stride; // row stride for chroma + + void* opaque; // user data + + // called when fresh samples are available. Currently, samples are in + // YUV420 format, and can be up to width x 24 in size (depending on the + // in-loop filtering level, e.g.). Should return false in case of error + // or abort request. The actual size of the area to update is mb_w x mb_h + // in size, taking cropping into account. + VP8IoPutHook put; + + // called just before starting to decode the blocks. + // Must return false in case of setup error, true otherwise. If false is + // returned, teardown() will NOT be called. But if the setup succeeded + // and true is returned, then teardown() will always be called afterward. + VP8IoSetupHook setup; + + // Called just after block decoding is finished (or when an error occurred + // during put()). Is NOT called if setup() failed. + VP8IoTeardownHook teardown; + + // this is a recommendation for the user-side yuv->rgb converter. This flag + // is set when calling setup() hook and can be overwritten by it. It then + // can be taken into consideration during the put() method. + int fancy_upsampling; + + // Input buffer. + size_t data_size; + const uint8_t* data; + + // If true, in-loop filtering will not be performed even if present in the + // bitstream. Switching off filtering may speed up decoding at the expense + // of more visible blocking. Note that output will also be non-compliant + // with the VP8 specifications. + int bypass_filtering; + + // Cropping parameters. + int use_cropping; + int crop_left, crop_right, crop_top, crop_bottom; + + // Scaling parameters. + int use_scaling; + int scaled_width, scaled_height; + + // If non NULL, pointer to the alpha data (if present) corresponding to the + // start of the current row (That is: it is pre-offset by mb_y and takes + // cropping into account). + const uint8_t* a; +}; + +// Internal, version-checked, entry point +int VP8InitIoInternal(VP8Io* const, int); + +// Set the custom IO function pointers and user-data. The setter for IO hooks +// should be called before initiating incremental decoding. Returns true if +// WebPIDecoder object is successfully modified, false otherwise. +int WebPISetIOHooks(WebPIDecoder* const idec, + VP8IoPutHook put, + VP8IoSetupHook setup, + VP8IoTeardownHook teardown, + void* user_data); + +// Main decoding object. This is an opaque structure. +typedef struct VP8Decoder VP8Decoder; + +// Create a new decoder object. +VP8Decoder* VP8New(void); + +// Must be called to make sure 'io' is initialized properly. +// Returns false in case of version mismatch. Upon such failure, no other +// decoding function should be called (VP8Decode, VP8GetHeaders, ...) +static WEBP_INLINE int VP8InitIo(VP8Io* const io) { + return VP8InitIoInternal(io, WEBP_DECODER_ABI_VERSION); +} + +// Decode the VP8 frame header. Returns true if ok. +// Note: 'io->data' must be pointing to the start of the VP8 frame header. +int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io); + +// Decode a picture. Will call VP8GetHeaders() if it wasn't done already. +// Returns false in case of error. +int VP8Decode(VP8Decoder* const dec, VP8Io* const io); + +// Return current status of the decoder: +VP8StatusCode VP8Status(VP8Decoder* const dec); + +// return readable string corresponding to the last status. +const char* VP8StatusMessage(VP8Decoder* const dec); + +// Resets the decoder in its initial state, reclaiming memory. +// Not a mandatory call between calls to VP8Decode(). +void VP8Clear(VP8Decoder* const dec); + +// Destroy the decoder object. +void VP8Delete(VP8Decoder* const dec); + +//------------------------------------------------------------------------------ +// Miscellaneous VP8/VP8L bitstream probing functions. + +// Returns true if the next 3 bytes in data contain the VP8 signature. +WEBP_EXTERN int VP8CheckSignature(const uint8_t* const data, size_t data_size); + +// Validates the VP8 data-header and retrieves basic header information viz +// width and height. Returns 0 in case of formatting error. *width/*height +// can be passed NULL. +WEBP_EXTERN int VP8GetInfo( + const uint8_t* data, + size_t data_size, // data available so far + size_t chunk_size, // total data size expected in the chunk + int* const width, int* const height); + +// Returns true if the next byte(s) in data is a VP8L signature. +WEBP_EXTERN int VP8LCheckSignature(const uint8_t* const data, size_t size); + +// Validates the VP8L data-header and retrieves basic header information viz +// width, height and alpha. Returns 0 in case of formatting error. +// width/height/has_alpha can be passed NULL. +WEBP_EXTERN int VP8LGetInfo( + const uint8_t* data, size_t data_size, // data available so far + int* const width, int* const height, int* const has_alpha); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_DEC_VP8_DEC_H_ diff --git a/third-party/webp/libwebp/src/dec/vp8i_dec.h b/third-party/webp/libwebp/src/dec/vp8i_dec.h new file mode 100644 index 0000000000..7929fd7506 --- /dev/null +++ b/third-party/webp/libwebp/src/dec/vp8i_dec.h @@ -0,0 +1,319 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// VP8 decoder: internal header. +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_DEC_VP8I_DEC_H_ +#define WEBP_DEC_VP8I_DEC_H_ + +#include // for memcpy() +#include "src/dec/common_dec.h" +#include "src/dec/vp8li_dec.h" +#include "src/utils/bit_reader_utils.h" +#include "src/utils/random_utils.h" +#include "src/utils/thread_utils.h" +#include "src/dsp/dsp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//------------------------------------------------------------------------------ +// Various defines and enums + +// version numbers +#define DEC_MAJ_VERSION 1 +#define DEC_MIN_VERSION 3 +#define DEC_REV_VERSION 2 + +// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline). +// Constraints are: We need to store one 16x16 block of luma samples (y), +// and two 8x8 chroma blocks (u/v). These are better be 16-bytes aligned, +// in order to be SIMD-friendly. We also need to store the top, left and +// top-left samples (from previously decoded blocks), along with four +// extra top-right samples for luma (intra4x4 prediction only). +// One possible layout is, using 32 * (17 + 9) bytes: +// +// .+------ <- only 1 pixel high +// .|yyyyt. +// .|yyyyt. +// .|yyyyt. +// .|yyyy.. +// .+--.+-- <- only 1 pixel high +// .|uu.|vv +// .|uu.|vv +// +// Every character is a 4x4 block, with legend: +// '.' = unused +// 'y' = y-samples 'u' = u-samples 'v' = u-samples +// '|' = left sample, '-' = top sample, '+' = top-left sample +// 't' = extra top-right sample for 4x4 modes +#define YUV_SIZE (BPS * 17 + BPS * 9) +#define Y_OFF (BPS * 1 + 8) +#define U_OFF (Y_OFF + BPS * 16 + BPS) +#define V_OFF (U_OFF + 16) + +// minimal width under which lossy multi-threading is always disabled +#define MIN_WIDTH_FOR_THREADS 512 + +//------------------------------------------------------------------------------ +// Headers + +typedef struct { + uint8_t key_frame_; + uint8_t profile_; + uint8_t show_; + uint32_t partition_length_; +} VP8FrameHeader; + +typedef struct { + uint16_t width_; + uint16_t height_; + uint8_t xscale_; + uint8_t yscale_; + uint8_t colorspace_; // 0 = YCbCr + uint8_t clamp_type_; +} VP8PictureHeader; + +// segment features +typedef struct { + int use_segment_; + int update_map_; // whether to update the segment map or not + int absolute_delta_; // absolute or delta values for quantizer and filter + int8_t quantizer_[NUM_MB_SEGMENTS]; // quantization changes + int8_t filter_strength_[NUM_MB_SEGMENTS]; // filter strength for segments +} VP8SegmentHeader; + +// probas associated to one of the contexts +typedef uint8_t VP8ProbaArray[NUM_PROBAS]; + +typedef struct { // all the probas associated to one band + VP8ProbaArray probas_[NUM_CTX]; +} VP8BandProbas; + +// Struct collecting all frame-persistent probabilities. +typedef struct { + uint8_t segments_[MB_FEATURE_TREE_PROBS]; + // Type: 0:Intra16-AC 1:Intra16-DC 2:Chroma 3:Intra4 + VP8BandProbas bands_[NUM_TYPES][NUM_BANDS]; + const VP8BandProbas* bands_ptr_[NUM_TYPES][16 + 1]; +} VP8Proba; + +// Filter parameters +typedef struct { + int simple_; // 0=complex, 1=simple + int level_; // [0..63] + int sharpness_; // [0..7] + int use_lf_delta_; + int ref_lf_delta_[NUM_REF_LF_DELTAS]; + int mode_lf_delta_[NUM_MODE_LF_DELTAS]; +} VP8FilterHeader; + +//------------------------------------------------------------------------------ +// Informations about the macroblocks. + +typedef struct { // filter specs + uint8_t f_limit_; // filter limit in [3..189], or 0 if no filtering + uint8_t f_ilevel_; // inner limit in [1..63] + uint8_t f_inner_; // do inner filtering? + uint8_t hev_thresh_; // high edge variance threshold in [0..2] +} VP8FInfo; + +typedef struct { // Top/Left Contexts used for syntax-parsing + uint8_t nz_; // non-zero AC/DC coeffs (4bit for luma + 4bit for chroma) + uint8_t nz_dc_; // non-zero DC coeff (1bit) +} VP8MB; + +// Dequantization matrices +typedef int quant_t[2]; // [DC / AC]. Can be 'uint16_t[2]' too (~slower). +typedef struct { + quant_t y1_mat_, y2_mat_, uv_mat_; + + int uv_quant_; // U/V quantizer value + int dither_; // dithering amplitude (0 = off, max=255) +} VP8QuantMatrix; + +// Data needed to reconstruct a macroblock +typedef struct { + int16_t coeffs_[384]; // 384 coeffs = (16+4+4) * 4*4 + uint8_t is_i4x4_; // true if intra4x4 + uint8_t imodes_[16]; // one 16x16 mode (#0) or sixteen 4x4 modes + uint8_t uvmode_; // chroma prediction mode + // bit-wise info about the content of each sub-4x4 blocks (in decoding order). + // Each of the 4x4 blocks for y/u/v is associated with a 2b code according to: + // code=0 -> no coefficient + // code=1 -> only DC + // code=2 -> first three coefficients are non-zero + // code=3 -> more than three coefficients are non-zero + // This allows to call specialized transform functions. + uint32_t non_zero_y_; + uint32_t non_zero_uv_; + uint8_t dither_; // local dithering strength (deduced from non_zero_*) + uint8_t skip_; + uint8_t segment_; +} VP8MBData; + +// Persistent information needed by the parallel processing +typedef struct { + int id_; // cache row to process (in [0..2]) + int mb_y_; // macroblock position of the row + int filter_row_; // true if row-filtering is needed + VP8FInfo* f_info_; // filter strengths (swapped with dec->f_info_) + VP8MBData* mb_data_; // reconstruction data (swapped with dec->mb_data_) + VP8Io io_; // copy of the VP8Io to pass to put() +} VP8ThreadContext; + +// Saved top samples, per macroblock. Fits into a cache-line. +typedef struct { + uint8_t y[16], u[8], v[8]; +} VP8TopSamples; + +//------------------------------------------------------------------------------ +// VP8Decoder: the main opaque structure handed over to user + +struct VP8Decoder { + VP8StatusCode status_; + int ready_; // true if ready to decode a picture with VP8Decode() + const char* error_msg_; // set when status_ is not OK. + + // Main data source + VP8BitReader br_; + + // headers + VP8FrameHeader frm_hdr_; + VP8PictureHeader pic_hdr_; + VP8FilterHeader filter_hdr_; + VP8SegmentHeader segment_hdr_; + + // Worker + WebPWorker worker_; + int mt_method_; // multi-thread method: 0=off, 1=[parse+recon][filter] + // 2=[parse][recon+filter] + int cache_id_; // current cache row + int num_caches_; // number of cached rows of 16 pixels (1, 2 or 3) + VP8ThreadContext thread_ctx_; // Thread context + + // dimension, in macroblock units. + int mb_w_, mb_h_; + + // Macroblock to process/filter, depending on cropping and filter_type. + int tl_mb_x_, tl_mb_y_; // top-left MB that must be in-loop filtered + int br_mb_x_, br_mb_y_; // last bottom-right MB that must be decoded + + // number of partitions minus one. + uint32_t num_parts_minus_one_; + // per-partition boolean decoders. + VP8BitReader parts_[MAX_NUM_PARTITIONS]; + + // Dithering strength, deduced from decoding options + int dither_; // whether to use dithering or not + VP8Random dithering_rg_; // random generator for dithering + + // dequantization (one set of DC/AC dequant factor per segment) + VP8QuantMatrix dqm_[NUM_MB_SEGMENTS]; + + // probabilities + VP8Proba proba_; + int use_skip_proba_; + uint8_t skip_p_; + + // Boundary data cache and persistent buffers. + uint8_t* intra_t_; // top intra modes values: 4 * mb_w_ + uint8_t intra_l_[4]; // left intra modes values + + VP8TopSamples* yuv_t_; // top y/u/v samples + + VP8MB* mb_info_; // contextual macroblock info (mb_w_ + 1) + VP8FInfo* f_info_; // filter strength info + uint8_t* yuv_b_; // main block for Y/U/V (size = YUV_SIZE) + + uint8_t* cache_y_; // macroblock row for storing unfiltered samples + uint8_t* cache_u_; + uint8_t* cache_v_; + int cache_y_stride_; + int cache_uv_stride_; + + // main memory chunk for the above data. Persistent. + void* mem_; + size_t mem_size_; + + // Per macroblock non-persistent infos. + int mb_x_, mb_y_; // current position, in macroblock units + VP8MBData* mb_data_; // parsed reconstruction data + + // Filtering side-info + int filter_type_; // 0=off, 1=simple, 2=complex + VP8FInfo fstrengths_[NUM_MB_SEGMENTS][2]; // precalculated per-segment/type + + // Alpha + struct ALPHDecoder* alph_dec_; // alpha-plane decoder object + const uint8_t* alpha_data_; // compressed alpha data (if present) + size_t alpha_data_size_; + int is_alpha_decoded_; // true if alpha_data_ is decoded in alpha_plane_ + uint8_t* alpha_plane_mem_; // memory allocated for alpha_plane_ + uint8_t* alpha_plane_; // output. Persistent, contains the whole data. + const uint8_t* alpha_prev_line_; // last decoded alpha row (or NULL) + int alpha_dithering_; // derived from decoding options (0=off, 100=full) +}; + +//------------------------------------------------------------------------------ +// internal functions. Not public. + +// in vp8.c +int VP8SetError(VP8Decoder* const dec, + VP8StatusCode error, const char* const msg); + +// in tree.c +void VP8ResetProba(VP8Proba* const proba); +void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec); +// parses one row of intra mode data in partition 0, returns !eof +int VP8ParseIntraModeRow(VP8BitReader* const br, VP8Decoder* const dec); + +// in quant.c +void VP8ParseQuant(VP8Decoder* const dec); + +// in frame.c +int VP8InitFrame(VP8Decoder* const dec, VP8Io* const io); +// Call io->setup() and finish setting up scan parameters. +// After this call returns, one must always call VP8ExitCritical() with the +// same parameters. Both functions should be used in pair. Returns VP8_STATUS_OK +// if ok, otherwise sets and returns the error status on *dec. +VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io); +// Must always be called in pair with VP8EnterCritical(). +// Returns false in case of error. +int VP8ExitCritical(VP8Decoder* const dec, VP8Io* const io); +// Return the multi-threading method to use (0=off), depending +// on options and bitstream size. Only for lossy decoding. +int VP8GetThreadMethod(const WebPDecoderOptions* const options, + const WebPHeaderStructure* const headers, + int width, int height); +// Initialize dithering post-process if needed. +void VP8InitDithering(const WebPDecoderOptions* const options, + VP8Decoder* const dec); +// Process the last decoded row (filtering + output). +int VP8ProcessRow(VP8Decoder* const dec, VP8Io* const io); +// To be called at the start of a new scanline, to initialize predictors. +void VP8InitScanline(VP8Decoder* const dec); +// Decode one macroblock. Returns false if there is not enough data. +int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br); + +// in alpha.c +const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, + const VP8Io* const io, + int row, int num_rows); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_DEC_VP8I_DEC_H_ diff --git a/third-party/webp/libwebp/src/dec/vp8l_dec.c b/third-party/webp/libwebp/src/dec/vp8l_dec.c new file mode 100644 index 0000000000..11c00ea964 --- /dev/null +++ b/third-party/webp/libwebp/src/dec/vp8l_dec.c @@ -0,0 +1,1778 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// main entry for the decoder +// +// Authors: Vikas Arora (vikaas.arora@gmail.com) +// Jyrki Alakuijala (jyrki@google.com) + +#include +#include + +#include "src/dec/alphai_dec.h" +#include "src/dec/vp8li_dec.h" +#include "src/dsp/dsp.h" +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" +#include "src/dsp/yuv.h" +#include "src/utils/endian_inl_utils.h" +#include "src/utils/huffman_utils.h" +#include "src/utils/utils.h" + +#define NUM_ARGB_CACHE_ROWS 16 + +static const int kCodeLengthLiterals = 16; +static const int kCodeLengthRepeatCode = 16; +static const uint8_t kCodeLengthExtraBits[3] = { 2, 3, 7 }; +static const uint8_t kCodeLengthRepeatOffsets[3] = { 3, 3, 11 }; + +// ----------------------------------------------------------------------------- +// Five Huffman codes are used at each meta code: +// 1. green + length prefix codes + color cache codes, +// 2. alpha, +// 3. red, +// 4. blue, and, +// 5. distance prefix codes. +typedef enum { + GREEN = 0, + RED = 1, + BLUE = 2, + ALPHA = 3, + DIST = 4 +} HuffIndex; + +static const uint16_t kAlphabetSize[HUFFMAN_CODES_PER_META_CODE] = { + NUM_LITERAL_CODES + NUM_LENGTH_CODES, + NUM_LITERAL_CODES, NUM_LITERAL_CODES, NUM_LITERAL_CODES, + NUM_DISTANCE_CODES +}; + +static const uint8_t kLiteralMap[HUFFMAN_CODES_PER_META_CODE] = { + 0, 1, 1, 1, 0 +}; + +#define NUM_CODE_LENGTH_CODES 19 +static const uint8_t kCodeLengthCodeOrder[NUM_CODE_LENGTH_CODES] = { + 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +}; + +#define CODE_TO_PLANE_CODES 120 +static const uint8_t kCodeToPlane[CODE_TO_PLANE_CODES] = { + 0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a, + 0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a, + 0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b, + 0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03, + 0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c, + 0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e, + 0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b, + 0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f, + 0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b, + 0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41, + 0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f, + 0x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70 +}; + +// Memory needed for lookup tables of one Huffman tree group. Red, blue, alpha +// and distance alphabets are constant (256 for red, blue and alpha, 40 for +// distance) and lookup table sizes for them in worst case are 630 and 410 +// respectively. Size of green alphabet depends on color cache size and is equal +// to 256 (green component values) + 24 (length prefix values) +// + color_cache_size (between 0 and 2048). +// All values computed for 8-bit first level lookup with Mark Adler's tool: +// https://github.com/madler/zlib/blob/v1.2.5/examples/enough.c +#define FIXED_TABLE_SIZE (630 * 3 + 410) +static const uint16_t kTableSize[12] = { + FIXED_TABLE_SIZE + 654, + FIXED_TABLE_SIZE + 656, + FIXED_TABLE_SIZE + 658, + FIXED_TABLE_SIZE + 662, + FIXED_TABLE_SIZE + 670, + FIXED_TABLE_SIZE + 686, + FIXED_TABLE_SIZE + 718, + FIXED_TABLE_SIZE + 782, + FIXED_TABLE_SIZE + 912, + FIXED_TABLE_SIZE + 1168, + FIXED_TABLE_SIZE + 1680, + FIXED_TABLE_SIZE + 2704 +}; + +static int VP8LSetError(VP8LDecoder* const dec, VP8StatusCode error) { + // The oldest error reported takes precedence over the new one. + if (dec->status_ == VP8_STATUS_OK || dec->status_ == VP8_STATUS_SUSPENDED) { + dec->status_ = error; + } + return 0; +} + +static int DecodeImageStream(int xsize, int ysize, + int is_level0, + VP8LDecoder* const dec, + uint32_t** const decoded_data); + +//------------------------------------------------------------------------------ + +int VP8LCheckSignature(const uint8_t* const data, size_t size) { + return (size >= VP8L_FRAME_HEADER_SIZE && + data[0] == VP8L_MAGIC_BYTE && + (data[4] >> 5) == 0); // version +} + +static int ReadImageInfo(VP8LBitReader* const br, + int* const width, int* const height, + int* const has_alpha) { + if (VP8LReadBits(br, 8) != VP8L_MAGIC_BYTE) return 0; + *width = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1; + *height = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1; + *has_alpha = VP8LReadBits(br, 1); + if (VP8LReadBits(br, VP8L_VERSION_BITS) != 0) return 0; + return !br->eos_; +} + +int VP8LGetInfo(const uint8_t* data, size_t data_size, + int* const width, int* const height, int* const has_alpha) { + if (data == NULL || data_size < VP8L_FRAME_HEADER_SIZE) { + return 0; // not enough data + } else if (!VP8LCheckSignature(data, data_size)) { + return 0; // bad signature + } else { + int w, h, a; + VP8LBitReader br; + VP8LInitBitReader(&br, data, data_size); + if (!ReadImageInfo(&br, &w, &h, &a)) { + return 0; + } + if (width != NULL) *width = w; + if (height != NULL) *height = h; + if (has_alpha != NULL) *has_alpha = a; + return 1; + } +} + +//------------------------------------------------------------------------------ + +static WEBP_INLINE int GetCopyDistance(int distance_symbol, + VP8LBitReader* const br) { + int extra_bits, offset; + if (distance_symbol < 4) { + return distance_symbol + 1; + } + extra_bits = (distance_symbol - 2) >> 1; + offset = (2 + (distance_symbol & 1)) << extra_bits; + return offset + VP8LReadBits(br, extra_bits) + 1; +} + +static WEBP_INLINE int GetCopyLength(int length_symbol, + VP8LBitReader* const br) { + // Length and distance prefixes are encoded the same way. + return GetCopyDistance(length_symbol, br); +} + +static WEBP_INLINE int PlaneCodeToDistance(int xsize, int plane_code) { + if (plane_code > CODE_TO_PLANE_CODES) { + return plane_code - CODE_TO_PLANE_CODES; + } else { + const int dist_code = kCodeToPlane[plane_code - 1]; + const int yoffset = dist_code >> 4; + const int xoffset = 8 - (dist_code & 0xf); + const int dist = yoffset * xsize + xoffset; + return (dist >= 1) ? dist : 1; // dist<1 can happen if xsize is very small + } +} + +//------------------------------------------------------------------------------ +// Decodes the next Huffman code from bit-stream. +// VP8LFillBitWindow(br) needs to be called at minimum every second call +// to ReadSymbol, in order to pre-fetch enough bits. +static WEBP_INLINE int ReadSymbol(const HuffmanCode* table, + VP8LBitReader* const br) { + int nbits; + uint32_t val = VP8LPrefetchBits(br); + table += val & HUFFMAN_TABLE_MASK; + nbits = table->bits - HUFFMAN_TABLE_BITS; + if (nbits > 0) { + VP8LSetBitPos(br, br->bit_pos_ + HUFFMAN_TABLE_BITS); + val = VP8LPrefetchBits(br); + table += table->value; + table += val & ((1 << nbits) - 1); + } + VP8LSetBitPos(br, br->bit_pos_ + table->bits); + return table->value; +} + +// Reads packed symbol depending on GREEN channel +#define BITS_SPECIAL_MARKER 0x100 // something large enough (and a bit-mask) +#define PACKED_NON_LITERAL_CODE 0 // must be < NUM_LITERAL_CODES +static WEBP_INLINE int ReadPackedSymbols(const HTreeGroup* group, + VP8LBitReader* const br, + uint32_t* const dst) { + const uint32_t val = VP8LPrefetchBits(br) & (HUFFMAN_PACKED_TABLE_SIZE - 1); + const HuffmanCode32 code = group->packed_table[val]; + assert(group->use_packed_table); + if (code.bits < BITS_SPECIAL_MARKER) { + VP8LSetBitPos(br, br->bit_pos_ + code.bits); + *dst = code.value; + return PACKED_NON_LITERAL_CODE; + } else { + VP8LSetBitPos(br, br->bit_pos_ + code.bits - BITS_SPECIAL_MARKER); + assert(code.value >= NUM_LITERAL_CODES); + return code.value; + } +} + +static int AccumulateHCode(HuffmanCode hcode, int shift, + HuffmanCode32* const huff) { + huff->bits += hcode.bits; + huff->value |= (uint32_t)hcode.value << shift; + assert(huff->bits <= HUFFMAN_TABLE_BITS); + return hcode.bits; +} + +static void BuildPackedTable(HTreeGroup* const htree_group) { + uint32_t code; + for (code = 0; code < HUFFMAN_PACKED_TABLE_SIZE; ++code) { + uint32_t bits = code; + HuffmanCode32* const huff = &htree_group->packed_table[bits]; + HuffmanCode hcode = htree_group->htrees[GREEN][bits]; + if (hcode.value >= NUM_LITERAL_CODES) { + huff->bits = hcode.bits + BITS_SPECIAL_MARKER; + huff->value = hcode.value; + } else { + huff->bits = 0; + huff->value = 0; + bits >>= AccumulateHCode(hcode, 8, huff); + bits >>= AccumulateHCode(htree_group->htrees[RED][bits], 16, huff); + bits >>= AccumulateHCode(htree_group->htrees[BLUE][bits], 0, huff); + bits >>= AccumulateHCode(htree_group->htrees[ALPHA][bits], 24, huff); + (void)bits; + } + } +} + +static int ReadHuffmanCodeLengths( + VP8LDecoder* const dec, const int* const code_length_code_lengths, + int num_symbols, int* const code_lengths) { + int ok = 0; + VP8LBitReader* const br = &dec->br_; + int symbol; + int max_symbol; + int prev_code_len = DEFAULT_CODE_LENGTH; + HuffmanTables tables; + + if (!VP8LHuffmanTablesAllocate(1 << LENGTHS_TABLE_BITS, &tables) || + !VP8LBuildHuffmanTable(&tables, LENGTHS_TABLE_BITS, + code_length_code_lengths, NUM_CODE_LENGTH_CODES)) { + goto End; + } + + if (VP8LReadBits(br, 1)) { // use length + const int length_nbits = 2 + 2 * VP8LReadBits(br, 3); + max_symbol = 2 + VP8LReadBits(br, length_nbits); + if (max_symbol > num_symbols) { + goto End; + } + } else { + max_symbol = num_symbols; + } + + symbol = 0; + while (symbol < num_symbols) { + const HuffmanCode* p; + int code_len; + if (max_symbol-- == 0) break; + VP8LFillBitWindow(br); + p = &tables.curr_segment->start[VP8LPrefetchBits(br) & LENGTHS_TABLE_MASK]; + VP8LSetBitPos(br, br->bit_pos_ + p->bits); + code_len = p->value; + if (code_len < kCodeLengthLiterals) { + code_lengths[symbol++] = code_len; + if (code_len != 0) prev_code_len = code_len; + } else { + const int use_prev = (code_len == kCodeLengthRepeatCode); + const int slot = code_len - kCodeLengthLiterals; + const int extra_bits = kCodeLengthExtraBits[slot]; + const int repeat_offset = kCodeLengthRepeatOffsets[slot]; + int repeat = VP8LReadBits(br, extra_bits) + repeat_offset; + if (symbol + repeat > num_symbols) { + goto End; + } else { + const int length = use_prev ? prev_code_len : 0; + while (repeat-- > 0) code_lengths[symbol++] = length; + } + } + } + ok = 1; + + End: + VP8LHuffmanTablesDeallocate(&tables); + if (!ok) return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR); + return ok; +} + +// 'code_lengths' is pre-allocated temporary buffer, used for creating Huffman +// tree. +static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec, + int* const code_lengths, + HuffmanTables* const table) { + int ok = 0; + int size = 0; + VP8LBitReader* const br = &dec->br_; + const int simple_code = VP8LReadBits(br, 1); + + memset(code_lengths, 0, alphabet_size * sizeof(*code_lengths)); + + if (simple_code) { // Read symbols, codes & code lengths directly. + const int num_symbols = VP8LReadBits(br, 1) + 1; + const int first_symbol_len_code = VP8LReadBits(br, 1); + // The first code is either 1 bit or 8 bit code. + int symbol = VP8LReadBits(br, (first_symbol_len_code == 0) ? 1 : 8); + code_lengths[symbol] = 1; + // The second code (if present), is always 8 bits long. + if (num_symbols == 2) { + symbol = VP8LReadBits(br, 8); + code_lengths[symbol] = 1; + } + ok = 1; + } else { // Decode Huffman-coded code lengths. + int i; + int code_length_code_lengths[NUM_CODE_LENGTH_CODES] = { 0 }; + const int num_codes = VP8LReadBits(br, 4) + 4; + assert(num_codes <= NUM_CODE_LENGTH_CODES); + + for (i = 0; i < num_codes; ++i) { + code_length_code_lengths[kCodeLengthCodeOrder[i]] = VP8LReadBits(br, 3); + } + ok = ReadHuffmanCodeLengths(dec, code_length_code_lengths, alphabet_size, + code_lengths); + } + + ok = ok && !br->eos_; + if (ok) { + size = VP8LBuildHuffmanTable(table, HUFFMAN_TABLE_BITS, + code_lengths, alphabet_size); + } + if (!ok || size == 0) { + return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR); + } + return size; +} + +static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize, + int color_cache_bits, int allow_recursion) { + int i; + VP8LBitReader* const br = &dec->br_; + VP8LMetadata* const hdr = &dec->hdr_; + uint32_t* huffman_image = NULL; + HTreeGroup* htree_groups = NULL; + HuffmanTables* huffman_tables = &hdr->huffman_tables_; + int num_htree_groups = 1; + int num_htree_groups_max = 1; + int* mapping = NULL; + int ok = 0; + + // Check the table has been 0 initialized (through InitMetadata). + assert(huffman_tables->root.start == NULL); + assert(huffman_tables->curr_segment == NULL); + + if (allow_recursion && VP8LReadBits(br, 1)) { + // use meta Huffman codes. + const int huffman_precision = VP8LReadBits(br, 3) + 2; + const int huffman_xsize = VP8LSubSampleSize(xsize, huffman_precision); + const int huffman_ysize = VP8LSubSampleSize(ysize, huffman_precision); + const int huffman_pixs = huffman_xsize * huffman_ysize; + if (!DecodeImageStream(huffman_xsize, huffman_ysize, /*is_level0=*/0, dec, + &huffman_image)) { + goto Error; + } + hdr->huffman_subsample_bits_ = huffman_precision; + for (i = 0; i < huffman_pixs; ++i) { + // The huffman data is stored in red and green bytes. + const int group = (huffman_image[i] >> 8) & 0xffff; + huffman_image[i] = group; + if (group >= num_htree_groups_max) { + num_htree_groups_max = group + 1; + } + } + // Check the validity of num_htree_groups_max. If it seems too big, use a + // smaller value for later. This will prevent big memory allocations to end + // up with a bad bitstream anyway. + // The value of 1000 is totally arbitrary. We know that num_htree_groups_max + // is smaller than (1 << 16) and should be smaller than the number of pixels + // (though the format allows it to be bigger). + if (num_htree_groups_max > 1000 || num_htree_groups_max > xsize * ysize) { + // Create a mapping from the used indices to the minimal set of used + // values [0, num_htree_groups) + mapping = (int*)WebPSafeMalloc(num_htree_groups_max, sizeof(*mapping)); + if (mapping == NULL) { + VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY); + goto Error; + } + // -1 means a value is unmapped, and therefore unused in the Huffman + // image. + memset(mapping, 0xff, num_htree_groups_max * sizeof(*mapping)); + for (num_htree_groups = 0, i = 0; i < huffman_pixs; ++i) { + // Get the current mapping for the group and remap the Huffman image. + int* const mapped_group = &mapping[huffman_image[i]]; + if (*mapped_group == -1) *mapped_group = num_htree_groups++; + huffman_image[i] = *mapped_group; + } + } else { + num_htree_groups = num_htree_groups_max; + } + } + + if (br->eos_) goto Error; + + if (!ReadHuffmanCodesHelper(color_cache_bits, num_htree_groups, + num_htree_groups_max, mapping, dec, + huffman_tables, &htree_groups)) { + goto Error; + } + ok = 1; + + // All OK. Finalize pointers. + hdr->huffman_image_ = huffman_image; + hdr->num_htree_groups_ = num_htree_groups; + hdr->htree_groups_ = htree_groups; + + Error: + WebPSafeFree(mapping); + if (!ok) { + WebPSafeFree(huffman_image); + VP8LHuffmanTablesDeallocate(huffman_tables); + VP8LHtreeGroupsFree(htree_groups); + } + return ok; +} + +int ReadHuffmanCodesHelper(int color_cache_bits, int num_htree_groups, + int num_htree_groups_max, const int* const mapping, + VP8LDecoder* const dec, + HuffmanTables* const huffman_tables, + HTreeGroup** const htree_groups) { + int i, j, ok = 0; + const int max_alphabet_size = + kAlphabetSize[0] + ((color_cache_bits > 0) ? 1 << color_cache_bits : 0); + const int table_size = kTableSize[color_cache_bits]; + int* code_lengths = NULL; + + if ((mapping == NULL && num_htree_groups != num_htree_groups_max) || + num_htree_groups > num_htree_groups_max) { + goto Error; + } + + code_lengths = + (int*)WebPSafeCalloc((uint64_t)max_alphabet_size, sizeof(*code_lengths)); + *htree_groups = VP8LHtreeGroupsNew(num_htree_groups); + + if (*htree_groups == NULL || code_lengths == NULL || + !VP8LHuffmanTablesAllocate(num_htree_groups * table_size, + huffman_tables)) { + VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY); + goto Error; + } + + for (i = 0; i < num_htree_groups_max; ++i) { + // If the index "i" is unused in the Huffman image, just make sure the + // coefficients are valid but do not store them. + if (mapping != NULL && mapping[i] == -1) { + for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) { + int alphabet_size = kAlphabetSize[j]; + if (j == 0 && color_cache_bits > 0) { + alphabet_size += (1 << color_cache_bits); + } + // Passing in NULL so that nothing gets filled. + if (!ReadHuffmanCode(alphabet_size, dec, code_lengths, NULL)) { + goto Error; + } + } + } else { + HTreeGroup* const htree_group = + &(*htree_groups)[(mapping == NULL) ? i : mapping[i]]; + HuffmanCode** const htrees = htree_group->htrees; + int size; + int total_size = 0; + int is_trivial_literal = 1; + int max_bits = 0; + for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) { + int alphabet_size = kAlphabetSize[j]; + if (j == 0 && color_cache_bits > 0) { + alphabet_size += (1 << color_cache_bits); + } + size = + ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_tables); + htrees[j] = huffman_tables->curr_segment->curr_table; + if (size == 0) { + goto Error; + } + if (is_trivial_literal && kLiteralMap[j] == 1) { + is_trivial_literal = (htrees[j]->bits == 0); + } + total_size += htrees[j]->bits; + huffman_tables->curr_segment->curr_table += size; + if (j <= ALPHA) { + int local_max_bits = code_lengths[0]; + int k; + for (k = 1; k < alphabet_size; ++k) { + if (code_lengths[k] > local_max_bits) { + local_max_bits = code_lengths[k]; + } + } + max_bits += local_max_bits; + } + } + htree_group->is_trivial_literal = is_trivial_literal; + htree_group->is_trivial_code = 0; + if (is_trivial_literal) { + const int red = htrees[RED][0].value; + const int blue = htrees[BLUE][0].value; + const int alpha = htrees[ALPHA][0].value; + htree_group->literal_arb = ((uint32_t)alpha << 24) | (red << 16) | blue; + if (total_size == 0 && htrees[GREEN][0].value < NUM_LITERAL_CODES) { + htree_group->is_trivial_code = 1; + htree_group->literal_arb |= htrees[GREEN][0].value << 8; + } + } + htree_group->use_packed_table = + !htree_group->is_trivial_code && (max_bits < HUFFMAN_PACKED_BITS); + if (htree_group->use_packed_table) BuildPackedTable(htree_group); + } + } + ok = 1; + + Error: + WebPSafeFree(code_lengths); + if (!ok) { + VP8LHuffmanTablesDeallocate(huffman_tables); + VP8LHtreeGroupsFree(*htree_groups); + *htree_groups = NULL; + } + return ok; +} + +//------------------------------------------------------------------------------ +// Scaling. + +#if !defined(WEBP_REDUCE_SIZE) +static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) { + const int num_channels = 4; + const int in_width = io->mb_w; + const int out_width = io->scaled_width; + const int in_height = io->mb_h; + const int out_height = io->scaled_height; + const uint64_t work_size = 2 * num_channels * (uint64_t)out_width; + rescaler_t* work; // Rescaler work area. + const uint64_t scaled_data_size = (uint64_t)out_width; + uint32_t* scaled_data; // Temporary storage for scaled BGRA data. + const uint64_t memory_size = sizeof(*dec->rescaler) + + work_size * sizeof(*work) + + scaled_data_size * sizeof(*scaled_data); + uint8_t* memory = (uint8_t*)WebPSafeMalloc(memory_size, sizeof(*memory)); + if (memory == NULL) { + return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY); + } + assert(dec->rescaler_memory == NULL); + dec->rescaler_memory = memory; + + dec->rescaler = (WebPRescaler*)memory; + memory += sizeof(*dec->rescaler); + work = (rescaler_t*)memory; + memory += work_size * sizeof(*work); + scaled_data = (uint32_t*)memory; + + if (!WebPRescalerInit(dec->rescaler, in_width, in_height, + (uint8_t*)scaled_data, out_width, out_height, + 0, num_channels, work)) { + return 0; + } + return 1; +} +#endif // WEBP_REDUCE_SIZE + +//------------------------------------------------------------------------------ +// Export to ARGB + +#if !defined(WEBP_REDUCE_SIZE) + +// We have special "export" function since we need to convert from BGRA +static int Export(WebPRescaler* const rescaler, WEBP_CSP_MODE colorspace, + int rgba_stride, uint8_t* const rgba) { + uint32_t* const src = (uint32_t*)rescaler->dst; + uint8_t* dst = rgba; + const int dst_width = rescaler->dst_width; + int num_lines_out = 0; + while (WebPRescalerHasPendingOutput(rescaler)) { + WebPRescalerExportRow(rescaler); + WebPMultARGBRow(src, dst_width, 1); + VP8LConvertFromBGRA(src, dst_width, colorspace, dst); + dst += rgba_stride; + ++num_lines_out; + } + return num_lines_out; +} + +// Emit scaled rows. +static int EmitRescaledRowsRGBA(const VP8LDecoder* const dec, + uint8_t* in, int in_stride, int mb_h, + uint8_t* const out, int out_stride) { + const WEBP_CSP_MODE colorspace = dec->output_->colorspace; + int num_lines_in = 0; + int num_lines_out = 0; + while (num_lines_in < mb_h) { + uint8_t* const row_in = in + (uint64_t)num_lines_in * in_stride; + uint8_t* const row_out = out + (uint64_t)num_lines_out * out_stride; + const int lines_left = mb_h - num_lines_in; + const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left); + int lines_imported; + assert(needed_lines > 0 && needed_lines <= lines_left); + WebPMultARGBRows(row_in, in_stride, + dec->rescaler->src_width, needed_lines, 0); + lines_imported = + WebPRescalerImport(dec->rescaler, lines_left, row_in, in_stride); + assert(lines_imported == needed_lines); + num_lines_in += lines_imported; + num_lines_out += Export(dec->rescaler, colorspace, out_stride, row_out); + } + return num_lines_out; +} + +#endif // WEBP_REDUCE_SIZE + +// Emit rows without any scaling. +static int EmitRows(WEBP_CSP_MODE colorspace, + const uint8_t* row_in, int in_stride, + int mb_w, int mb_h, + uint8_t* const out, int out_stride) { + int lines = mb_h; + uint8_t* row_out = out; + while (lines-- > 0) { + VP8LConvertFromBGRA((const uint32_t*)row_in, mb_w, colorspace, row_out); + row_in += in_stride; + row_out += out_stride; + } + return mb_h; // Num rows out == num rows in. +} + +//------------------------------------------------------------------------------ +// Export to YUVA + +static void ConvertToYUVA(const uint32_t* const src, int width, int y_pos, + const WebPDecBuffer* const output) { + const WebPYUVABuffer* const buf = &output->u.YUVA; + + // first, the luma plane + WebPConvertARGBToY(src, buf->y + y_pos * buf->y_stride, width); + + // then U/V planes + { + uint8_t* const u = buf->u + (y_pos >> 1) * buf->u_stride; + uint8_t* const v = buf->v + (y_pos >> 1) * buf->v_stride; + // even lines: store values + // odd lines: average with previous values + WebPConvertARGBToUV(src, u, v, width, !(y_pos & 1)); + } + // Lastly, store alpha if needed. + if (buf->a != NULL) { + uint8_t* const a = buf->a + y_pos * buf->a_stride; +#if defined(WORDS_BIGENDIAN) + WebPExtractAlpha((uint8_t*)src + 0, 0, width, 1, a, 0); +#else + WebPExtractAlpha((uint8_t*)src + 3, 0, width, 1, a, 0); +#endif + } +} + +static int ExportYUVA(const VP8LDecoder* const dec, int y_pos) { + WebPRescaler* const rescaler = dec->rescaler; + uint32_t* const src = (uint32_t*)rescaler->dst; + const int dst_width = rescaler->dst_width; + int num_lines_out = 0; + while (WebPRescalerHasPendingOutput(rescaler)) { + WebPRescalerExportRow(rescaler); + WebPMultARGBRow(src, dst_width, 1); + ConvertToYUVA(src, dst_width, y_pos, dec->output_); + ++y_pos; + ++num_lines_out; + } + return num_lines_out; +} + +static int EmitRescaledRowsYUVA(const VP8LDecoder* const dec, + uint8_t* in, int in_stride, int mb_h) { + int num_lines_in = 0; + int y_pos = dec->last_out_row_; + while (num_lines_in < mb_h) { + const int lines_left = mb_h - num_lines_in; + const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left); + int lines_imported; + WebPMultARGBRows(in, in_stride, dec->rescaler->src_width, needed_lines, 0); + lines_imported = + WebPRescalerImport(dec->rescaler, lines_left, in, in_stride); + assert(lines_imported == needed_lines); + num_lines_in += lines_imported; + in += needed_lines * in_stride; + y_pos += ExportYUVA(dec, y_pos); + } + return y_pos; +} + +static int EmitRowsYUVA(const VP8LDecoder* const dec, + const uint8_t* in, int in_stride, + int mb_w, int num_rows) { + int y_pos = dec->last_out_row_; + while (num_rows-- > 0) { + ConvertToYUVA((const uint32_t*)in, mb_w, y_pos, dec->output_); + in += in_stride; + ++y_pos; + } + return y_pos; +} + +//------------------------------------------------------------------------------ +// Cropping. + +// Sets io->mb_y, io->mb_h & io->mb_w according to start row, end row and +// crop options. Also updates the input data pointer, so that it points to the +// start of the cropped window. Note that pixels are in ARGB format even if +// 'in_data' is uint8_t*. +// Returns true if the crop window is not empty. +static int SetCropWindow(VP8Io* const io, int y_start, int y_end, + uint8_t** const in_data, int pixel_stride) { + assert(y_start < y_end); + assert(io->crop_left < io->crop_right); + if (y_end > io->crop_bottom) { + y_end = io->crop_bottom; // make sure we don't overflow on last row. + } + if (y_start < io->crop_top) { + const int delta = io->crop_top - y_start; + y_start = io->crop_top; + *in_data += delta * pixel_stride; + } + if (y_start >= y_end) return 0; // Crop window is empty. + + *in_data += io->crop_left * sizeof(uint32_t); + + io->mb_y = y_start - io->crop_top; + io->mb_w = io->crop_right - io->crop_left; + io->mb_h = y_end - y_start; + return 1; // Non-empty crop window. +} + +//------------------------------------------------------------------------------ + +static WEBP_INLINE int GetMetaIndex( + const uint32_t* const image, int xsize, int bits, int x, int y) { + if (bits == 0) return 0; + return image[xsize * (y >> bits) + (x >> bits)]; +} + +static WEBP_INLINE HTreeGroup* GetHtreeGroupForPos(VP8LMetadata* const hdr, + int x, int y) { + const int meta_index = GetMetaIndex(hdr->huffman_image_, hdr->huffman_xsize_, + hdr->huffman_subsample_bits_, x, y); + assert(meta_index < hdr->num_htree_groups_); + return hdr->htree_groups_ + meta_index; +} + +//------------------------------------------------------------------------------ +// Main loop, with custom row-processing function + +typedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row); + +static void ApplyInverseTransforms(VP8LDecoder* const dec, + int start_row, int num_rows, + const uint32_t* const rows) { + int n = dec->next_transform_; + const int cache_pixs = dec->width_ * num_rows; + const int end_row = start_row + num_rows; + const uint32_t* rows_in = rows; + uint32_t* const rows_out = dec->argb_cache_; + + // Inverse transforms. + while (n-- > 0) { + VP8LTransform* const transform = &dec->transforms_[n]; + VP8LInverseTransform(transform, start_row, end_row, rows_in, rows_out); + rows_in = rows_out; + } + if (rows_in != rows_out) { + // No transform called, hence just copy. + memcpy(rows_out, rows_in, cache_pixs * sizeof(*rows_out)); + } +} + +// Processes (transforms, scales & color-converts) the rows decoded after the +// last call. +static void ProcessRows(VP8LDecoder* const dec, int row) { + const uint32_t* const rows = dec->pixels_ + dec->width_ * dec->last_row_; + const int num_rows = row - dec->last_row_; + + assert(row <= dec->io_->crop_bottom); + // We can't process more than NUM_ARGB_CACHE_ROWS at a time (that's the size + // of argb_cache_), but we currently don't need more than that. + assert(num_rows <= NUM_ARGB_CACHE_ROWS); + if (num_rows > 0) { // Emit output. + VP8Io* const io = dec->io_; + uint8_t* rows_data = (uint8_t*)dec->argb_cache_; + const int in_stride = io->width * sizeof(uint32_t); // in unit of RGBA + ApplyInverseTransforms(dec, dec->last_row_, num_rows, rows); + if (!SetCropWindow(io, dec->last_row_, row, &rows_data, in_stride)) { + // Nothing to output (this time). + } else { + const WebPDecBuffer* const output = dec->output_; + if (WebPIsRGBMode(output->colorspace)) { // convert to RGBA + const WebPRGBABuffer* const buf = &output->u.RGBA; + uint8_t* const rgba = + buf->rgba + (int64_t)dec->last_out_row_ * buf->stride; + const int num_rows_out = +#if !defined(WEBP_REDUCE_SIZE) + io->use_scaling ? + EmitRescaledRowsRGBA(dec, rows_data, in_stride, io->mb_h, + rgba, buf->stride) : +#endif // WEBP_REDUCE_SIZE + EmitRows(output->colorspace, rows_data, in_stride, + io->mb_w, io->mb_h, rgba, buf->stride); + // Update 'last_out_row_'. + dec->last_out_row_ += num_rows_out; + } else { // convert to YUVA + dec->last_out_row_ = io->use_scaling ? + EmitRescaledRowsYUVA(dec, rows_data, in_stride, io->mb_h) : + EmitRowsYUVA(dec, rows_data, in_stride, io->mb_w, io->mb_h); + } + assert(dec->last_out_row_ <= output->height); + } + } + + // Update 'last_row_'. + dec->last_row_ = row; + assert(dec->last_row_ <= dec->height_); +} + +// Row-processing for the special case when alpha data contains only one +// transform (color indexing), and trivial non-green literals. +static int Is8bOptimizable(const VP8LMetadata* const hdr) { + int i; + if (hdr->color_cache_size_ > 0) return 0; + // When the Huffman tree contains only one symbol, we can skip the + // call to ReadSymbol() for red/blue/alpha channels. + for (i = 0; i < hdr->num_htree_groups_; ++i) { + HuffmanCode** const htrees = hdr->htree_groups_[i].htrees; + if (htrees[RED][0].bits > 0) return 0; + if (htrees[BLUE][0].bits > 0) return 0; + if (htrees[ALPHA][0].bits > 0) return 0; + } + return 1; +} + +static void AlphaApplyFilter(ALPHDecoder* const alph_dec, + int first_row, int last_row, + uint8_t* out, int stride) { + if (alph_dec->filter_ != WEBP_FILTER_NONE) { + int y; + const uint8_t* prev_line = alph_dec->prev_line_; + assert(WebPUnfilters[alph_dec->filter_] != NULL); + for (y = first_row; y < last_row; ++y) { + WebPUnfilters[alph_dec->filter_](prev_line, out, out, stride); + prev_line = out; + out += stride; + } + alph_dec->prev_line_ = prev_line; + } +} + +static void ExtractPalettedAlphaRows(VP8LDecoder* const dec, int last_row) { + // For vertical and gradient filtering, we need to decode the part above the + // crop_top row, in order to have the correct spatial predictors. + ALPHDecoder* const alph_dec = (ALPHDecoder*)dec->io_->opaque; + const int top_row = + (alph_dec->filter_ == WEBP_FILTER_NONE || + alph_dec->filter_ == WEBP_FILTER_HORIZONTAL) ? dec->io_->crop_top + : dec->last_row_; + const int first_row = (dec->last_row_ < top_row) ? top_row : dec->last_row_; + assert(last_row <= dec->io_->crop_bottom); + if (last_row > first_row) { + // Special method for paletted alpha data. We only process the cropped area. + const int width = dec->io_->width; + uint8_t* out = alph_dec->output_ + width * first_row; + const uint8_t* const in = + (uint8_t*)dec->pixels_ + dec->width_ * first_row; + VP8LTransform* const transform = &dec->transforms_[0]; + assert(dec->next_transform_ == 1); + assert(transform->type_ == COLOR_INDEXING_TRANSFORM); + VP8LColorIndexInverseTransformAlpha(transform, first_row, last_row, + in, out); + AlphaApplyFilter(alph_dec, first_row, last_row, out, width); + } + dec->last_row_ = dec->last_out_row_ = last_row; +} + +//------------------------------------------------------------------------------ +// Helper functions for fast pattern copy (8b and 32b) + +// cyclic rotation of pattern word +static WEBP_INLINE uint32_t Rotate8b(uint32_t V) { +#if defined(WORDS_BIGENDIAN) + return ((V & 0xff000000u) >> 24) | (V << 8); +#else + return ((V & 0xffu) << 24) | (V >> 8); +#endif +} + +// copy 1, 2 or 4-bytes pattern +static WEBP_INLINE void CopySmallPattern8b(const uint8_t* src, uint8_t* dst, + int length, uint32_t pattern) { + int i; + // align 'dst' to 4-bytes boundary. Adjust the pattern along the way. + while ((uintptr_t)dst & 3) { + *dst++ = *src++; + pattern = Rotate8b(pattern); + --length; + } + // Copy the pattern 4 bytes at a time. + for (i = 0; i < (length >> 2); ++i) { + ((uint32_t*)dst)[i] = pattern; + } + // Finish with left-overs. 'pattern' is still correctly positioned, + // so no Rotate8b() call is needed. + for (i <<= 2; i < length; ++i) { + dst[i] = src[i]; + } +} + +static WEBP_INLINE void CopyBlock8b(uint8_t* const dst, int dist, int length) { + const uint8_t* src = dst - dist; + if (length >= 8) { + uint32_t pattern = 0; + switch (dist) { + case 1: + pattern = src[0]; +#if defined(__arm__) || defined(_M_ARM) // arm doesn't like multiply that much + pattern |= pattern << 8; + pattern |= pattern << 16; +#elif defined(WEBP_USE_MIPS_DSP_R2) + __asm__ volatile ("replv.qb %0, %0" : "+r"(pattern)); +#else + pattern = 0x01010101u * pattern; +#endif + break; + case 2: +#if !defined(WORDS_BIGENDIAN) + memcpy(&pattern, src, sizeof(uint16_t)); +#else + pattern = ((uint32_t)src[0] << 8) | src[1]; +#endif +#if defined(__arm__) || defined(_M_ARM) + pattern |= pattern << 16; +#elif defined(WEBP_USE_MIPS_DSP_R2) + __asm__ volatile ("replv.ph %0, %0" : "+r"(pattern)); +#else + pattern = 0x00010001u * pattern; +#endif + break; + case 4: + memcpy(&pattern, src, sizeof(uint32_t)); + break; + default: + goto Copy; + } + CopySmallPattern8b(src, dst, length, pattern); + return; + } + Copy: + if (dist >= length) { // no overlap -> use memcpy() + memcpy(dst, src, length * sizeof(*dst)); + } else { + int i; + for (i = 0; i < length; ++i) dst[i] = src[i]; + } +} + +// copy pattern of 1 or 2 uint32_t's +static WEBP_INLINE void CopySmallPattern32b(const uint32_t* src, + uint32_t* dst, + int length, uint64_t pattern) { + int i; + if ((uintptr_t)dst & 4) { // Align 'dst' to 8-bytes boundary. + *dst++ = *src++; + pattern = (pattern >> 32) | (pattern << 32); + --length; + } + assert(0 == ((uintptr_t)dst & 7)); + for (i = 0; i < (length >> 1); ++i) { + ((uint64_t*)dst)[i] = pattern; // Copy the pattern 8 bytes at a time. + } + if (length & 1) { // Finish with left-over. + dst[i << 1] = src[i << 1]; + } +} + +static WEBP_INLINE void CopyBlock32b(uint32_t* const dst, + int dist, int length) { + const uint32_t* const src = dst - dist; + if (dist <= 2 && length >= 4 && ((uintptr_t)dst & 3) == 0) { + uint64_t pattern; + if (dist == 1) { + pattern = (uint64_t)src[0]; + pattern |= pattern << 32; + } else { + memcpy(&pattern, src, sizeof(pattern)); + } + CopySmallPattern32b(src, dst, length, pattern); + } else if (dist >= length) { // no overlap + memcpy(dst, src, length * sizeof(*dst)); + } else { + int i; + for (i = 0; i < length; ++i) dst[i] = src[i]; + } +} + +//------------------------------------------------------------------------------ + +static int DecodeAlphaData(VP8LDecoder* const dec, uint8_t* const data, + int width, int height, int last_row) { + int ok = 1; + int row = dec->last_pixel_ / width; + int col = dec->last_pixel_ % width; + VP8LBitReader* const br = &dec->br_; + VP8LMetadata* const hdr = &dec->hdr_; + int pos = dec->last_pixel_; // current position + const int end = width * height; // End of data + const int last = width * last_row; // Last pixel to decode + const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES; + const int mask = hdr->huffman_mask_; + const HTreeGroup* htree_group = + (pos < last) ? GetHtreeGroupForPos(hdr, col, row) : NULL; + assert(pos <= end); + assert(last_row <= height); + assert(Is8bOptimizable(hdr)); + + while (!br->eos_ && pos < last) { + int code; + // Only update when changing tile. + if ((col & mask) == 0) { + htree_group = GetHtreeGroupForPos(hdr, col, row); + } + assert(htree_group != NULL); + VP8LFillBitWindow(br); + code = ReadSymbol(htree_group->htrees[GREEN], br); + if (code < NUM_LITERAL_CODES) { // Literal + data[pos] = code; + ++pos; + ++col; + if (col >= width) { + col = 0; + ++row; + if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) { + ExtractPalettedAlphaRows(dec, row); + } + } + } else if (code < len_code_limit) { // Backward reference + int dist_code, dist; + const int length_sym = code - NUM_LITERAL_CODES; + const int length = GetCopyLength(length_sym, br); + const int dist_symbol = ReadSymbol(htree_group->htrees[DIST], br); + VP8LFillBitWindow(br); + dist_code = GetCopyDistance(dist_symbol, br); + dist = PlaneCodeToDistance(width, dist_code); + if (pos >= dist && end - pos >= length) { + CopyBlock8b(data + pos, dist, length); + } else { + ok = 0; + goto End; + } + pos += length; + col += length; + while (col >= width) { + col -= width; + ++row; + if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) { + ExtractPalettedAlphaRows(dec, row); + } + } + if (pos < last && (col & mask)) { + htree_group = GetHtreeGroupForPos(hdr, col, row); + } + } else { // Not reached + ok = 0; + goto End; + } + br->eos_ = VP8LIsEndOfStream(br); + } + // Process the remaining rows corresponding to last row-block. + ExtractPalettedAlphaRows(dec, row > last_row ? last_row : row); + + End: + br->eos_ = VP8LIsEndOfStream(br); + if (!ok || (br->eos_ && pos < end)) { + return VP8LSetError( + dec, br->eos_ ? VP8_STATUS_SUSPENDED : VP8_STATUS_BITSTREAM_ERROR); + } + dec->last_pixel_ = pos; + return ok; +} + +static void SaveState(VP8LDecoder* const dec, int last_pixel) { + assert(dec->incremental_); + dec->saved_br_ = dec->br_; + dec->saved_last_pixel_ = last_pixel; + if (dec->hdr_.color_cache_size_ > 0) { + VP8LColorCacheCopy(&dec->hdr_.color_cache_, &dec->hdr_.saved_color_cache_); + } +} + +static void RestoreState(VP8LDecoder* const dec) { + assert(dec->br_.eos_); + dec->status_ = VP8_STATUS_SUSPENDED; + dec->br_ = dec->saved_br_; + dec->last_pixel_ = dec->saved_last_pixel_; + if (dec->hdr_.color_cache_size_ > 0) { + VP8LColorCacheCopy(&dec->hdr_.saved_color_cache_, &dec->hdr_.color_cache_); + } +} + +#define SYNC_EVERY_N_ROWS 8 // minimum number of rows between check-points +static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data, + int width, int height, int last_row, + ProcessRowsFunc process_func) { + int row = dec->last_pixel_ / width; + int col = dec->last_pixel_ % width; + VP8LBitReader* const br = &dec->br_; + VP8LMetadata* const hdr = &dec->hdr_; + uint32_t* src = data + dec->last_pixel_; + uint32_t* last_cached = src; + uint32_t* const src_end = data + width * height; // End of data + uint32_t* const src_last = data + width * last_row; // Last pixel to decode + const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES; + const int color_cache_limit = len_code_limit + hdr->color_cache_size_; + int next_sync_row = dec->incremental_ ? row : 1 << 24; + VP8LColorCache* const color_cache = + (hdr->color_cache_size_ > 0) ? &hdr->color_cache_ : NULL; + const int mask = hdr->huffman_mask_; + const HTreeGroup* htree_group = + (src < src_last) ? GetHtreeGroupForPos(hdr, col, row) : NULL; + assert(dec->last_row_ < last_row); + assert(src_last <= src_end); + + while (src < src_last) { + int code; + if (row >= next_sync_row) { + SaveState(dec, (int)(src - data)); + next_sync_row = row + SYNC_EVERY_N_ROWS; + } + // Only update when changing tile. Note we could use this test: + // if "((((prev_col ^ col) | prev_row ^ row)) > mask)" -> tile changed + // but that's actually slower and needs storing the previous col/row. + if ((col & mask) == 0) { + htree_group = GetHtreeGroupForPos(hdr, col, row); + } + assert(htree_group != NULL); + if (htree_group->is_trivial_code) { + *src = htree_group->literal_arb; + goto AdvanceByOne; + } + VP8LFillBitWindow(br); + if (htree_group->use_packed_table) { + code = ReadPackedSymbols(htree_group, br, src); + if (VP8LIsEndOfStream(br)) break; + if (code == PACKED_NON_LITERAL_CODE) goto AdvanceByOne; + } else { + code = ReadSymbol(htree_group->htrees[GREEN], br); + } + if (VP8LIsEndOfStream(br)) break; + if (code < NUM_LITERAL_CODES) { // Literal + if (htree_group->is_trivial_literal) { + *src = htree_group->literal_arb | (code << 8); + } else { + int red, blue, alpha; + red = ReadSymbol(htree_group->htrees[RED], br); + VP8LFillBitWindow(br); + blue = ReadSymbol(htree_group->htrees[BLUE], br); + alpha = ReadSymbol(htree_group->htrees[ALPHA], br); + if (VP8LIsEndOfStream(br)) break; + *src = ((uint32_t)alpha << 24) | (red << 16) | (code << 8) | blue; + } + AdvanceByOne: + ++src; + ++col; + if (col >= width) { + col = 0; + ++row; + if (process_func != NULL) { + if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) { + process_func(dec, row); + } + } + if (color_cache != NULL) { + while (last_cached < src) { + VP8LColorCacheInsert(color_cache, *last_cached++); + } + } + } + } else if (code < len_code_limit) { // Backward reference + int dist_code, dist; + const int length_sym = code - NUM_LITERAL_CODES; + const int length = GetCopyLength(length_sym, br); + const int dist_symbol = ReadSymbol(htree_group->htrees[DIST], br); + VP8LFillBitWindow(br); + dist_code = GetCopyDistance(dist_symbol, br); + dist = PlaneCodeToDistance(width, dist_code); + + if (VP8LIsEndOfStream(br)) break; + if (src - data < (ptrdiff_t)dist || src_end - src < (ptrdiff_t)length) { + goto Error; + } else { + CopyBlock32b(src, dist, length); + } + src += length; + col += length; + while (col >= width) { + col -= width; + ++row; + if (process_func != NULL) { + if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) { + process_func(dec, row); + } + } + } + // Because of the check done above (before 'src' was incremented by + // 'length'), the following holds true. + assert(src <= src_end); + if (col & mask) htree_group = GetHtreeGroupForPos(hdr, col, row); + if (color_cache != NULL) { + while (last_cached < src) { + VP8LColorCacheInsert(color_cache, *last_cached++); + } + } + } else if (code < color_cache_limit) { // Color cache + const int key = code - len_code_limit; + assert(color_cache != NULL); + while (last_cached < src) { + VP8LColorCacheInsert(color_cache, *last_cached++); + } + *src = VP8LColorCacheLookup(color_cache, key); + goto AdvanceByOne; + } else { // Not reached + goto Error; + } + } + + br->eos_ = VP8LIsEndOfStream(br); + // In incremental decoding: + // br->eos_ && src < src_last: if 'br' reached the end of the buffer and + // 'src_last' has not been reached yet, there is not enough data. 'dec' has to + // be reset until there is more data. + // !br->eos_ && src < src_last: this cannot happen as either the buffer is + // fully read, either enough has been read to reach 'src_last'. + // src >= src_last: 'src_last' is reached, all is fine. 'src' can actually go + // beyond 'src_last' in case the image is cropped and an LZ77 goes further. + // The buffer might have been enough or there is some left. 'br->eos_' does + // not matter. + assert(!dec->incremental_ || (br->eos_ && src < src_last) || src >= src_last); + if (dec->incremental_ && br->eos_ && src < src_last) { + RestoreState(dec); + } else if ((dec->incremental_ && src >= src_last) || !br->eos_) { + // Process the remaining rows corresponding to last row-block. + if (process_func != NULL) { + process_func(dec, row > last_row ? last_row : row); + } + dec->status_ = VP8_STATUS_OK; + dec->last_pixel_ = (int)(src - data); // end-of-scan marker + } else { + // if not incremental, and we are past the end of buffer (eos_=1), then this + // is a real bitstream error. + goto Error; + } + return 1; + + Error: + return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR); +} + +// ----------------------------------------------------------------------------- +// VP8LTransform + +static void ClearTransform(VP8LTransform* const transform) { + WebPSafeFree(transform->data_); + transform->data_ = NULL; +} + +// For security reason, we need to remap the color map to span +// the total possible bundled values, and not just the num_colors. +static int ExpandColorMap(int num_colors, VP8LTransform* const transform) { + int i; + const int final_num_colors = 1 << (8 >> transform->bits_); + uint32_t* const new_color_map = + (uint32_t*)WebPSafeMalloc((uint64_t)final_num_colors, + sizeof(*new_color_map)); + if (new_color_map == NULL) { + return 0; + } else { + uint8_t* const data = (uint8_t*)transform->data_; + uint8_t* const new_data = (uint8_t*)new_color_map; + new_color_map[0] = transform->data_[0]; + for (i = 4; i < 4 * num_colors; ++i) { + // Equivalent to VP8LAddPixels(), on a byte-basis. + new_data[i] = (data[i] + new_data[i - 4]) & 0xff; + } + for (; i < 4 * final_num_colors; ++i) { + new_data[i] = 0; // black tail. + } + WebPSafeFree(transform->data_); + transform->data_ = new_color_map; + } + return 1; +} + +static int ReadTransform(int* const xsize, int const* ysize, + VP8LDecoder* const dec) { + int ok = 1; + VP8LBitReader* const br = &dec->br_; + VP8LTransform* transform = &dec->transforms_[dec->next_transform_]; + const VP8LImageTransformType type = + (VP8LImageTransformType)VP8LReadBits(br, 2); + + // Each transform type can only be present once in the stream. + if (dec->transforms_seen_ & (1U << type)) { + return 0; // Already there, let's not accept the second same transform. + } + dec->transforms_seen_ |= (1U << type); + + transform->type_ = type; + transform->xsize_ = *xsize; + transform->ysize_ = *ysize; + transform->data_ = NULL; + ++dec->next_transform_; + assert(dec->next_transform_ <= NUM_TRANSFORMS); + + switch (type) { + case PREDICTOR_TRANSFORM: + case CROSS_COLOR_TRANSFORM: + transform->bits_ = VP8LReadBits(br, 3) + 2; + ok = DecodeImageStream(VP8LSubSampleSize(transform->xsize_, + transform->bits_), + VP8LSubSampleSize(transform->ysize_, + transform->bits_), + /*is_level0=*/0, dec, &transform->data_); + break; + case COLOR_INDEXING_TRANSFORM: { + const int num_colors = VP8LReadBits(br, 8) + 1; + const int bits = (num_colors > 16) ? 0 + : (num_colors > 4) ? 1 + : (num_colors > 2) ? 2 + : 3; + *xsize = VP8LSubSampleSize(transform->xsize_, bits); + transform->bits_ = bits; + ok = DecodeImageStream(num_colors, /*ysize=*/1, /*is_level0=*/0, dec, + &transform->data_); + if (ok && !ExpandColorMap(num_colors, transform)) { + return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY); + } + break; + } + case SUBTRACT_GREEN_TRANSFORM: + break; + default: + assert(0); // can't happen + break; + } + + return ok; +} + +// ----------------------------------------------------------------------------- +// VP8LMetadata + +static void InitMetadata(VP8LMetadata* const hdr) { + assert(hdr != NULL); + memset(hdr, 0, sizeof(*hdr)); +} + +static void ClearMetadata(VP8LMetadata* const hdr) { + assert(hdr != NULL); + + WebPSafeFree(hdr->huffman_image_); + VP8LHuffmanTablesDeallocate(&hdr->huffman_tables_); + VP8LHtreeGroupsFree(hdr->htree_groups_); + VP8LColorCacheClear(&hdr->color_cache_); + VP8LColorCacheClear(&hdr->saved_color_cache_); + InitMetadata(hdr); +} + +// ----------------------------------------------------------------------------- +// VP8LDecoder + +VP8LDecoder* VP8LNew(void) { + VP8LDecoder* const dec = (VP8LDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec)); + if (dec == NULL) return NULL; + dec->status_ = VP8_STATUS_OK; + dec->state_ = READ_DIM; + + VP8LDspInit(); // Init critical function pointers. + + return dec; +} + +void VP8LClear(VP8LDecoder* const dec) { + int i; + if (dec == NULL) return; + ClearMetadata(&dec->hdr_); + + WebPSafeFree(dec->pixels_); + dec->pixels_ = NULL; + for (i = 0; i < dec->next_transform_; ++i) { + ClearTransform(&dec->transforms_[i]); + } + dec->next_transform_ = 0; + dec->transforms_seen_ = 0; + + WebPSafeFree(dec->rescaler_memory); + dec->rescaler_memory = NULL; + + dec->output_ = NULL; // leave no trace behind +} + +void VP8LDelete(VP8LDecoder* const dec) { + if (dec != NULL) { + VP8LClear(dec); + WebPSafeFree(dec); + } +} + +static void UpdateDecoder(VP8LDecoder* const dec, int width, int height) { + VP8LMetadata* const hdr = &dec->hdr_; + const int num_bits = hdr->huffman_subsample_bits_; + dec->width_ = width; + dec->height_ = height; + + hdr->huffman_xsize_ = VP8LSubSampleSize(width, num_bits); + hdr->huffman_mask_ = (num_bits == 0) ? ~0 : (1 << num_bits) - 1; +} + +static int DecodeImageStream(int xsize, int ysize, + int is_level0, + VP8LDecoder* const dec, + uint32_t** const decoded_data) { + int ok = 1; + int transform_xsize = xsize; + int transform_ysize = ysize; + VP8LBitReader* const br = &dec->br_; + VP8LMetadata* const hdr = &dec->hdr_; + uint32_t* data = NULL; + int color_cache_bits = 0; + + // Read the transforms (may recurse). + if (is_level0) { + while (ok && VP8LReadBits(br, 1)) { + ok = ReadTransform(&transform_xsize, &transform_ysize, dec); + } + } + + // Color cache + if (ok && VP8LReadBits(br, 1)) { + color_cache_bits = VP8LReadBits(br, 4); + ok = (color_cache_bits >= 1 && color_cache_bits <= MAX_CACHE_BITS); + if (!ok) { + VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR); + goto End; + } + } + + // Read the Huffman codes (may recurse). + ok = ok && ReadHuffmanCodes(dec, transform_xsize, transform_ysize, + color_cache_bits, is_level0); + if (!ok) { + VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR); + goto End; + } + + // Finish setting up the color-cache + if (color_cache_bits > 0) { + hdr->color_cache_size_ = 1 << color_cache_bits; + if (!VP8LColorCacheInit(&hdr->color_cache_, color_cache_bits)) { + ok = VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY); + goto End; + } + } else { + hdr->color_cache_size_ = 0; + } + UpdateDecoder(dec, transform_xsize, transform_ysize); + + if (is_level0) { // level 0 complete + dec->state_ = READ_HDR; + goto End; + } + + { + const uint64_t total_size = (uint64_t)transform_xsize * transform_ysize; + data = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*data)); + if (data == NULL) { + ok = VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY); + goto End; + } + } + + // Use the Huffman trees to decode the LZ77 encoded data. + ok = DecodeImageData(dec, data, transform_xsize, transform_ysize, + transform_ysize, NULL); + ok = ok && !br->eos_; + + End: + if (!ok) { + WebPSafeFree(data); + ClearMetadata(hdr); + } else { + if (decoded_data != NULL) { + *decoded_data = data; + } else { + // We allocate image data in this function only for transforms. At level 0 + // (that is: not the transforms), we shouldn't have allocated anything. + assert(data == NULL); + assert(is_level0); + } + dec->last_pixel_ = 0; // Reset for future DECODE_DATA_FUNC() calls. + if (!is_level0) ClearMetadata(hdr); // Clean up temporary data behind. + } + return ok; +} + +//------------------------------------------------------------------------------ +// Allocate internal buffers dec->pixels_ and dec->argb_cache_. +static int AllocateInternalBuffers32b(VP8LDecoder* const dec, int final_width) { + const uint64_t num_pixels = (uint64_t)dec->width_ * dec->height_; + // Scratch buffer corresponding to top-prediction row for transforming the + // first row in the row-blocks. Not needed for paletted alpha. + const uint64_t cache_top_pixels = (uint16_t)final_width; + // Scratch buffer for temporary BGRA storage. Not needed for paletted alpha. + const uint64_t cache_pixels = (uint64_t)final_width * NUM_ARGB_CACHE_ROWS; + const uint64_t total_num_pixels = + num_pixels + cache_top_pixels + cache_pixels; + + assert(dec->width_ <= final_width); + dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint32_t)); + if (dec->pixels_ == NULL) { + dec->argb_cache_ = NULL; // for soundness + return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY); + } + dec->argb_cache_ = dec->pixels_ + num_pixels + cache_top_pixels; + return 1; +} + +static int AllocateInternalBuffers8b(VP8LDecoder* const dec) { + const uint64_t total_num_pixels = (uint64_t)dec->width_ * dec->height_; + dec->argb_cache_ = NULL; // for soundness + dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint8_t)); + if (dec->pixels_ == NULL) { + return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY); + } + return 1; +} + +//------------------------------------------------------------------------------ + +// Special row-processing that only stores the alpha data. +static void ExtractAlphaRows(VP8LDecoder* const dec, int last_row) { + int cur_row = dec->last_row_; + int num_rows = last_row - cur_row; + const uint32_t* in = dec->pixels_ + dec->width_ * cur_row; + + assert(last_row <= dec->io_->crop_bottom); + while (num_rows > 0) { + const int num_rows_to_process = + (num_rows > NUM_ARGB_CACHE_ROWS) ? NUM_ARGB_CACHE_ROWS : num_rows; + // Extract alpha (which is stored in the green plane). + ALPHDecoder* const alph_dec = (ALPHDecoder*)dec->io_->opaque; + uint8_t* const output = alph_dec->output_; + const int width = dec->io_->width; // the final width (!= dec->width_) + const int cache_pixs = width * num_rows_to_process; + uint8_t* const dst = output + width * cur_row; + const uint32_t* const src = dec->argb_cache_; + ApplyInverseTransforms(dec, cur_row, num_rows_to_process, in); + WebPExtractGreen(src, dst, cache_pixs); + AlphaApplyFilter(alph_dec, + cur_row, cur_row + num_rows_to_process, dst, width); + num_rows -= num_rows_to_process; + in += num_rows_to_process * dec->width_; + cur_row += num_rows_to_process; + } + assert(cur_row == last_row); + dec->last_row_ = dec->last_out_row_ = last_row; +} + +int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec, + const uint8_t* const data, size_t data_size) { + int ok = 0; + VP8LDecoder* dec = VP8LNew(); + + if (dec == NULL) return 0; + + assert(alph_dec != NULL); + + dec->width_ = alph_dec->width_; + dec->height_ = alph_dec->height_; + dec->io_ = &alph_dec->io_; + dec->io_->opaque = alph_dec; + dec->io_->width = alph_dec->width_; + dec->io_->height = alph_dec->height_; + + dec->status_ = VP8_STATUS_OK; + VP8LInitBitReader(&dec->br_, data, data_size); + + if (!DecodeImageStream(alph_dec->width_, alph_dec->height_, /*is_level0=*/1, + dec, /*decoded_data=*/NULL)) { + goto Err; + } + + // Special case: if alpha data uses only the color indexing transform and + // doesn't use color cache (a frequent case), we will use DecodeAlphaData() + // method that only needs allocation of 1 byte per pixel (alpha channel). + if (dec->next_transform_ == 1 && + dec->transforms_[0].type_ == COLOR_INDEXING_TRANSFORM && + Is8bOptimizable(&dec->hdr_)) { + alph_dec->use_8b_decode_ = 1; + ok = AllocateInternalBuffers8b(dec); + } else { + // Allocate internal buffers (note that dec->width_ may have changed here). + alph_dec->use_8b_decode_ = 0; + ok = AllocateInternalBuffers32b(dec, alph_dec->width_); + } + + if (!ok) goto Err; + + // Only set here, once we are sure it is valid (to avoid thread races). + alph_dec->vp8l_dec_ = dec; + return 1; + + Err: + VP8LDelete(dec); + return 0; +} + +int VP8LDecodeAlphaImageStream(ALPHDecoder* const alph_dec, int last_row) { + VP8LDecoder* const dec = alph_dec->vp8l_dec_; + assert(dec != NULL); + assert(last_row <= dec->height_); + + if (dec->last_row_ >= last_row) { + return 1; // done + } + + if (!alph_dec->use_8b_decode_) WebPInitAlphaProcessing(); + + // Decode (with special row processing). + return alph_dec->use_8b_decode_ ? + DecodeAlphaData(dec, (uint8_t*)dec->pixels_, dec->width_, dec->height_, + last_row) : + DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_, + last_row, ExtractAlphaRows); +} + +//------------------------------------------------------------------------------ + +int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io) { + int width, height, has_alpha; + + if (dec == NULL) return 0; + if (io == NULL) { + return VP8LSetError(dec, VP8_STATUS_INVALID_PARAM); + } + + dec->io_ = io; + dec->status_ = VP8_STATUS_OK; + VP8LInitBitReader(&dec->br_, io->data, io->data_size); + if (!ReadImageInfo(&dec->br_, &width, &height, &has_alpha)) { + VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR); + goto Error; + } + dec->state_ = READ_DIM; + io->width = width; + io->height = height; + + if (!DecodeImageStream(width, height, /*is_level0=*/1, dec, + /*decoded_data=*/NULL)) { + goto Error; + } + return 1; + + Error: + VP8LClear(dec); + assert(dec->status_ != VP8_STATUS_OK); + return 0; +} + +int VP8LDecodeImage(VP8LDecoder* const dec) { + VP8Io* io = NULL; + WebPDecParams* params = NULL; + + if (dec == NULL) return 0; + + assert(dec->hdr_.huffman_tables_.root.start != NULL); + assert(dec->hdr_.htree_groups_ != NULL); + assert(dec->hdr_.num_htree_groups_ > 0); + + io = dec->io_; + assert(io != NULL); + params = (WebPDecParams*)io->opaque; + assert(params != NULL); + + // Initialization. + if (dec->state_ != READ_DATA) { + dec->output_ = params->output; + assert(dec->output_ != NULL); + + if (!WebPIoInitFromOptions(params->options, io, MODE_BGRA)) { + VP8LSetError(dec, VP8_STATUS_INVALID_PARAM); + goto Err; + } + + if (!AllocateInternalBuffers32b(dec, io->width)) goto Err; + +#if !defined(WEBP_REDUCE_SIZE) + if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err; +#else + if (io->use_scaling) { + VP8LSetError(dec, VP8_STATUS_INVALID_PARAM); + goto Err; + } +#endif + if (io->use_scaling || WebPIsPremultipliedMode(dec->output_->colorspace)) { + // need the alpha-multiply functions for premultiplied output or rescaling + WebPInitAlphaProcessing(); + } + + if (!WebPIsRGBMode(dec->output_->colorspace)) { + WebPInitConvertARGBToYUV(); + if (dec->output_->u.YUVA.a != NULL) WebPInitAlphaProcessing(); + } + if (dec->incremental_) { + if (dec->hdr_.color_cache_size_ > 0 && + dec->hdr_.saved_color_cache_.colors_ == NULL) { + if (!VP8LColorCacheInit(&dec->hdr_.saved_color_cache_, + dec->hdr_.color_cache_.hash_bits_)) { + VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY); + goto Err; + } + } + } + dec->state_ = READ_DATA; + } + + // Decode. + if (!DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_, + io->crop_bottom, ProcessRows)) { + goto Err; + } + + params->last_y = dec->last_out_row_; + return 1; + + Err: + VP8LClear(dec); + assert(dec->status_ != VP8_STATUS_OK); + return 0; +} + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/src/dec/vp8li_dec.h b/third-party/webp/libwebp/src/dec/vp8li_dec.h new file mode 100644 index 0000000000..b057573f6c --- /dev/null +++ b/third-party/webp/libwebp/src/dec/vp8li_dec.h @@ -0,0 +1,148 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Lossless decoder: internal header. +// +// Author: Skal (pascal.massimino@gmail.com) +// Vikas Arora(vikaas.arora@gmail.com) + +#ifndef WEBP_DEC_VP8LI_DEC_H_ +#define WEBP_DEC_VP8LI_DEC_H_ + +#include // for memcpy() +#include "src/dec/webpi_dec.h" +#include "src/utils/bit_reader_utils.h" +#include "src/utils/color_cache_utils.h" +#include "src/utils/huffman_utils.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + READ_DATA = 0, + READ_HDR = 1, + READ_DIM = 2 +} VP8LDecodeState; + +typedef struct VP8LTransform VP8LTransform; +struct VP8LTransform { + VP8LImageTransformType type_; // transform type. + int bits_; // subsampling bits defining transform window. + int xsize_; // transform window X index. + int ysize_; // transform window Y index. + uint32_t* data_; // transform data. +}; + +typedef struct { + int color_cache_size_; + VP8LColorCache color_cache_; + VP8LColorCache saved_color_cache_; // for incremental + + int huffman_mask_; + int huffman_subsample_bits_; + int huffman_xsize_; + uint32_t* huffman_image_; + int num_htree_groups_; + HTreeGroup* htree_groups_; + HuffmanTables huffman_tables_; +} VP8LMetadata; + +typedef struct VP8LDecoder VP8LDecoder; +struct VP8LDecoder { + VP8StatusCode status_; + VP8LDecodeState state_; + VP8Io* io_; + + const WebPDecBuffer* output_; // shortcut to io->opaque->output + + uint32_t* pixels_; // Internal data: either uint8_t* for alpha + // or uint32_t* for BGRA. + uint32_t* argb_cache_; // Scratch buffer for temporary BGRA storage. + + VP8LBitReader br_; + int incremental_; // if true, incremental decoding is expected + VP8LBitReader saved_br_; // note: could be local variables too + int saved_last_pixel_; + + int width_; + int height_; + int last_row_; // last input row decoded so far. + int last_pixel_; // last pixel decoded so far. However, it may + // not be transformed, scaled and + // color-converted yet. + int last_out_row_; // last row output so far. + + VP8LMetadata hdr_; + + int next_transform_; + VP8LTransform transforms_[NUM_TRANSFORMS]; + // or'd bitset storing the transforms types. + uint32_t transforms_seen_; + + uint8_t* rescaler_memory; // Working memory for rescaling work. + WebPRescaler* rescaler; // Common rescaler for all channels. +}; + +//------------------------------------------------------------------------------ +// internal functions. Not public. + +struct ALPHDecoder; // Defined in dec/alphai.h. + +// in vp8l.c + +// Decodes image header for alpha data stored using lossless compression. +// Returns false in case of error. +int VP8LDecodeAlphaHeader(struct ALPHDecoder* const alph_dec, + const uint8_t* const data, size_t data_size); + +// Decodes *at least* 'last_row' rows of alpha. If some of the initial rows are +// already decoded in previous call(s), it will resume decoding from where it +// was paused. +// Returns false in case of bitstream error. +int VP8LDecodeAlphaImageStream(struct ALPHDecoder* const alph_dec, + int last_row); + +// Allocates and initialize a new lossless decoder instance. +VP8LDecoder* VP8LNew(void); + +// Decodes the image header. Returns false in case of error. +int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io); + +// Decodes an image. It's required to decode the lossless header before calling +// this function. Returns false in case of error, with updated dec->status_. +int VP8LDecodeImage(VP8LDecoder* const dec); + +// Resets the decoder in its initial state, reclaiming memory. +// Preserves the dec->status_ value. +void VP8LClear(VP8LDecoder* const dec); + +// Clears and deallocate a lossless decoder instance. +void VP8LDelete(VP8LDecoder* const dec); + +// Helper function for reading the different Huffman codes and storing them in +// 'huffman_tables' and 'htree_groups'. +// If mapping is NULL 'num_htree_groups_max' must equal 'num_htree_groups'. +// If it is not NULL, it maps 'num_htree_groups_max' indices to the +// 'num_htree_groups' groups. If 'num_htree_groups_max' > 'num_htree_groups', +// some of those indices map to -1. This is used for non-balanced codes to +// limit memory usage. +int ReadHuffmanCodesHelper(int color_cache_bits, int num_htree_groups, + int num_htree_groups_max, const int* const mapping, + VP8LDecoder* const dec, + HuffmanTables* const huffman_tables, + HTreeGroup** const htree_groups); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_DEC_VP8LI_DEC_H_ diff --git a/third-party/webp/libwebp/src/dec/webp_dec.c b/third-party/webp/libwebp/src/dec/webp_dec.c new file mode 100644 index 0000000000..f557868b99 --- /dev/null +++ b/third-party/webp/libwebp/src/dec/webp_dec.c @@ -0,0 +1,859 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Main decoding functions for WEBP images. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include + +#include "src/dec/vp8i_dec.h" +#include "src/dec/vp8li_dec.h" +#include "src/dec/webpi_dec.h" +#include "src/utils/utils.h" +#include "src/webp/mux_types.h" // ALPHA_FLAG + +//------------------------------------------------------------------------------ +// RIFF layout is: +// Offset tag +// 0...3 "RIFF" 4-byte tag +// 4...7 size of image data (including metadata) starting at offset 8 +// 8...11 "WEBP" our form-type signature +// The RIFF container (12 bytes) is followed by appropriate chunks: +// 12..15 "VP8 ": 4-bytes tags, signaling the use of VP8 video format +// 16..19 size of the raw VP8 image data, starting at offset 20 +// 20.... the VP8 bytes +// Or, +// 12..15 "VP8L": 4-bytes tags, signaling the use of VP8L lossless format +// 16..19 size of the raw VP8L image data, starting at offset 20 +// 20.... the VP8L bytes +// Or, +// 12..15 "VP8X": 4-bytes tags, describing the extended-VP8 chunk. +// 16..19 size of the VP8X chunk starting at offset 20. +// 20..23 VP8X flags bit-map corresponding to the chunk-types present. +// 24..26 Width of the Canvas Image. +// 27..29 Height of the Canvas Image. +// There can be extra chunks after the "VP8X" chunk (ICCP, ANMF, VP8, VP8L, +// XMP, EXIF ...) +// All sizes are in little-endian order. +// Note: chunk data size must be padded to multiple of 2 when written. + +// Validates the RIFF container (if detected) and skips over it. +// If a RIFF container is detected, returns: +// VP8_STATUS_BITSTREAM_ERROR for invalid header, +// VP8_STATUS_NOT_ENOUGH_DATA for truncated data if have_all_data is true, +// and VP8_STATUS_OK otherwise. +// In case there are not enough bytes (partial RIFF container), return 0 for +// *riff_size. Else return the RIFF size extracted from the header. +static VP8StatusCode ParseRIFF(const uint8_t** const data, + size_t* const data_size, int have_all_data, + size_t* const riff_size) { + assert(data != NULL); + assert(data_size != NULL); + assert(riff_size != NULL); + + *riff_size = 0; // Default: no RIFF present. + if (*data_size >= RIFF_HEADER_SIZE && !memcmp(*data, "RIFF", TAG_SIZE)) { + if (memcmp(*data + 8, "WEBP", TAG_SIZE)) { + return VP8_STATUS_BITSTREAM_ERROR; // Wrong image file signature. + } else { + const uint32_t size = GetLE32(*data + TAG_SIZE); + // Check that we have at least one chunk (i.e "WEBP" + "VP8?nnnn"). + if (size < TAG_SIZE + CHUNK_HEADER_SIZE) { + return VP8_STATUS_BITSTREAM_ERROR; + } + if (size > MAX_CHUNK_PAYLOAD) { + return VP8_STATUS_BITSTREAM_ERROR; + } + if (have_all_data && (size > *data_size - CHUNK_HEADER_SIZE)) { + return VP8_STATUS_NOT_ENOUGH_DATA; // Truncated bitstream. + } + // We have a RIFF container. Skip it. + *riff_size = size; + *data += RIFF_HEADER_SIZE; + *data_size -= RIFF_HEADER_SIZE; + } + } + return VP8_STATUS_OK; +} + +// Validates the VP8X header and skips over it. +// Returns VP8_STATUS_BITSTREAM_ERROR for invalid VP8X header, +// VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and +// VP8_STATUS_OK otherwise. +// If a VP8X chunk is found, found_vp8x is set to true and *width_ptr, +// *height_ptr and *flags_ptr are set to the corresponding values extracted +// from the VP8X chunk. +static VP8StatusCode ParseVP8X(const uint8_t** const data, + size_t* const data_size, + int* const found_vp8x, + int* const width_ptr, int* const height_ptr, + uint32_t* const flags_ptr) { + const uint32_t vp8x_size = CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE; + assert(data != NULL); + assert(data_size != NULL); + assert(found_vp8x != NULL); + + *found_vp8x = 0; + + if (*data_size < CHUNK_HEADER_SIZE) { + return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data. + } + + if (!memcmp(*data, "VP8X", TAG_SIZE)) { + int width, height; + uint32_t flags; + const uint32_t chunk_size = GetLE32(*data + TAG_SIZE); + if (chunk_size != VP8X_CHUNK_SIZE) { + return VP8_STATUS_BITSTREAM_ERROR; // Wrong chunk size. + } + + // Verify if enough data is available to validate the VP8X chunk. + if (*data_size < vp8x_size) { + return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data. + } + flags = GetLE32(*data + 8); + width = 1 + GetLE24(*data + 12); + height = 1 + GetLE24(*data + 15); + if (width * (uint64_t)height >= MAX_IMAGE_AREA) { + return VP8_STATUS_BITSTREAM_ERROR; // image is too large + } + + if (flags_ptr != NULL) *flags_ptr = flags; + if (width_ptr != NULL) *width_ptr = width; + if (height_ptr != NULL) *height_ptr = height; + // Skip over VP8X header bytes. + *data += vp8x_size; + *data_size -= vp8x_size; + *found_vp8x = 1; + } + return VP8_STATUS_OK; +} + +// Skips to the next VP8/VP8L chunk header in the data given the size of the +// RIFF chunk 'riff_size'. +// Returns VP8_STATUS_BITSTREAM_ERROR if any invalid chunk size is encountered, +// VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and +// VP8_STATUS_OK otherwise. +// If an alpha chunk is found, *alpha_data and *alpha_size are set +// appropriately. +static VP8StatusCode ParseOptionalChunks(const uint8_t** const data, + size_t* const data_size, + size_t const riff_size, + const uint8_t** const alpha_data, + size_t* const alpha_size) { + const uint8_t* buf; + size_t buf_size; + uint32_t total_size = TAG_SIZE + // "WEBP". + CHUNK_HEADER_SIZE + // "VP8Xnnnn". + VP8X_CHUNK_SIZE; // data. + assert(data != NULL); + assert(data_size != NULL); + buf = *data; + buf_size = *data_size; + + assert(alpha_data != NULL); + assert(alpha_size != NULL); + *alpha_data = NULL; + *alpha_size = 0; + + while (1) { + uint32_t chunk_size; + uint32_t disk_chunk_size; // chunk_size with padding + + *data = buf; + *data_size = buf_size; + + if (buf_size < CHUNK_HEADER_SIZE) { // Insufficient data. + return VP8_STATUS_NOT_ENOUGH_DATA; + } + + chunk_size = GetLE32(buf + TAG_SIZE); + if (chunk_size > MAX_CHUNK_PAYLOAD) { + return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size. + } + // For odd-sized chunk-payload, there's one byte padding at the end. + disk_chunk_size = (CHUNK_HEADER_SIZE + chunk_size + 1) & ~1u; + total_size += disk_chunk_size; + + // Check that total bytes skipped so far does not exceed riff_size. + if (riff_size > 0 && (total_size > riff_size)) { + return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size. + } + + // Start of a (possibly incomplete) VP8/VP8L chunk implies that we have + // parsed all the optional chunks. + // Note: This check must occur before the check 'buf_size < disk_chunk_size' + // below to allow incomplete VP8/VP8L chunks. + if (!memcmp(buf, "VP8 ", TAG_SIZE) || + !memcmp(buf, "VP8L", TAG_SIZE)) { + return VP8_STATUS_OK; + } + + if (buf_size < disk_chunk_size) { // Insufficient data. + return VP8_STATUS_NOT_ENOUGH_DATA; + } + + if (!memcmp(buf, "ALPH", TAG_SIZE)) { // A valid ALPH header. + *alpha_data = buf + CHUNK_HEADER_SIZE; + *alpha_size = chunk_size; + } + + // We have a full and valid chunk; skip it. + buf += disk_chunk_size; + buf_size -= disk_chunk_size; + } +} + +// Validates the VP8/VP8L Header ("VP8 nnnn" or "VP8L nnnn") and skips over it. +// Returns VP8_STATUS_BITSTREAM_ERROR for invalid (chunk larger than +// riff_size) VP8/VP8L header, +// VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and +// VP8_STATUS_OK otherwise. +// If a VP8/VP8L chunk is found, *chunk_size is set to the total number of bytes +// extracted from the VP8/VP8L chunk header. +// The flag '*is_lossless' is set to 1 in case of VP8L chunk / raw VP8L data. +static VP8StatusCode ParseVP8Header(const uint8_t** const data_ptr, + size_t* const data_size, int have_all_data, + size_t riff_size, size_t* const chunk_size, + int* const is_lossless) { + const uint8_t* const data = *data_ptr; + const int is_vp8 = !memcmp(data, "VP8 ", TAG_SIZE); + const int is_vp8l = !memcmp(data, "VP8L", TAG_SIZE); + const uint32_t minimal_size = + TAG_SIZE + CHUNK_HEADER_SIZE; // "WEBP" + "VP8 nnnn" OR + // "WEBP" + "VP8Lnnnn" + assert(data != NULL); + assert(data_size != NULL); + assert(chunk_size != NULL); + assert(is_lossless != NULL); + + if (*data_size < CHUNK_HEADER_SIZE) { + return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data. + } + + if (is_vp8 || is_vp8l) { + // Bitstream contains VP8/VP8L header. + const uint32_t size = GetLE32(data + TAG_SIZE); + if ((riff_size >= minimal_size) && (size > riff_size - minimal_size)) { + return VP8_STATUS_BITSTREAM_ERROR; // Inconsistent size information. + } + if (have_all_data && (size > *data_size - CHUNK_HEADER_SIZE)) { + return VP8_STATUS_NOT_ENOUGH_DATA; // Truncated bitstream. + } + // Skip over CHUNK_HEADER_SIZE bytes from VP8/VP8L Header. + *chunk_size = size; + *data_ptr += CHUNK_HEADER_SIZE; + *data_size -= CHUNK_HEADER_SIZE; + *is_lossless = is_vp8l; + } else { + // Raw VP8/VP8L bitstream (no header). + *is_lossless = VP8LCheckSignature(data, *data_size); + *chunk_size = *data_size; + } + + return VP8_STATUS_OK; +} + +//------------------------------------------------------------------------------ + +// Fetch '*width', '*height', '*has_alpha' and fill out 'headers' based on +// 'data'. All the output parameters may be NULL. If 'headers' is NULL only the +// minimal amount will be read to fetch the remaining parameters. +// If 'headers' is non-NULL this function will attempt to locate both alpha +// data (with or without a VP8X chunk) and the bitstream chunk (VP8/VP8L). +// Note: The following chunk sequences (before the raw VP8/VP8L data) are +// considered valid by this function: +// RIFF + VP8(L) +// RIFF + VP8X + (optional chunks) + VP8(L) +// ALPH + VP8 <-- Not a valid WebP format: only allowed for internal purpose. +// VP8(L) <-- Not a valid WebP format: only allowed for internal purpose. +static VP8StatusCode ParseHeadersInternal(const uint8_t* data, + size_t data_size, + int* const width, + int* const height, + int* const has_alpha, + int* const has_animation, + int* const format, + WebPHeaderStructure* const headers) { + int canvas_width = 0; + int canvas_height = 0; + int image_width = 0; + int image_height = 0; + int found_riff = 0; + int found_vp8x = 0; + int animation_present = 0; + const int have_all_data = (headers != NULL) ? headers->have_all_data : 0; + + VP8StatusCode status; + WebPHeaderStructure hdrs; + + if (data == NULL || data_size < RIFF_HEADER_SIZE) { + return VP8_STATUS_NOT_ENOUGH_DATA; + } + memset(&hdrs, 0, sizeof(hdrs)); + hdrs.data = data; + hdrs.data_size = data_size; + + // Skip over RIFF header. + status = ParseRIFF(&data, &data_size, have_all_data, &hdrs.riff_size); + if (status != VP8_STATUS_OK) { + return status; // Wrong RIFF header / insufficient data. + } + found_riff = (hdrs.riff_size > 0); + + // Skip over VP8X. + { + uint32_t flags = 0; + status = ParseVP8X(&data, &data_size, &found_vp8x, + &canvas_width, &canvas_height, &flags); + if (status != VP8_STATUS_OK) { + return status; // Wrong VP8X / insufficient data. + } + animation_present = !!(flags & ANIMATION_FLAG); + if (!found_riff && found_vp8x) { + // Note: This restriction may be removed in the future, if it becomes + // necessary to send VP8X chunk to the decoder. + return VP8_STATUS_BITSTREAM_ERROR; + } + if (has_alpha != NULL) *has_alpha = !!(flags & ALPHA_FLAG); + if (has_animation != NULL) *has_animation = animation_present; + if (format != NULL) *format = 0; // default = undefined + + image_width = canvas_width; + image_height = canvas_height; + if (found_vp8x && animation_present && headers == NULL) { + status = VP8_STATUS_OK; + goto ReturnWidthHeight; // Just return features from VP8X header. + } + } + + if (data_size < TAG_SIZE) { + status = VP8_STATUS_NOT_ENOUGH_DATA; + goto ReturnWidthHeight; + } + + // Skip over optional chunks if data started with "RIFF + VP8X" or "ALPH". + if ((found_riff && found_vp8x) || + (!found_riff && !found_vp8x && !memcmp(data, "ALPH", TAG_SIZE))) { + status = ParseOptionalChunks(&data, &data_size, hdrs.riff_size, + &hdrs.alpha_data, &hdrs.alpha_data_size); + if (status != VP8_STATUS_OK) { + goto ReturnWidthHeight; // Invalid chunk size / insufficient data. + } + } + + // Skip over VP8/VP8L header. + status = ParseVP8Header(&data, &data_size, have_all_data, hdrs.riff_size, + &hdrs.compressed_size, &hdrs.is_lossless); + if (status != VP8_STATUS_OK) { + goto ReturnWidthHeight; // Wrong VP8/VP8L chunk-header / insufficient data. + } + if (hdrs.compressed_size > MAX_CHUNK_PAYLOAD) { + return VP8_STATUS_BITSTREAM_ERROR; + } + + if (format != NULL && !animation_present) { + *format = hdrs.is_lossless ? 2 : 1; + } + + if (!hdrs.is_lossless) { + if (data_size < VP8_FRAME_HEADER_SIZE) { + status = VP8_STATUS_NOT_ENOUGH_DATA; + goto ReturnWidthHeight; + } + // Validates raw VP8 data. + if (!VP8GetInfo(data, data_size, (uint32_t)hdrs.compressed_size, + &image_width, &image_height)) { + return VP8_STATUS_BITSTREAM_ERROR; + } + } else { + if (data_size < VP8L_FRAME_HEADER_SIZE) { + status = VP8_STATUS_NOT_ENOUGH_DATA; + goto ReturnWidthHeight; + } + // Validates raw VP8L data. + if (!VP8LGetInfo(data, data_size, &image_width, &image_height, has_alpha)) { + return VP8_STATUS_BITSTREAM_ERROR; + } + } + // Validates image size coherency. + if (found_vp8x) { + if (canvas_width != image_width || canvas_height != image_height) { + return VP8_STATUS_BITSTREAM_ERROR; + } + } + if (headers != NULL) { + *headers = hdrs; + headers->offset = data - headers->data; + assert((uint64_t)(data - headers->data) < MAX_CHUNK_PAYLOAD); + assert(headers->offset == headers->data_size - data_size); + } + ReturnWidthHeight: + if (status == VP8_STATUS_OK || + (status == VP8_STATUS_NOT_ENOUGH_DATA && found_vp8x && headers == NULL)) { + if (has_alpha != NULL) { + // If the data did not contain a VP8X/VP8L chunk the only definitive way + // to set this is by looking for alpha data (from an ALPH chunk). + *has_alpha |= (hdrs.alpha_data != NULL); + } + if (width != NULL) *width = image_width; + if (height != NULL) *height = image_height; + return VP8_STATUS_OK; + } else { + return status; + } +} + +VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers) { + // status is marked volatile as a workaround for a clang-3.8 (aarch64) bug + volatile VP8StatusCode status; + int has_animation = 0; + assert(headers != NULL); + // fill out headers, ignore width/height/has_alpha. + status = ParseHeadersInternal(headers->data, headers->data_size, + NULL, NULL, NULL, &has_animation, + NULL, headers); + if (status == VP8_STATUS_OK || status == VP8_STATUS_NOT_ENOUGH_DATA) { + // The WebPDemux API + libwebp can be used to decode individual + // uncomposited frames or the WebPAnimDecoder can be used to fully + // reconstruct them (see webp/demux.h). + if (has_animation) { + status = VP8_STATUS_UNSUPPORTED_FEATURE; + } + } + return status; +} + +//------------------------------------------------------------------------------ +// WebPDecParams + +void WebPResetDecParams(WebPDecParams* const params) { + if (params != NULL) { + memset(params, 0, sizeof(*params)); + } +} + +//------------------------------------------------------------------------------ +// "Into" decoding variants + +// Main flow +static VP8StatusCode DecodeInto(const uint8_t* const data, size_t data_size, + WebPDecParams* const params) { + VP8StatusCode status; + VP8Io io; + WebPHeaderStructure headers; + + headers.data = data; + headers.data_size = data_size; + headers.have_all_data = 1; + status = WebPParseHeaders(&headers); // Process Pre-VP8 chunks. + if (status != VP8_STATUS_OK) { + return status; + } + + assert(params != NULL); + VP8InitIo(&io); + io.data = headers.data + headers.offset; + io.data_size = headers.data_size - headers.offset; + WebPInitCustomIo(params, &io); // Plug the I/O functions. + + if (!headers.is_lossless) { + VP8Decoder* const dec = VP8New(); + if (dec == NULL) { + return VP8_STATUS_OUT_OF_MEMORY; + } + dec->alpha_data_ = headers.alpha_data; + dec->alpha_data_size_ = headers.alpha_data_size; + + // Decode bitstream header, update io->width/io->height. + if (!VP8GetHeaders(dec, &io)) { + status = dec->status_; // An error occurred. Grab error status. + } else { + // Allocate/check output buffers. + status = WebPAllocateDecBuffer(io.width, io.height, params->options, + params->output); + if (status == VP8_STATUS_OK) { // Decode + // This change must be done before calling VP8Decode() + dec->mt_method_ = VP8GetThreadMethod(params->options, &headers, + io.width, io.height); + VP8InitDithering(params->options, dec); + if (!VP8Decode(dec, &io)) { + status = dec->status_; + } + } + } + VP8Delete(dec); + } else { + VP8LDecoder* const dec = VP8LNew(); + if (dec == NULL) { + return VP8_STATUS_OUT_OF_MEMORY; + } + if (!VP8LDecodeHeader(dec, &io)) { + status = dec->status_; // An error occurred. Grab error status. + } else { + // Allocate/check output buffers. + status = WebPAllocateDecBuffer(io.width, io.height, params->options, + params->output); + if (status == VP8_STATUS_OK) { // Decode + if (!VP8LDecodeImage(dec)) { + status = dec->status_; + } + } + } + VP8LDelete(dec); + } + + if (status != VP8_STATUS_OK) { + WebPFreeDecBuffer(params->output); + } else { + if (params->options != NULL && params->options->flip) { + // This restores the original stride values if options->flip was used + // during the call to WebPAllocateDecBuffer above. + status = WebPFlipBuffer(params->output); + } + } + return status; +} + +// Helpers +static uint8_t* DecodeIntoRGBABuffer(WEBP_CSP_MODE colorspace, + const uint8_t* const data, + size_t data_size, + uint8_t* const rgba, + int stride, size_t size) { + WebPDecParams params; + WebPDecBuffer buf; + if (rgba == NULL) { + return NULL; + } + WebPInitDecBuffer(&buf); + WebPResetDecParams(¶ms); + params.output = &buf; + buf.colorspace = colorspace; + buf.u.RGBA.rgba = rgba; + buf.u.RGBA.stride = stride; + buf.u.RGBA.size = size; + buf.is_external_memory = 1; + if (DecodeInto(data, data_size, ¶ms) != VP8_STATUS_OK) { + return NULL; + } + return rgba; +} + +uint8_t* WebPDecodeRGBInto(const uint8_t* data, size_t data_size, + uint8_t* output, size_t size, int stride) { + return DecodeIntoRGBABuffer(MODE_RGB, data, data_size, output, stride, size); +} + +uint8_t* WebPDecodeRGBAInto(const uint8_t* data, size_t data_size, + uint8_t* output, size_t size, int stride) { + return DecodeIntoRGBABuffer(MODE_RGBA, data, data_size, output, stride, size); +} + +uint8_t* WebPDecodeARGBInto(const uint8_t* data, size_t data_size, + uint8_t* output, size_t size, int stride) { + return DecodeIntoRGBABuffer(MODE_ARGB, data, data_size, output, stride, size); +} + +uint8_t* WebPDecodeBGRInto(const uint8_t* data, size_t data_size, + uint8_t* output, size_t size, int stride) { + return DecodeIntoRGBABuffer(MODE_BGR, data, data_size, output, stride, size); +} + +uint8_t* WebPDecodeBGRAInto(const uint8_t* data, size_t data_size, + uint8_t* output, size_t size, int stride) { + return DecodeIntoRGBABuffer(MODE_BGRA, data, data_size, output, stride, size); +} + +uint8_t* WebPDecodeYUVInto(const uint8_t* data, size_t data_size, + uint8_t* luma, size_t luma_size, int luma_stride, + uint8_t* u, size_t u_size, int u_stride, + uint8_t* v, size_t v_size, int v_stride) { + WebPDecParams params; + WebPDecBuffer output; + if (luma == NULL) return NULL; + WebPInitDecBuffer(&output); + WebPResetDecParams(¶ms); + params.output = &output; + output.colorspace = MODE_YUV; + output.u.YUVA.y = luma; + output.u.YUVA.y_stride = luma_stride; + output.u.YUVA.y_size = luma_size; + output.u.YUVA.u = u; + output.u.YUVA.u_stride = u_stride; + output.u.YUVA.u_size = u_size; + output.u.YUVA.v = v; + output.u.YUVA.v_stride = v_stride; + output.u.YUVA.v_size = v_size; + output.is_external_memory = 1; + if (DecodeInto(data, data_size, ¶ms) != VP8_STATUS_OK) { + return NULL; + } + return luma; +} + +//------------------------------------------------------------------------------ + +static uint8_t* Decode(WEBP_CSP_MODE mode, const uint8_t* const data, + size_t data_size, int* const width, int* const height, + WebPDecBuffer* const keep_info) { + WebPDecParams params; + WebPDecBuffer output; + + WebPInitDecBuffer(&output); + WebPResetDecParams(¶ms); + params.output = &output; + output.colorspace = mode; + + // Retrieve (and report back) the required dimensions from bitstream. + if (!WebPGetInfo(data, data_size, &output.width, &output.height)) { + return NULL; + } + if (width != NULL) *width = output.width; + if (height != NULL) *height = output.height; + + // Decode + if (DecodeInto(data, data_size, ¶ms) != VP8_STATUS_OK) { + return NULL; + } + if (keep_info != NULL) { // keep track of the side-info + WebPCopyDecBuffer(&output, keep_info); + } + // return decoded samples (don't clear 'output'!) + return WebPIsRGBMode(mode) ? output.u.RGBA.rgba : output.u.YUVA.y; +} + +uint8_t* WebPDecodeRGB(const uint8_t* data, size_t data_size, + int* width, int* height) { + return Decode(MODE_RGB, data, data_size, width, height, NULL); +} + +uint8_t* WebPDecodeRGBA(const uint8_t* data, size_t data_size, + int* width, int* height) { + return Decode(MODE_RGBA, data, data_size, width, height, NULL); +} + +uint8_t* WebPDecodeARGB(const uint8_t* data, size_t data_size, + int* width, int* height) { + return Decode(MODE_ARGB, data, data_size, width, height, NULL); +} + +uint8_t* WebPDecodeBGR(const uint8_t* data, size_t data_size, + int* width, int* height) { + return Decode(MODE_BGR, data, data_size, width, height, NULL); +} + +uint8_t* WebPDecodeBGRA(const uint8_t* data, size_t data_size, + int* width, int* height) { + return Decode(MODE_BGRA, data, data_size, width, height, NULL); +} + +uint8_t* WebPDecodeYUV(const uint8_t* data, size_t data_size, + int* width, int* height, uint8_t** u, uint8_t** v, + int* stride, int* uv_stride) { + // data, width and height are checked by Decode(). + if (u == NULL || v == NULL || stride == NULL || uv_stride == NULL) { + return NULL; + } + + { + WebPDecBuffer output; // only to preserve the side-infos + uint8_t* const out = Decode(MODE_YUV, data, data_size, + width, height, &output); + + if (out != NULL) { + const WebPYUVABuffer* const buf = &output.u.YUVA; + *u = buf->u; + *v = buf->v; + *stride = buf->y_stride; + *uv_stride = buf->u_stride; + assert(buf->u_stride == buf->v_stride); + } + return out; + } +} + +static void DefaultFeatures(WebPBitstreamFeatures* const features) { + assert(features != NULL); + memset(features, 0, sizeof(*features)); +} + +static VP8StatusCode GetFeatures(const uint8_t* const data, size_t data_size, + WebPBitstreamFeatures* const features) { + if (features == NULL || data == NULL) { + return VP8_STATUS_INVALID_PARAM; + } + DefaultFeatures(features); + + // Only parse enough of the data to retrieve the features. + return ParseHeadersInternal(data, data_size, + &features->width, &features->height, + &features->has_alpha, &features->has_animation, + &features->format, NULL); +} + +//------------------------------------------------------------------------------ +// WebPGetInfo() + +int WebPGetInfo(const uint8_t* data, size_t data_size, + int* width, int* height) { + WebPBitstreamFeatures features; + + if (GetFeatures(data, data_size, &features) != VP8_STATUS_OK) { + return 0; + } + + if (width != NULL) { + *width = features.width; + } + if (height != NULL) { + *height = features.height; + } + + return 1; +} + +//------------------------------------------------------------------------------ +// Advance decoding API + +int WebPInitDecoderConfigInternal(WebPDecoderConfig* config, + int version) { + if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) { + return 0; // version mismatch + } + if (config == NULL) { + return 0; + } + memset(config, 0, sizeof(*config)); + DefaultFeatures(&config->input); + WebPInitDecBuffer(&config->output); + return 1; +} + +VP8StatusCode WebPGetFeaturesInternal(const uint8_t* data, size_t data_size, + WebPBitstreamFeatures* features, + int version) { + if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) { + return VP8_STATUS_INVALID_PARAM; // version mismatch + } + if (features == NULL) { + return VP8_STATUS_INVALID_PARAM; + } + return GetFeatures(data, data_size, features); +} + +VP8StatusCode WebPDecode(const uint8_t* data, size_t data_size, + WebPDecoderConfig* config) { + WebPDecParams params; + VP8StatusCode status; + + if (config == NULL) { + return VP8_STATUS_INVALID_PARAM; + } + + status = GetFeatures(data, data_size, &config->input); + if (status != VP8_STATUS_OK) { + if (status == VP8_STATUS_NOT_ENOUGH_DATA) { + return VP8_STATUS_BITSTREAM_ERROR; // Not-enough-data treated as error. + } + return status; + } + + WebPResetDecParams(¶ms); + params.options = &config->options; + params.output = &config->output; + if (WebPAvoidSlowMemory(params.output, &config->input)) { + // decoding to slow memory: use a temporary in-mem buffer to decode into. + WebPDecBuffer in_mem_buffer; + WebPInitDecBuffer(&in_mem_buffer); + in_mem_buffer.colorspace = config->output.colorspace; + in_mem_buffer.width = config->input.width; + in_mem_buffer.height = config->input.height; + params.output = &in_mem_buffer; + status = DecodeInto(data, data_size, ¶ms); + if (status == VP8_STATUS_OK) { // do the slow-copy + status = WebPCopyDecBufferPixels(&in_mem_buffer, &config->output); + } + WebPFreeDecBuffer(&in_mem_buffer); + } else { + status = DecodeInto(data, data_size, ¶ms); + } + + return status; +} + +//------------------------------------------------------------------------------ +// Cropping and rescaling. + +int WebPCheckCropDimensions(int image_width, int image_height, + int x, int y, int w, int h) { + return !(x < 0 || y < 0 || w <= 0 || h <= 0 || + x >= image_width || w > image_width || w > image_width - x || + y >= image_height || h > image_height || h > image_height - y); +} + +int WebPIoInitFromOptions(const WebPDecoderOptions* const options, + VP8Io* const io, WEBP_CSP_MODE src_colorspace) { + const int W = io->width; + const int H = io->height; + int x = 0, y = 0, w = W, h = H; + + // Cropping + io->use_cropping = (options != NULL) && options->use_cropping; + if (io->use_cropping) { + w = options->crop_width; + h = options->crop_height; + x = options->crop_left; + y = options->crop_top; + if (!WebPIsRGBMode(src_colorspace)) { // only snap for YUV420 + x &= ~1; + y &= ~1; + } + if (!WebPCheckCropDimensions(W, H, x, y, w, h)) { + return 0; // out of frame boundary error + } + } + io->crop_left = x; + io->crop_top = y; + io->crop_right = x + w; + io->crop_bottom = y + h; + io->mb_w = w; + io->mb_h = h; + + // Scaling + io->use_scaling = (options != NULL) && options->use_scaling; + if (io->use_scaling) { + int scaled_width = options->scaled_width; + int scaled_height = options->scaled_height; + if (!WebPRescalerGetScaledDimensions(w, h, &scaled_width, &scaled_height)) { + return 0; + } + io->scaled_width = scaled_width; + io->scaled_height = scaled_height; + } + + // Filter + io->bypass_filtering = (options != NULL) && options->bypass_filtering; + + // Fancy upsampler +#ifdef FANCY_UPSAMPLING + io->fancy_upsampling = (options == NULL) || (!options->no_fancy_upsampling); +#endif + + if (io->use_scaling) { + // disable filter (only for large downscaling ratio). + io->bypass_filtering |= (io->scaled_width < W * 3 / 4) && + (io->scaled_height < H * 3 / 4); + io->fancy_upsampling = 0; + } + return 1; +} + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/src/dec/webpi_dec.h b/third-party/webp/libwebp/src/dec/webpi_dec.h new file mode 100644 index 0000000000..3b97388c71 --- /dev/null +++ b/third-party/webp/libwebp/src/dec/webpi_dec.h @@ -0,0 +1,137 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Internal header: WebP decoding parameters and custom IO on buffer +// +// Author: somnath@google.com (Somnath Banerjee) + +#ifndef WEBP_DEC_WEBPI_DEC_H_ +#define WEBP_DEC_WEBPI_DEC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "src/utils/rescaler_utils.h" +#include "src/dec/vp8_dec.h" + +//------------------------------------------------------------------------------ +// WebPDecParams: Decoding output parameters. Transient internal object. + +typedef struct WebPDecParams WebPDecParams; +typedef int (*OutputFunc)(const VP8Io* const io, WebPDecParams* const p); +typedef int (*OutputAlphaFunc)(const VP8Io* const io, WebPDecParams* const p, + int expected_num_out_lines); +typedef int (*OutputRowFunc)(WebPDecParams* const p, int y_pos, + int max_out_lines); + +struct WebPDecParams { + WebPDecBuffer* output; // output buffer. + uint8_t* tmp_y, *tmp_u, *tmp_v; // cache for the fancy upsampler + // or used for tmp rescaling + + int last_y; // coordinate of the line that was last output + const WebPDecoderOptions* options; // if not NULL, use alt decoding features + + WebPRescaler* scaler_y, *scaler_u, *scaler_v, *scaler_a; // rescalers + void* memory; // overall scratch memory for the output work. + + OutputFunc emit; // output RGB or YUV samples + OutputAlphaFunc emit_alpha; // output alpha channel + OutputRowFunc emit_alpha_row; // output one line of rescaled alpha values +}; + +// Should be called first, before any use of the WebPDecParams object. +void WebPResetDecParams(WebPDecParams* const params); + +//------------------------------------------------------------------------------ +// Header parsing helpers + +// Structure storing a description of the RIFF headers. +typedef struct { + const uint8_t* data; // input buffer + size_t data_size; // input buffer size + int have_all_data; // true if all data is known to be available + size_t offset; // offset to main data chunk (VP8 or VP8L) + const uint8_t* alpha_data; // points to alpha chunk (if present) + size_t alpha_data_size; // alpha chunk size + size_t compressed_size; // VP8/VP8L compressed data size + size_t riff_size; // size of the riff payload (or 0 if absent) + int is_lossless; // true if a VP8L chunk is present +} WebPHeaderStructure; + +// Skips over all valid chunks prior to the first VP8/VP8L frame header. +// Returns: VP8_STATUS_OK, VP8_STATUS_BITSTREAM_ERROR (invalid header/chunk), +// VP8_STATUS_NOT_ENOUGH_DATA (partial input) or VP8_STATUS_UNSUPPORTED_FEATURE +// in the case of non-decodable features (animation for instance). +// In 'headers', compressed_size, offset, alpha_data, alpha_size, and lossless +// fields are updated appropriately upon success. +VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers); + +//------------------------------------------------------------------------------ +// Misc utils + +// Returns true if crop dimensions are within image bounds. +int WebPCheckCropDimensions(int image_width, int image_height, + int x, int y, int w, int h); + +// Initializes VP8Io with custom setup, io and teardown functions. The default +// hooks will use the supplied 'params' as io->opaque handle. +void WebPInitCustomIo(WebPDecParams* const params, VP8Io* const io); + +// Setup crop_xxx fields, mb_w and mb_h in io. 'src_colorspace' refers +// to the *compressed* format, not the output one. +int WebPIoInitFromOptions(const WebPDecoderOptions* const options, + VP8Io* const io, WEBP_CSP_MODE src_colorspace); + +//------------------------------------------------------------------------------ +// Internal functions regarding WebPDecBuffer memory (in buffer.c). +// Don't really need to be externally visible for now. + +// Prepare 'buffer' with the requested initial dimensions width/height. +// If no external storage is supplied, initializes buffer by allocating output +// memory and setting up the stride information. Validate the parameters. Return +// an error code in case of problem (no memory, or invalid stride / size / +// dimension / etc.). If *options is not NULL, also verify that the options' +// parameters are valid and apply them to the width/height dimensions of the +// output buffer. This takes cropping / scaling / rotation into account. +// Also incorporates the options->flip flag to flip the buffer parameters if +// needed. +VP8StatusCode WebPAllocateDecBuffer(int width, int height, + const WebPDecoderOptions* const options, + WebPDecBuffer* const buffer); + +// Flip buffer vertically by negating the various strides. +VP8StatusCode WebPFlipBuffer(WebPDecBuffer* const buffer); + +// Copy 'src' into 'dst' buffer, making sure 'dst' is not marked as owner of the +// memory (still held by 'src'). No pixels are copied. +void WebPCopyDecBuffer(const WebPDecBuffer* const src, + WebPDecBuffer* const dst); + +// Copy and transfer ownership from src to dst (beware of parameter order!) +void WebPGrabDecBuffer(WebPDecBuffer* const src, WebPDecBuffer* const dst); + +// Copy pixels from 'src' into a *preallocated* 'dst' buffer. Returns +// VP8_STATUS_INVALID_PARAM if the 'dst' is not set up correctly for the copy. +VP8StatusCode WebPCopyDecBufferPixels(const WebPDecBuffer* const src, + WebPDecBuffer* const dst); + +// Returns true if decoding will be slow with the current configuration +// and bitstream features. +int WebPAvoidSlowMemory(const WebPDecBuffer* const output, + const WebPBitstreamFeatures* const features); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_DEC_WEBPI_DEC_H_ diff --git a/third-party/webp/libwebp/src/demux/Makefile.am b/third-party/webp/libwebp/src/demux/Makefile.am new file mode 100644 index 0000000000..2df2db5b92 --- /dev/null +++ b/third-party/webp/libwebp/src/demux/Makefile.am @@ -0,0 +1,18 @@ +AM_CPPFLAGS += -I$(top_builddir) -I$(top_srcdir) +lib_LTLIBRARIES = libwebpdemux.la + +libwebpdemux_la_SOURCES = +libwebpdemux_la_SOURCES += anim_decode.c demux.c + +libwebpdemuxinclude_HEADERS = +libwebpdemuxinclude_HEADERS += ../webp/decode.h +libwebpdemuxinclude_HEADERS += ../webp/demux.h +libwebpdemuxinclude_HEADERS += ../webp/mux_types.h +libwebpdemuxinclude_HEADERS += ../webp/types.h +noinst_HEADERS = +noinst_HEADERS += ../webp/format_constants.h + +libwebpdemux_la_LIBADD = ../libwebp.la +libwebpdemux_la_LDFLAGS = -no-undefined -version-info 2:14:0 +libwebpdemuxincludedir = $(includedir)/webp +pkgconfig_DATA = libwebpdemux.pc diff --git a/third-party/webp/libwebp/src/demux/anim_decode.c b/third-party/webp/libwebp/src/demux/anim_decode.c new file mode 100644 index 0000000000..e077ffb536 --- /dev/null +++ b/third-party/webp/libwebp/src/demux/anim_decode.c @@ -0,0 +1,473 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// AnimDecoder implementation. +// + +#ifdef HAVE_CONFIG_H +#include "src/webp/config.h" +#endif + +#include +#include + +#include "src/utils/utils.h" +#include "src/webp/decode.h" +#include "src/webp/demux.h" + +#define NUM_CHANNELS 4 + +// Channel extraction from a uint32_t representation of a uint8_t RGBA/BGRA +// buffer. +#ifdef WORDS_BIGENDIAN +#define CHANNEL_SHIFT(i) (24 - (i) * 8) +#else +#define CHANNEL_SHIFT(i) ((i) * 8) +#endif + +typedef void (*BlendRowFunc)(uint32_t* const, const uint32_t* const, int); +static void BlendPixelRowNonPremult(uint32_t* const src, + const uint32_t* const dst, int num_pixels); +static void BlendPixelRowPremult(uint32_t* const src, const uint32_t* const dst, + int num_pixels); + +struct WebPAnimDecoder { + WebPDemuxer* demux_; // Demuxer created from given WebP bitstream. + WebPDecoderConfig config_; // Decoder config. + // Note: we use a pointer to a function blending multiple pixels at a time to + // allow possible inlining of per-pixel blending function. + BlendRowFunc blend_func_; // Pointer to the chose blend row function. + WebPAnimInfo info_; // Global info about the animation. + uint8_t* curr_frame_; // Current canvas (not disposed). + uint8_t* prev_frame_disposed_; // Previous canvas (properly disposed). + int prev_frame_timestamp_; // Previous frame timestamp (milliseconds). + WebPIterator prev_iter_; // Iterator object for previous frame. + int prev_frame_was_keyframe_; // True if previous frame was a keyframe. + int next_frame_; // Index of the next frame to be decoded + // (starting from 1). +}; + +static void DefaultDecoderOptions(WebPAnimDecoderOptions* const dec_options) { + dec_options->color_mode = MODE_RGBA; + dec_options->use_threads = 0; +} + +int WebPAnimDecoderOptionsInitInternal(WebPAnimDecoderOptions* dec_options, + int abi_version) { + if (dec_options == NULL || + WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_DEMUX_ABI_VERSION)) { + return 0; + } + DefaultDecoderOptions(dec_options); + return 1; +} + +static int ApplyDecoderOptions(const WebPAnimDecoderOptions* const dec_options, + WebPAnimDecoder* const dec) { + WEBP_CSP_MODE mode; + WebPDecoderConfig* config = &dec->config_; + assert(dec_options != NULL); + + mode = dec_options->color_mode; + if (mode != MODE_RGBA && mode != MODE_BGRA && + mode != MODE_rgbA && mode != MODE_bgrA) { + return 0; + } + dec->blend_func_ = (mode == MODE_RGBA || mode == MODE_BGRA) + ? &BlendPixelRowNonPremult + : &BlendPixelRowPremult; + WebPInitDecoderConfig(config); + config->output.colorspace = mode; + config->output.is_external_memory = 1; + config->options.use_threads = dec_options->use_threads; + // Note: config->output.u.RGBA is set at the time of decoding each frame. + return 1; +} + +WebPAnimDecoder* WebPAnimDecoderNewInternal( + const WebPData* webp_data, const WebPAnimDecoderOptions* dec_options, + int abi_version) { + WebPAnimDecoderOptions options; + WebPAnimDecoder* dec = NULL; + WebPBitstreamFeatures features; + if (webp_data == NULL || + WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_DEMUX_ABI_VERSION)) { + return NULL; + } + + // Validate the bitstream before doing expensive allocations. The demuxer may + // be more tolerant than the decoder. + if (WebPGetFeatures(webp_data->bytes, webp_data->size, &features) != + VP8_STATUS_OK) { + return NULL; + } + + // Note: calloc() so that the pointer members are initialized to NULL. + dec = (WebPAnimDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec)); + if (dec == NULL) goto Error; + + if (dec_options != NULL) { + options = *dec_options; + } else { + DefaultDecoderOptions(&options); + } + if (!ApplyDecoderOptions(&options, dec)) goto Error; + + dec->demux_ = WebPDemux(webp_data); + if (dec->demux_ == NULL) goto Error; + + dec->info_.canvas_width = WebPDemuxGetI(dec->demux_, WEBP_FF_CANVAS_WIDTH); + dec->info_.canvas_height = WebPDemuxGetI(dec->demux_, WEBP_FF_CANVAS_HEIGHT); + dec->info_.loop_count = WebPDemuxGetI(dec->demux_, WEBP_FF_LOOP_COUNT); + dec->info_.bgcolor = WebPDemuxGetI(dec->demux_, WEBP_FF_BACKGROUND_COLOR); + dec->info_.frame_count = WebPDemuxGetI(dec->demux_, WEBP_FF_FRAME_COUNT); + + // Note: calloc() because we fill frame with zeroes as well. + dec->curr_frame_ = (uint8_t*)WebPSafeCalloc( + dec->info_.canvas_width * NUM_CHANNELS, dec->info_.canvas_height); + if (dec->curr_frame_ == NULL) goto Error; + dec->prev_frame_disposed_ = (uint8_t*)WebPSafeCalloc( + dec->info_.canvas_width * NUM_CHANNELS, dec->info_.canvas_height); + if (dec->prev_frame_disposed_ == NULL) goto Error; + + WebPAnimDecoderReset(dec); + return dec; + + Error: + WebPAnimDecoderDelete(dec); + return NULL; +} + +int WebPAnimDecoderGetInfo(const WebPAnimDecoder* dec, WebPAnimInfo* info) { + if (dec == NULL || info == NULL) return 0; + *info = dec->info_; + return 1; +} + +// Returns true if the frame covers the full canvas. +static int IsFullFrame(int width, int height, int canvas_width, + int canvas_height) { + return (width == canvas_width && height == canvas_height); +} + +// Clear the canvas to transparent. +static int ZeroFillCanvas(uint8_t* buf, uint32_t canvas_width, + uint32_t canvas_height) { + const uint64_t size = + (uint64_t)canvas_width * canvas_height * NUM_CHANNELS * sizeof(*buf); + if (!CheckSizeOverflow(size)) return 0; + memset(buf, 0, (size_t)size); + return 1; +} + +// Clear given frame rectangle to transparent. +static void ZeroFillFrameRect(uint8_t* buf, int buf_stride, int x_offset, + int y_offset, int width, int height) { + int j; + assert(width * NUM_CHANNELS <= buf_stride); + buf += y_offset * buf_stride + x_offset * NUM_CHANNELS; + for (j = 0; j < height; ++j) { + memset(buf, 0, width * NUM_CHANNELS); + buf += buf_stride; + } +} + +// Copy width * height pixels from 'src' to 'dst'. +static int CopyCanvas(const uint8_t* src, uint8_t* dst, + uint32_t width, uint32_t height) { + const uint64_t size = (uint64_t)width * height * NUM_CHANNELS; + if (!CheckSizeOverflow(size)) return 0; + assert(src != NULL && dst != NULL); + memcpy(dst, src, (size_t)size); + return 1; +} + +// Returns true if the current frame is a key-frame. +static int IsKeyFrame(const WebPIterator* const curr, + const WebPIterator* const prev, + int prev_frame_was_key_frame, + int canvas_width, int canvas_height) { + if (curr->frame_num == 1) { + return 1; + } else if ((!curr->has_alpha || curr->blend_method == WEBP_MUX_NO_BLEND) && + IsFullFrame(curr->width, curr->height, + canvas_width, canvas_height)) { + return 1; + } else { + return (prev->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) && + (IsFullFrame(prev->width, prev->height, canvas_width, + canvas_height) || + prev_frame_was_key_frame); + } +} + + +// Blend a single channel of 'src' over 'dst', given their alpha channel values. +// 'src' and 'dst' are assumed to be NOT pre-multiplied by alpha. +static uint8_t BlendChannelNonPremult(uint32_t src, uint8_t src_a, + uint32_t dst, uint8_t dst_a, + uint32_t scale, int shift) { + const uint8_t src_channel = (src >> shift) & 0xff; + const uint8_t dst_channel = (dst >> shift) & 0xff; + const uint32_t blend_unscaled = src_channel * src_a + dst_channel * dst_a; + assert(blend_unscaled < (1ULL << 32) / scale); + return (blend_unscaled * scale) >> CHANNEL_SHIFT(3); +} + +// Blend 'src' over 'dst' assuming they are NOT pre-multiplied by alpha. +static uint32_t BlendPixelNonPremult(uint32_t src, uint32_t dst) { + const uint8_t src_a = (src >> CHANNEL_SHIFT(3)) & 0xff; + + if (src_a == 0) { + return dst; + } else { + const uint8_t dst_a = (dst >> CHANNEL_SHIFT(3)) & 0xff; + // This is the approximate integer arithmetic for the actual formula: + // dst_factor_a = (dst_a * (255 - src_a)) / 255. + const uint8_t dst_factor_a = (dst_a * (256 - src_a)) >> 8; + const uint8_t blend_a = src_a + dst_factor_a; + const uint32_t scale = (1UL << 24) / blend_a; + + const uint8_t blend_r = BlendChannelNonPremult( + src, src_a, dst, dst_factor_a, scale, CHANNEL_SHIFT(0)); + const uint8_t blend_g = BlendChannelNonPremult( + src, src_a, dst, dst_factor_a, scale, CHANNEL_SHIFT(1)); + const uint8_t blend_b = BlendChannelNonPremult( + src, src_a, dst, dst_factor_a, scale, CHANNEL_SHIFT(2)); + assert(src_a + dst_factor_a < 256); + + return ((uint32_t)blend_r << CHANNEL_SHIFT(0)) | + ((uint32_t)blend_g << CHANNEL_SHIFT(1)) | + ((uint32_t)blend_b << CHANNEL_SHIFT(2)) | + ((uint32_t)blend_a << CHANNEL_SHIFT(3)); + } +} + +// Blend 'num_pixels' in 'src' over 'dst' assuming they are NOT pre-multiplied +// by alpha. +static void BlendPixelRowNonPremult(uint32_t* const src, + const uint32_t* const dst, int num_pixels) { + int i; + for (i = 0; i < num_pixels; ++i) { + const uint8_t src_alpha = (src[i] >> CHANNEL_SHIFT(3)) & 0xff; + if (src_alpha != 0xff) { + src[i] = BlendPixelNonPremult(src[i], dst[i]); + } + } +} + +// Individually multiply each channel in 'pix' by 'scale'. +static WEBP_INLINE uint32_t ChannelwiseMultiply(uint32_t pix, uint32_t scale) { + uint32_t mask = 0x00FF00FF; + uint32_t rb = ((pix & mask) * scale) >> 8; + uint32_t ag = ((pix >> 8) & mask) * scale; + return (rb & mask) | (ag & ~mask); +} + +// Blend 'src' over 'dst' assuming they are pre-multiplied by alpha. +static uint32_t BlendPixelPremult(uint32_t src, uint32_t dst) { + const uint8_t src_a = (src >> CHANNEL_SHIFT(3)) & 0xff; + return src + ChannelwiseMultiply(dst, 256 - src_a); +} + +// Blend 'num_pixels' in 'src' over 'dst' assuming they are pre-multiplied by +// alpha. +static void BlendPixelRowPremult(uint32_t* const src, const uint32_t* const dst, + int num_pixels) { + int i; + for (i = 0; i < num_pixels; ++i) { + const uint8_t src_alpha = (src[i] >> CHANNEL_SHIFT(3)) & 0xff; + if (src_alpha != 0xff) { + src[i] = BlendPixelPremult(src[i], dst[i]); + } + } +} + +// Returns two ranges ( pairs) at row 'canvas_y', that belong to +// 'src' but not 'dst'. A point range is empty if the corresponding width is 0. +static void FindBlendRangeAtRow(const WebPIterator* const src, + const WebPIterator* const dst, int canvas_y, + int* const left1, int* const width1, + int* const left2, int* const width2) { + const int src_max_x = src->x_offset + src->width; + const int dst_max_x = dst->x_offset + dst->width; + const int dst_max_y = dst->y_offset + dst->height; + assert(canvas_y >= src->y_offset && canvas_y < (src->y_offset + src->height)); + *left1 = -1; + *width1 = 0; + *left2 = -1; + *width2 = 0; + + if (canvas_y < dst->y_offset || canvas_y >= dst_max_y || + src->x_offset >= dst_max_x || src_max_x <= dst->x_offset) { + *left1 = src->x_offset; + *width1 = src->width; + return; + } + + if (src->x_offset < dst->x_offset) { + *left1 = src->x_offset; + *width1 = dst->x_offset - src->x_offset; + } + + if (src_max_x > dst_max_x) { + *left2 = dst_max_x; + *width2 = src_max_x - dst_max_x; + } +} + +int WebPAnimDecoderGetNext(WebPAnimDecoder* dec, + uint8_t** buf_ptr, int* timestamp_ptr) { + WebPIterator iter; + uint32_t width; + uint32_t height; + int is_key_frame; + int timestamp; + BlendRowFunc blend_row; + + if (dec == NULL || buf_ptr == NULL || timestamp_ptr == NULL) return 0; + if (!WebPAnimDecoderHasMoreFrames(dec)) return 0; + + width = dec->info_.canvas_width; + height = dec->info_.canvas_height; + blend_row = dec->blend_func_; + + // Get compressed frame. + if (!WebPDemuxGetFrame(dec->demux_, dec->next_frame_, &iter)) { + return 0; + } + timestamp = dec->prev_frame_timestamp_ + iter.duration; + + // Initialize. + is_key_frame = IsKeyFrame(&iter, &dec->prev_iter_, + dec->prev_frame_was_keyframe_, width, height); + if (is_key_frame) { + if (!ZeroFillCanvas(dec->curr_frame_, width, height)) { + goto Error; + } + } else { + if (!CopyCanvas(dec->prev_frame_disposed_, dec->curr_frame_, + width, height)) { + goto Error; + } + } + + // Decode. + { + const uint8_t* in = iter.fragment.bytes; + const size_t in_size = iter.fragment.size; + const uint32_t stride = width * NUM_CHANNELS; // at most 25 + 2 bits + const uint64_t out_offset = (uint64_t)iter.y_offset * stride + + (uint64_t)iter.x_offset * NUM_CHANNELS; // 53b + const uint64_t size = (uint64_t)iter.height * stride; // at most 25 + 27b + WebPDecoderConfig* const config = &dec->config_; + WebPRGBABuffer* const buf = &config->output.u.RGBA; + if ((size_t)size != size) goto Error; + buf->stride = (int)stride; + buf->size = (size_t)size; + buf->rgba = dec->curr_frame_ + out_offset; + + if (WebPDecode(in, in_size, config) != VP8_STATUS_OK) { + goto Error; + } + } + + // During the decoding of current frame, we may have set some pixels to be + // transparent (i.e. alpha < 255). However, the value of each of these + // pixels should have been determined by blending it against the value of + // that pixel in the previous frame if blending method of is WEBP_MUX_BLEND. + if (iter.frame_num > 1 && iter.blend_method == WEBP_MUX_BLEND && + !is_key_frame) { + if (dec->prev_iter_.dispose_method == WEBP_MUX_DISPOSE_NONE) { + int y; + // Blend transparent pixels with pixels in previous canvas. + for (y = 0; y < iter.height; ++y) { + const size_t offset = + (iter.y_offset + y) * width + iter.x_offset; + blend_row((uint32_t*)dec->curr_frame_ + offset, + (uint32_t*)dec->prev_frame_disposed_ + offset, iter.width); + } + } else { + int y; + assert(dec->prev_iter_.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND); + // We need to blend a transparent pixel with its value just after + // initialization. That is, blend it with: + // * Fully transparent pixel if it belongs to prevRect <-- No-op. + // * The pixel in the previous canvas otherwise <-- Need alpha-blending. + for (y = 0; y < iter.height; ++y) { + const int canvas_y = iter.y_offset + y; + int left1, width1, left2, width2; + FindBlendRangeAtRow(&iter, &dec->prev_iter_, canvas_y, &left1, &width1, + &left2, &width2); + if (width1 > 0) { + const size_t offset1 = canvas_y * width + left1; + blend_row((uint32_t*)dec->curr_frame_ + offset1, + (uint32_t*)dec->prev_frame_disposed_ + offset1, width1); + } + if (width2 > 0) { + const size_t offset2 = canvas_y * width + left2; + blend_row((uint32_t*)dec->curr_frame_ + offset2, + (uint32_t*)dec->prev_frame_disposed_ + offset2, width2); + } + } + } + } + + // Update info of the previous frame and dispose it for the next iteration. + dec->prev_frame_timestamp_ = timestamp; + WebPDemuxReleaseIterator(&dec->prev_iter_); + dec->prev_iter_ = iter; + dec->prev_frame_was_keyframe_ = is_key_frame; + CopyCanvas(dec->curr_frame_, dec->prev_frame_disposed_, width, height); + if (dec->prev_iter_.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) { + ZeroFillFrameRect(dec->prev_frame_disposed_, width * NUM_CHANNELS, + dec->prev_iter_.x_offset, dec->prev_iter_.y_offset, + dec->prev_iter_.width, dec->prev_iter_.height); + } + ++dec->next_frame_; + + // All OK, fill in the values. + *buf_ptr = dec->curr_frame_; + *timestamp_ptr = timestamp; + return 1; + + Error: + WebPDemuxReleaseIterator(&iter); + return 0; +} + +int WebPAnimDecoderHasMoreFrames(const WebPAnimDecoder* dec) { + if (dec == NULL) return 0; + return (dec->next_frame_ <= (int)dec->info_.frame_count); +} + +void WebPAnimDecoderReset(WebPAnimDecoder* dec) { + if (dec != NULL) { + dec->prev_frame_timestamp_ = 0; + WebPDemuxReleaseIterator(&dec->prev_iter_); + memset(&dec->prev_iter_, 0, sizeof(dec->prev_iter_)); + dec->prev_frame_was_keyframe_ = 0; + dec->next_frame_ = 1; + } +} + +const WebPDemuxer* WebPAnimDecoderGetDemuxer(const WebPAnimDecoder* dec) { + if (dec == NULL) return NULL; + return dec->demux_; +} + +void WebPAnimDecoderDelete(WebPAnimDecoder* dec) { + if (dec != NULL) { + WebPDemuxReleaseIterator(&dec->prev_iter_); + WebPDemuxDelete(dec->demux_); + WebPSafeFree(dec->curr_frame_); + WebPSafeFree(dec->prev_frame_disposed_); + WebPSafeFree(dec); + } +} diff --git a/third-party/webp/libwebp/src/demux/demux.c b/third-party/webp/libwebp/src/demux/demux.c new file mode 100644 index 0000000000..4b0d3f59e9 --- /dev/null +++ b/third-party/webp/libwebp/src/demux/demux.c @@ -0,0 +1,975 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// WebP container demux. +// + +#ifdef HAVE_CONFIG_H +#include "src/webp/config.h" +#endif + +#include +#include +#include + +#include "src/utils/utils.h" +#include "src/webp/decode.h" // WebPGetFeatures +#include "src/webp/demux.h" +#include "src/webp/format_constants.h" + +#define DMUX_MAJ_VERSION 1 +#define DMUX_MIN_VERSION 3 +#define DMUX_REV_VERSION 2 + +typedef struct { + size_t start_; // start location of the data + size_t end_; // end location + size_t riff_end_; // riff chunk end location, can be > end_. + size_t buf_size_; // size of the buffer + const uint8_t* buf_; +} MemBuffer; + +typedef struct { + size_t offset_; + size_t size_; +} ChunkData; + +typedef struct Frame { + int x_offset_, y_offset_; + int width_, height_; + int has_alpha_; + int duration_; + WebPMuxAnimDispose dispose_method_; + WebPMuxAnimBlend blend_method_; + int frame_num_; + int complete_; // img_components_ contains a full image. + ChunkData img_components_[2]; // 0=VP8{,L} 1=ALPH + struct Frame* next_; +} Frame; + +typedef struct Chunk { + ChunkData data_; + struct Chunk* next_; +} Chunk; + +struct WebPDemuxer { + MemBuffer mem_; + WebPDemuxState state_; + int is_ext_format_; + uint32_t feature_flags_; + int canvas_width_, canvas_height_; + int loop_count_; + uint32_t bgcolor_; + int num_frames_; + Frame* frames_; + Frame** frames_tail_; + Chunk* chunks_; // non-image chunks + Chunk** chunks_tail_; +}; + +typedef enum { + PARSE_OK, + PARSE_NEED_MORE_DATA, + PARSE_ERROR +} ParseStatus; + +typedef struct ChunkParser { + uint8_t id[4]; + ParseStatus (*parse)(WebPDemuxer* const dmux); + int (*valid)(const WebPDemuxer* const dmux); +} ChunkParser; + +static ParseStatus ParseSingleImage(WebPDemuxer* const dmux); +static ParseStatus ParseVP8X(WebPDemuxer* const dmux); +static int IsValidSimpleFormat(const WebPDemuxer* const dmux); +static int IsValidExtendedFormat(const WebPDemuxer* const dmux); + +static const ChunkParser kMasterChunks[] = { + { { 'V', 'P', '8', ' ' }, ParseSingleImage, IsValidSimpleFormat }, + { { 'V', 'P', '8', 'L' }, ParseSingleImage, IsValidSimpleFormat }, + { { 'V', 'P', '8', 'X' }, ParseVP8X, IsValidExtendedFormat }, + { { '0', '0', '0', '0' }, NULL, NULL }, +}; + +//------------------------------------------------------------------------------ + +int WebPGetDemuxVersion(void) { + return (DMUX_MAJ_VERSION << 16) | (DMUX_MIN_VERSION << 8) | DMUX_REV_VERSION; +} + +// ----------------------------------------------------------------------------- +// MemBuffer + +static int RemapMemBuffer(MemBuffer* const mem, + const uint8_t* data, size_t size) { + if (size < mem->buf_size_) return 0; // can't remap to a shorter buffer! + + mem->buf_ = data; + mem->end_ = mem->buf_size_ = size; + return 1; +} + +static int InitMemBuffer(MemBuffer* const mem, + const uint8_t* data, size_t size) { + memset(mem, 0, sizeof(*mem)); + return RemapMemBuffer(mem, data, size); +} + +// Return the remaining data size available in 'mem'. +static WEBP_INLINE size_t MemDataSize(const MemBuffer* const mem) { + return (mem->end_ - mem->start_); +} + +// Return true if 'size' exceeds the end of the RIFF chunk. +static WEBP_INLINE int SizeIsInvalid(const MemBuffer* const mem, size_t size) { + return (size > mem->riff_end_ - mem->start_); +} + +static WEBP_INLINE void Skip(MemBuffer* const mem, size_t size) { + mem->start_ += size; +} + +static WEBP_INLINE void Rewind(MemBuffer* const mem, size_t size) { + mem->start_ -= size; +} + +static WEBP_INLINE const uint8_t* GetBuffer(MemBuffer* const mem) { + return mem->buf_ + mem->start_; +} + +// Read from 'mem' and skip the read bytes. +static WEBP_INLINE uint8_t ReadByte(MemBuffer* const mem) { + const uint8_t byte = mem->buf_[mem->start_]; + Skip(mem, 1); + return byte; +} + +static WEBP_INLINE int ReadLE16s(MemBuffer* const mem) { + const uint8_t* const data = mem->buf_ + mem->start_; + const int val = GetLE16(data); + Skip(mem, 2); + return val; +} + +static WEBP_INLINE int ReadLE24s(MemBuffer* const mem) { + const uint8_t* const data = mem->buf_ + mem->start_; + const int val = GetLE24(data); + Skip(mem, 3); + return val; +} + +static WEBP_INLINE uint32_t ReadLE32(MemBuffer* const mem) { + const uint8_t* const data = mem->buf_ + mem->start_; + const uint32_t val = GetLE32(data); + Skip(mem, 4); + return val; +} + +// ----------------------------------------------------------------------------- +// Secondary chunk parsing + +static void AddChunk(WebPDemuxer* const dmux, Chunk* const chunk) { + *dmux->chunks_tail_ = chunk; + chunk->next_ = NULL; + dmux->chunks_tail_ = &chunk->next_; +} + +// Add a frame to the end of the list, ensuring the last frame is complete. +// Returns true on success, false otherwise. +static int AddFrame(WebPDemuxer* const dmux, Frame* const frame) { + const Frame* const last_frame = *dmux->frames_tail_; + if (last_frame != NULL && !last_frame->complete_) return 0; + + *dmux->frames_tail_ = frame; + frame->next_ = NULL; + dmux->frames_tail_ = &frame->next_; + return 1; +} + +static void SetFrameInfo(size_t start_offset, size_t size, + int frame_num, int complete, + const WebPBitstreamFeatures* const features, + Frame* const frame) { + frame->img_components_[0].offset_ = start_offset; + frame->img_components_[0].size_ = size; + frame->width_ = features->width; + frame->height_ = features->height; + frame->has_alpha_ |= features->has_alpha; + frame->frame_num_ = frame_num; + frame->complete_ = complete; +} + +// Store image bearing chunks to 'frame'. 'min_size' is an optional size +// requirement, it may be zero. +static ParseStatus StoreFrame(int frame_num, uint32_t min_size, + MemBuffer* const mem, Frame* const frame) { + int alpha_chunks = 0; + int image_chunks = 0; + int done = (MemDataSize(mem) < CHUNK_HEADER_SIZE || + MemDataSize(mem) < min_size); + ParseStatus status = PARSE_OK; + + if (done) return PARSE_NEED_MORE_DATA; + + do { + const size_t chunk_start_offset = mem->start_; + const uint32_t fourcc = ReadLE32(mem); + const uint32_t payload_size = ReadLE32(mem); + uint32_t payload_size_padded; + size_t payload_available; + size_t chunk_size; + + if (payload_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR; + + payload_size_padded = payload_size + (payload_size & 1); + payload_available = (payload_size_padded > MemDataSize(mem)) + ? MemDataSize(mem) : payload_size_padded; + chunk_size = CHUNK_HEADER_SIZE + payload_available; + if (SizeIsInvalid(mem, payload_size_padded)) return PARSE_ERROR; + if (payload_size_padded > MemDataSize(mem)) status = PARSE_NEED_MORE_DATA; + + switch (fourcc) { + case MKFOURCC('A', 'L', 'P', 'H'): + if (alpha_chunks == 0) { + ++alpha_chunks; + frame->img_components_[1].offset_ = chunk_start_offset; + frame->img_components_[1].size_ = chunk_size; + frame->has_alpha_ = 1; + frame->frame_num_ = frame_num; + Skip(mem, payload_available); + } else { + goto Done; + } + break; + case MKFOURCC('V', 'P', '8', 'L'): + if (alpha_chunks > 0) return PARSE_ERROR; // VP8L has its own alpha + // fall through + case MKFOURCC('V', 'P', '8', ' '): + if (image_chunks == 0) { + // Extract the bitstream features, tolerating failures when the data + // is incomplete. + WebPBitstreamFeatures features; + const VP8StatusCode vp8_status = + WebPGetFeatures(mem->buf_ + chunk_start_offset, chunk_size, + &features); + if (status == PARSE_NEED_MORE_DATA && + vp8_status == VP8_STATUS_NOT_ENOUGH_DATA) { + return PARSE_NEED_MORE_DATA; + } else if (vp8_status != VP8_STATUS_OK) { + // We have enough data, and yet WebPGetFeatures() failed. + return PARSE_ERROR; + } + ++image_chunks; + SetFrameInfo(chunk_start_offset, chunk_size, frame_num, + status == PARSE_OK, &features, frame); + Skip(mem, payload_available); + } else { + goto Done; + } + break; + Done: + default: + // Restore fourcc/size when moving up one level in parsing. + Rewind(mem, CHUNK_HEADER_SIZE); + done = 1; + break; + } + + if (mem->start_ == mem->riff_end_) { + done = 1; + } else if (MemDataSize(mem) < CHUNK_HEADER_SIZE) { + status = PARSE_NEED_MORE_DATA; + } + } while (!done && status == PARSE_OK); + + return status; +} + +// Creates a new Frame if 'actual_size' is within bounds and 'mem' contains +// enough data ('min_size') to parse the payload. +// Returns PARSE_OK on success with *frame pointing to the new Frame. +// Returns PARSE_NEED_MORE_DATA with insufficient data, PARSE_ERROR otherwise. +static ParseStatus NewFrame(const MemBuffer* const mem, + uint32_t min_size, uint32_t actual_size, + Frame** frame) { + if (SizeIsInvalid(mem, min_size)) return PARSE_ERROR; + if (actual_size < min_size) return PARSE_ERROR; + if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA; + + *frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(**frame)); + return (*frame == NULL) ? PARSE_ERROR : PARSE_OK; +} + +// Parse a 'ANMF' chunk and any image bearing chunks that immediately follow. +// 'frame_chunk_size' is the previously validated, padded chunk size. +static ParseStatus ParseAnimationFrame( + WebPDemuxer* const dmux, uint32_t frame_chunk_size) { + const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG); + const uint32_t anmf_payload_size = frame_chunk_size - ANMF_CHUNK_SIZE; + int added_frame = 0; + int bits; + MemBuffer* const mem = &dmux->mem_; + Frame* frame; + size_t start_offset; + ParseStatus status = + NewFrame(mem, ANMF_CHUNK_SIZE, frame_chunk_size, &frame); + if (status != PARSE_OK) return status; + + frame->x_offset_ = 2 * ReadLE24s(mem); + frame->y_offset_ = 2 * ReadLE24s(mem); + frame->width_ = 1 + ReadLE24s(mem); + frame->height_ = 1 + ReadLE24s(mem); + frame->duration_ = ReadLE24s(mem); + bits = ReadByte(mem); + frame->dispose_method_ = + (bits & 1) ? WEBP_MUX_DISPOSE_BACKGROUND : WEBP_MUX_DISPOSE_NONE; + frame->blend_method_ = (bits & 2) ? WEBP_MUX_NO_BLEND : WEBP_MUX_BLEND; + if (frame->width_ * (uint64_t)frame->height_ >= MAX_IMAGE_AREA) { + WebPSafeFree(frame); + return PARSE_ERROR; + } + + // Store a frame only if the animation flag is set there is some data for + // this frame is available. + start_offset = mem->start_; + status = StoreFrame(dmux->num_frames_ + 1, anmf_payload_size, mem, frame); + if (status != PARSE_ERROR && mem->start_ - start_offset > anmf_payload_size) { + status = PARSE_ERROR; + } + if (status != PARSE_ERROR && is_animation && frame->frame_num_ > 0) { + added_frame = AddFrame(dmux, frame); + if (added_frame) { + ++dmux->num_frames_; + } else { + status = PARSE_ERROR; + } + } + + if (!added_frame) WebPSafeFree(frame); + return status; +} + +// General chunk storage, starting with the header at 'start_offset', allowing +// the user to request the payload via a fourcc string. 'size' includes the +// header and the unpadded payload size. +// Returns true on success, false otherwise. +static int StoreChunk(WebPDemuxer* const dmux, + size_t start_offset, uint32_t size) { + Chunk* const chunk = (Chunk*)WebPSafeCalloc(1ULL, sizeof(*chunk)); + if (chunk == NULL) return 0; + + chunk->data_.offset_ = start_offset; + chunk->data_.size_ = size; + AddChunk(dmux, chunk); + return 1; +} + +// ----------------------------------------------------------------------------- +// Primary chunk parsing + +static ParseStatus ReadHeader(MemBuffer* const mem) { + const size_t min_size = RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE; + uint32_t riff_size; + + // Basic file level validation. + if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA; + if (memcmp(GetBuffer(mem), "RIFF", CHUNK_SIZE_BYTES) || + memcmp(GetBuffer(mem) + CHUNK_HEADER_SIZE, "WEBP", CHUNK_SIZE_BYTES)) { + return PARSE_ERROR; + } + + riff_size = GetLE32(GetBuffer(mem) + TAG_SIZE); + if (riff_size < CHUNK_HEADER_SIZE) return PARSE_ERROR; + if (riff_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR; + + // There's no point in reading past the end of the RIFF chunk + mem->riff_end_ = riff_size + CHUNK_HEADER_SIZE; + if (mem->buf_size_ > mem->riff_end_) { + mem->buf_size_ = mem->end_ = mem->riff_end_; + } + + Skip(mem, RIFF_HEADER_SIZE); + return PARSE_OK; +} + +static ParseStatus ParseSingleImage(WebPDemuxer* const dmux) { + const size_t min_size = CHUNK_HEADER_SIZE; + MemBuffer* const mem = &dmux->mem_; + Frame* frame; + ParseStatus status; + int image_added = 0; + + if (dmux->frames_ != NULL) return PARSE_ERROR; + if (SizeIsInvalid(mem, min_size)) return PARSE_ERROR; + if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA; + + frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(*frame)); + if (frame == NULL) return PARSE_ERROR; + + // For the single image case we allow parsing of a partial frame, so no + // minimum size is imposed here. + status = StoreFrame(1, 0, &dmux->mem_, frame); + if (status != PARSE_ERROR) { + const int has_alpha = !!(dmux->feature_flags_ & ALPHA_FLAG); + // Clear any alpha when the alpha flag is missing. + if (!has_alpha && frame->img_components_[1].size_ > 0) { + frame->img_components_[1].offset_ = 0; + frame->img_components_[1].size_ = 0; + frame->has_alpha_ = 0; + } + + // Use the frame width/height as the canvas values for non-vp8x files. + // Also, set ALPHA_FLAG if this is a lossless image with alpha. + if (!dmux->is_ext_format_ && frame->width_ > 0 && frame->height_ > 0) { + dmux->state_ = WEBP_DEMUX_PARSED_HEADER; + dmux->canvas_width_ = frame->width_; + dmux->canvas_height_ = frame->height_; + dmux->feature_flags_ |= frame->has_alpha_ ? ALPHA_FLAG : 0; + } + if (!AddFrame(dmux, frame)) { + status = PARSE_ERROR; // last frame was left incomplete + } else { + image_added = 1; + dmux->num_frames_ = 1; + } + } + + if (!image_added) WebPSafeFree(frame); + return status; +} + +static ParseStatus ParseVP8XChunks(WebPDemuxer* const dmux) { + const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG); + MemBuffer* const mem = &dmux->mem_; + int anim_chunks = 0; + ParseStatus status = PARSE_OK; + + do { + int store_chunk = 1; + const size_t chunk_start_offset = mem->start_; + const uint32_t fourcc = ReadLE32(mem); + const uint32_t chunk_size = ReadLE32(mem); + uint32_t chunk_size_padded; + + if (chunk_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR; + + chunk_size_padded = chunk_size + (chunk_size & 1); + if (SizeIsInvalid(mem, chunk_size_padded)) return PARSE_ERROR; + + switch (fourcc) { + case MKFOURCC('V', 'P', '8', 'X'): { + return PARSE_ERROR; + } + case MKFOURCC('A', 'L', 'P', 'H'): + case MKFOURCC('V', 'P', '8', ' '): + case MKFOURCC('V', 'P', '8', 'L'): { + // check that this isn't an animation (all frames should be in an ANMF). + if (anim_chunks > 0 || is_animation) return PARSE_ERROR; + + Rewind(mem, CHUNK_HEADER_SIZE); + status = ParseSingleImage(dmux); + break; + } + case MKFOURCC('A', 'N', 'I', 'M'): { + if (chunk_size_padded < ANIM_CHUNK_SIZE) return PARSE_ERROR; + + if (MemDataSize(mem) < chunk_size_padded) { + status = PARSE_NEED_MORE_DATA; + } else if (anim_chunks == 0) { + ++anim_chunks; + dmux->bgcolor_ = ReadLE32(mem); + dmux->loop_count_ = ReadLE16s(mem); + Skip(mem, chunk_size_padded - ANIM_CHUNK_SIZE); + } else { + store_chunk = 0; + goto Skip; + } + break; + } + case MKFOURCC('A', 'N', 'M', 'F'): { + if (anim_chunks == 0) return PARSE_ERROR; // 'ANIM' precedes frames. + status = ParseAnimationFrame(dmux, chunk_size_padded); + break; + } + case MKFOURCC('I', 'C', 'C', 'P'): { + store_chunk = !!(dmux->feature_flags_ & ICCP_FLAG); + goto Skip; + } + case MKFOURCC('E', 'X', 'I', 'F'): { + store_chunk = !!(dmux->feature_flags_ & EXIF_FLAG); + goto Skip; + } + case MKFOURCC('X', 'M', 'P', ' '): { + store_chunk = !!(dmux->feature_flags_ & XMP_FLAG); + goto Skip; + } + Skip: + default: { + if (chunk_size_padded <= MemDataSize(mem)) { + if (store_chunk) { + // Store only the chunk header and unpadded size as only the payload + // will be returned to the user. + if (!StoreChunk(dmux, chunk_start_offset, + CHUNK_HEADER_SIZE + chunk_size)) { + return PARSE_ERROR; + } + } + Skip(mem, chunk_size_padded); + } else { + status = PARSE_NEED_MORE_DATA; + } + } + } + + if (mem->start_ == mem->riff_end_) { + break; + } else if (MemDataSize(mem) < CHUNK_HEADER_SIZE) { + status = PARSE_NEED_MORE_DATA; + } + } while (status == PARSE_OK); + + return status; +} + +static ParseStatus ParseVP8X(WebPDemuxer* const dmux) { + MemBuffer* const mem = &dmux->mem_; + uint32_t vp8x_size; + + if (MemDataSize(mem) < CHUNK_HEADER_SIZE) return PARSE_NEED_MORE_DATA; + + dmux->is_ext_format_ = 1; + Skip(mem, TAG_SIZE); // VP8X + vp8x_size = ReadLE32(mem); + if (vp8x_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR; + if (vp8x_size < VP8X_CHUNK_SIZE) return PARSE_ERROR; + vp8x_size += vp8x_size & 1; + if (SizeIsInvalid(mem, vp8x_size)) return PARSE_ERROR; + if (MemDataSize(mem) < vp8x_size) return PARSE_NEED_MORE_DATA; + + dmux->feature_flags_ = ReadByte(mem); + Skip(mem, 3); // Reserved. + dmux->canvas_width_ = 1 + ReadLE24s(mem); + dmux->canvas_height_ = 1 + ReadLE24s(mem); + if (dmux->canvas_width_ * (uint64_t)dmux->canvas_height_ >= MAX_IMAGE_AREA) { + return PARSE_ERROR; // image final dimension is too large + } + Skip(mem, vp8x_size - VP8X_CHUNK_SIZE); // skip any trailing data. + dmux->state_ = WEBP_DEMUX_PARSED_HEADER; + + if (SizeIsInvalid(mem, CHUNK_HEADER_SIZE)) return PARSE_ERROR; + if (MemDataSize(mem) < CHUNK_HEADER_SIZE) return PARSE_NEED_MORE_DATA; + + return ParseVP8XChunks(dmux); +} + +// ----------------------------------------------------------------------------- +// Format validation + +static int IsValidSimpleFormat(const WebPDemuxer* const dmux) { + const Frame* const frame = dmux->frames_; + if (dmux->state_ == WEBP_DEMUX_PARSING_HEADER) return 1; + + if (dmux->canvas_width_ <= 0 || dmux->canvas_height_ <= 0) return 0; + if (dmux->state_ == WEBP_DEMUX_DONE && frame == NULL) return 0; + + if (frame->width_ <= 0 || frame->height_ <= 0) return 0; + return 1; +} + +// If 'exact' is true, check that the image resolution matches the canvas. +// If 'exact' is false, check that the x/y offsets do not exceed the canvas. +static int CheckFrameBounds(const Frame* const frame, int exact, + int canvas_width, int canvas_height) { + if (exact) { + if (frame->x_offset_ != 0 || frame->y_offset_ != 0) { + return 0; + } + if (frame->width_ != canvas_width || frame->height_ != canvas_height) { + return 0; + } + } else { + if (frame->x_offset_ < 0 || frame->y_offset_ < 0) return 0; + if (frame->width_ + frame->x_offset_ > canvas_width) return 0; + if (frame->height_ + frame->y_offset_ > canvas_height) return 0; + } + return 1; +} + +static int IsValidExtendedFormat(const WebPDemuxer* const dmux) { + const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG); + const Frame* f = dmux->frames_; + + if (dmux->state_ == WEBP_DEMUX_PARSING_HEADER) return 1; + + if (dmux->canvas_width_ <= 0 || dmux->canvas_height_ <= 0) return 0; + if (dmux->loop_count_ < 0) return 0; + if (dmux->state_ == WEBP_DEMUX_DONE && dmux->frames_ == NULL) return 0; + if (dmux->feature_flags_ & ~ALL_VALID_FLAGS) return 0; // invalid bitstream + + while (f != NULL) { + const int cur_frame_set = f->frame_num_; + + // Check frame properties. + for (; f != NULL && f->frame_num_ == cur_frame_set; f = f->next_) { + const ChunkData* const image = f->img_components_; + const ChunkData* const alpha = f->img_components_ + 1; + + if (!is_animation && f->frame_num_ > 1) return 0; + + if (f->complete_) { + if (alpha->size_ == 0 && image->size_ == 0) return 0; + // Ensure alpha precedes image bitstream. + if (alpha->size_ > 0 && alpha->offset_ > image->offset_) { + return 0; + } + + if (f->width_ <= 0 || f->height_ <= 0) return 0; + } else { + // There shouldn't be a partial frame in a complete file. + if (dmux->state_ == WEBP_DEMUX_DONE) return 0; + + // Ensure alpha precedes image bitstream. + if (alpha->size_ > 0 && image->size_ > 0 && + alpha->offset_ > image->offset_) { + return 0; + } + // There shouldn't be any frames after an incomplete one. + if (f->next_ != NULL) return 0; + } + + if (f->width_ > 0 && f->height_ > 0 && + !CheckFrameBounds(f, !is_animation, + dmux->canvas_width_, dmux->canvas_height_)) { + return 0; + } + } + } + return 1; +} + +// ----------------------------------------------------------------------------- +// WebPDemuxer object + +static void InitDemux(WebPDemuxer* const dmux, const MemBuffer* const mem) { + dmux->state_ = WEBP_DEMUX_PARSING_HEADER; + dmux->loop_count_ = 1; + dmux->bgcolor_ = 0xFFFFFFFF; // White background by default. + dmux->canvas_width_ = -1; + dmux->canvas_height_ = -1; + dmux->frames_tail_ = &dmux->frames_; + dmux->chunks_tail_ = &dmux->chunks_; + dmux->mem_ = *mem; +} + +static ParseStatus CreateRawImageDemuxer(MemBuffer* const mem, + WebPDemuxer** demuxer) { + WebPBitstreamFeatures features; + const VP8StatusCode status = + WebPGetFeatures(mem->buf_, mem->buf_size_, &features); + *demuxer = NULL; + if (status != VP8_STATUS_OK) { + return (status == VP8_STATUS_NOT_ENOUGH_DATA) ? PARSE_NEED_MORE_DATA + : PARSE_ERROR; + } + + { + WebPDemuxer* const dmux = (WebPDemuxer*)WebPSafeCalloc(1ULL, sizeof(*dmux)); + Frame* const frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(*frame)); + if (dmux == NULL || frame == NULL) goto Error; + InitDemux(dmux, mem); + SetFrameInfo(0, mem->buf_size_, 1 /*frame_num*/, 1 /*complete*/, &features, + frame); + if (!AddFrame(dmux, frame)) goto Error; + dmux->state_ = WEBP_DEMUX_DONE; + dmux->canvas_width_ = frame->width_; + dmux->canvas_height_ = frame->height_; + dmux->feature_flags_ |= frame->has_alpha_ ? ALPHA_FLAG : 0; + dmux->num_frames_ = 1; + assert(IsValidSimpleFormat(dmux)); + *demuxer = dmux; + return PARSE_OK; + + Error: + WebPSafeFree(dmux); + WebPSafeFree(frame); + return PARSE_ERROR; + } +} + +WebPDemuxer* WebPDemuxInternal(const WebPData* data, int allow_partial, + WebPDemuxState* state, int version) { + const ChunkParser* parser; + int partial; + ParseStatus status = PARSE_ERROR; + MemBuffer mem; + WebPDemuxer* dmux; + + if (state != NULL) *state = WEBP_DEMUX_PARSE_ERROR; + + if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DEMUX_ABI_VERSION)) return NULL; + if (data == NULL || data->bytes == NULL || data->size == 0) return NULL; + + if (!InitMemBuffer(&mem, data->bytes, data->size)) return NULL; + status = ReadHeader(&mem); + if (status != PARSE_OK) { + // If parsing of the webp file header fails attempt to handle a raw + // VP8/VP8L frame. Note 'allow_partial' is ignored in this case. + if (status == PARSE_ERROR) { + status = CreateRawImageDemuxer(&mem, &dmux); + if (status == PARSE_OK) { + if (state != NULL) *state = WEBP_DEMUX_DONE; + return dmux; + } + } + if (state != NULL) { + *state = (status == PARSE_NEED_MORE_DATA) ? WEBP_DEMUX_PARSING_HEADER + : WEBP_DEMUX_PARSE_ERROR; + } + return NULL; + } + + partial = (mem.buf_size_ < mem.riff_end_); + if (!allow_partial && partial) return NULL; + + dmux = (WebPDemuxer*)WebPSafeCalloc(1ULL, sizeof(*dmux)); + if (dmux == NULL) return NULL; + InitDemux(dmux, &mem); + + status = PARSE_ERROR; + for (parser = kMasterChunks; parser->parse != NULL; ++parser) { + if (!memcmp(parser->id, GetBuffer(&dmux->mem_), TAG_SIZE)) { + status = parser->parse(dmux); + if (status == PARSE_OK) dmux->state_ = WEBP_DEMUX_DONE; + if (status == PARSE_NEED_MORE_DATA && !partial) status = PARSE_ERROR; + if (status != PARSE_ERROR && !parser->valid(dmux)) status = PARSE_ERROR; + if (status == PARSE_ERROR) dmux->state_ = WEBP_DEMUX_PARSE_ERROR; + break; + } + } + if (state != NULL) *state = dmux->state_; + + if (status == PARSE_ERROR) { + WebPDemuxDelete(dmux); + return NULL; + } + return dmux; +} + +void WebPDemuxDelete(WebPDemuxer* dmux) { + Chunk* c; + Frame* f; + if (dmux == NULL) return; + + for (f = dmux->frames_; f != NULL;) { + Frame* const cur_frame = f; + f = f->next_; + WebPSafeFree(cur_frame); + } + for (c = dmux->chunks_; c != NULL;) { + Chunk* const cur_chunk = c; + c = c->next_; + WebPSafeFree(cur_chunk); + } + WebPSafeFree(dmux); +} + +// ----------------------------------------------------------------------------- + +uint32_t WebPDemuxGetI(const WebPDemuxer* dmux, WebPFormatFeature feature) { + if (dmux == NULL) return 0; + + switch (feature) { + case WEBP_FF_FORMAT_FLAGS: return dmux->feature_flags_; + case WEBP_FF_CANVAS_WIDTH: return (uint32_t)dmux->canvas_width_; + case WEBP_FF_CANVAS_HEIGHT: return (uint32_t)dmux->canvas_height_; + case WEBP_FF_LOOP_COUNT: return (uint32_t)dmux->loop_count_; + case WEBP_FF_BACKGROUND_COLOR: return dmux->bgcolor_; + case WEBP_FF_FRAME_COUNT: return (uint32_t)dmux->num_frames_; + } + return 0; +} + +// ----------------------------------------------------------------------------- +// Frame iteration + +static const Frame* GetFrame(const WebPDemuxer* const dmux, int frame_num) { + const Frame* f; + for (f = dmux->frames_; f != NULL; f = f->next_) { + if (frame_num == f->frame_num_) break; + } + return f; +} + +static const uint8_t* GetFramePayload(const uint8_t* const mem_buf, + const Frame* const frame, + size_t* const data_size) { + *data_size = 0; + if (frame != NULL) { + const ChunkData* const image = frame->img_components_; + const ChunkData* const alpha = frame->img_components_ + 1; + size_t start_offset = image->offset_; + *data_size = image->size_; + + // if alpha exists it precedes image, update the size allowing for + // intervening chunks. + if (alpha->size_ > 0) { + const size_t inter_size = (image->offset_ > 0) + ? image->offset_ - (alpha->offset_ + alpha->size_) + : 0; + start_offset = alpha->offset_; + *data_size += alpha->size_ + inter_size; + } + return mem_buf + start_offset; + } + return NULL; +} + +// Create a whole 'frame' from VP8 (+ alpha) or lossless. +static int SynthesizeFrame(const WebPDemuxer* const dmux, + const Frame* const frame, + WebPIterator* const iter) { + const uint8_t* const mem_buf = dmux->mem_.buf_; + size_t payload_size = 0; + const uint8_t* const payload = GetFramePayload(mem_buf, frame, &payload_size); + if (payload == NULL) return 0; + assert(frame != NULL); + + iter->frame_num = frame->frame_num_; + iter->num_frames = dmux->num_frames_; + iter->x_offset = frame->x_offset_; + iter->y_offset = frame->y_offset_; + iter->width = frame->width_; + iter->height = frame->height_; + iter->has_alpha = frame->has_alpha_; + iter->duration = frame->duration_; + iter->dispose_method = frame->dispose_method_; + iter->blend_method = frame->blend_method_; + iter->complete = frame->complete_; + iter->fragment.bytes = payload; + iter->fragment.size = payload_size; + return 1; +} + +static int SetFrame(int frame_num, WebPIterator* const iter) { + const Frame* frame; + const WebPDemuxer* const dmux = (WebPDemuxer*)iter->private_; + if (dmux == NULL || frame_num < 0) return 0; + if (frame_num > dmux->num_frames_) return 0; + if (frame_num == 0) frame_num = dmux->num_frames_; + + frame = GetFrame(dmux, frame_num); + if (frame == NULL) return 0; + + return SynthesizeFrame(dmux, frame, iter); +} + +int WebPDemuxGetFrame(const WebPDemuxer* dmux, int frame, WebPIterator* iter) { + if (iter == NULL) return 0; + + memset(iter, 0, sizeof(*iter)); + iter->private_ = (void*)dmux; + return SetFrame(frame, iter); +} + +int WebPDemuxNextFrame(WebPIterator* iter) { + if (iter == NULL) return 0; + return SetFrame(iter->frame_num + 1, iter); +} + +int WebPDemuxPrevFrame(WebPIterator* iter) { + if (iter == NULL) return 0; + if (iter->frame_num <= 1) return 0; + return SetFrame(iter->frame_num - 1, iter); +} + +void WebPDemuxReleaseIterator(WebPIterator* iter) { + (void)iter; +} + +// ----------------------------------------------------------------------------- +// Chunk iteration + +static int ChunkCount(const WebPDemuxer* const dmux, const char fourcc[4]) { + const uint8_t* const mem_buf = dmux->mem_.buf_; + const Chunk* c; + int count = 0; + for (c = dmux->chunks_; c != NULL; c = c->next_) { + const uint8_t* const header = mem_buf + c->data_.offset_; + if (!memcmp(header, fourcc, TAG_SIZE)) ++count; + } + return count; +} + +static const Chunk* GetChunk(const WebPDemuxer* const dmux, + const char fourcc[4], int chunk_num) { + const uint8_t* const mem_buf = dmux->mem_.buf_; + const Chunk* c; + int count = 0; + for (c = dmux->chunks_; c != NULL; c = c->next_) { + const uint8_t* const header = mem_buf + c->data_.offset_; + if (!memcmp(header, fourcc, TAG_SIZE)) ++count; + if (count == chunk_num) break; + } + return c; +} + +static int SetChunk(const char fourcc[4], int chunk_num, + WebPChunkIterator* const iter) { + const WebPDemuxer* const dmux = (WebPDemuxer*)iter->private_; + int count; + + if (dmux == NULL || fourcc == NULL || chunk_num < 0) return 0; + count = ChunkCount(dmux, fourcc); + if (count == 0) return 0; + if (chunk_num == 0) chunk_num = count; + + if (chunk_num <= count) { + const uint8_t* const mem_buf = dmux->mem_.buf_; + const Chunk* const chunk = GetChunk(dmux, fourcc, chunk_num); + iter->chunk.bytes = mem_buf + chunk->data_.offset_ + CHUNK_HEADER_SIZE; + iter->chunk.size = chunk->data_.size_ - CHUNK_HEADER_SIZE; + iter->num_chunks = count; + iter->chunk_num = chunk_num; + return 1; + } + return 0; +} + +int WebPDemuxGetChunk(const WebPDemuxer* dmux, + const char fourcc[4], int chunk_num, + WebPChunkIterator* iter) { + if (iter == NULL) return 0; + + memset(iter, 0, sizeof(*iter)); + iter->private_ = (void*)dmux; + return SetChunk(fourcc, chunk_num, iter); +} + +int WebPDemuxNextChunk(WebPChunkIterator* iter) { + if (iter != NULL) { + const char* const fourcc = + (const char*)iter->chunk.bytes - CHUNK_HEADER_SIZE; + return SetChunk(fourcc, iter->chunk_num + 1, iter); + } + return 0; +} + +int WebPDemuxPrevChunk(WebPChunkIterator* iter) { + if (iter != NULL && iter->chunk_num > 1) { + const char* const fourcc = + (const char*)iter->chunk.bytes - CHUNK_HEADER_SIZE; + return SetChunk(fourcc, iter->chunk_num - 1, iter); + } + return 0; +} + +void WebPDemuxReleaseChunkIterator(WebPChunkIterator* iter) { + (void)iter; +} + diff --git a/third-party/webp/libwebp/src/demux/libwebpdemux.pc.in b/third-party/webp/libwebp/src/demux/libwebpdemux.pc.in new file mode 100644 index 0000000000..4da2e40adc --- /dev/null +++ b/third-party/webp/libwebp/src/demux/libwebpdemux.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libwebpdemux +Description: Library for parsing the WebP graphics format container +Version: @PACKAGE_VERSION@ +Requires.private: libwebp >= 0.2.0 +Cflags: -I${includedir} +Libs: -L${libdir} -l@webp_libname_prefix@webpdemux diff --git a/third-party/webp/libwebp/src/demux/libwebpdemux.rc b/third-party/webp/libwebp/src/demux/libwebpdemux.rc new file mode 100644 index 0000000000..b0c9413e6b --- /dev/null +++ b/third-party/webp/libwebp/src/demux/libwebpdemux.rc @@ -0,0 +1,41 @@ +#define APSTUDIO_READONLY_SYMBOLS +#include "winres.h" +#undef APSTUDIO_READONLY_SYMBOLS + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,3,2 + PRODUCTVERSION 1,0,3,2 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "Google, Inc." + VALUE "FileDescription", "libwebpdemux DLL" + VALUE "FileVersion", "1.3.2" + VALUE "InternalName", "libwebpdemux.dll" + VALUE "LegalCopyright", "Copyright (C) 2023" + VALUE "OriginalFilename", "libwebpdemux.dll" + VALUE "ProductName", "WebP Image Demuxer" + VALUE "ProductVersion", "1.3.2" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // English (United States) resources diff --git a/third-party/webp/libwebp/src/dsp/Makefile.am b/third-party/webp/libwebp/src/dsp/Makefile.am new file mode 100644 index 0000000000..7db4ef0f07 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/Makefile.am @@ -0,0 +1,187 @@ +AM_CPPFLAGS += -I$(top_builddir) -I$(top_srcdir) +noinst_LTLIBRARIES = +noinst_LTLIBRARIES += libwebpdsp.la +noinst_LTLIBRARIES += libwebpdsp_sse2.la +noinst_LTLIBRARIES += libwebpdspdecode_sse2.la +noinst_LTLIBRARIES += libwebpdsp_sse41.la +noinst_LTLIBRARIES += libwebpdspdecode_sse41.la +noinst_LTLIBRARIES += libwebpdsp_neon.la +noinst_LTLIBRARIES += libwebpdspdecode_neon.la +noinst_LTLIBRARIES += libwebpdsp_msa.la +noinst_LTLIBRARIES += libwebpdspdecode_msa.la +noinst_LTLIBRARIES += libwebpdsp_mips32.la +noinst_LTLIBRARIES += libwebpdspdecode_mips32.la +noinst_LTLIBRARIES += libwebpdsp_mips_dsp_r2.la +noinst_LTLIBRARIES += libwebpdspdecode_mips_dsp_r2.la + +if BUILD_LIBWEBPDECODER + noinst_LTLIBRARIES += libwebpdspdecode.la +endif + +common_HEADERS = ../webp/types.h +commondir = $(includedir)/webp + +COMMON_SOURCES = +COMMON_SOURCES += alpha_processing.c +COMMON_SOURCES += cpu.c +COMMON_SOURCES += cpu.h +COMMON_SOURCES += dec.c +COMMON_SOURCES += dec_clip_tables.c +COMMON_SOURCES += dsp.h +COMMON_SOURCES += filters.c +COMMON_SOURCES += lossless.c +COMMON_SOURCES += lossless.h +COMMON_SOURCES += lossless_common.h +COMMON_SOURCES += rescaler.c +COMMON_SOURCES += upsampling.c +COMMON_SOURCES += yuv.c +COMMON_SOURCES += yuv.h + +ENC_SOURCES = +ENC_SOURCES += cost.c +ENC_SOURCES += enc.c +ENC_SOURCES += lossless_enc.c +ENC_SOURCES += quant.h +ENC_SOURCES += ssim.c + +libwebpdspdecode_sse41_la_SOURCES = +libwebpdspdecode_sse41_la_SOURCES += alpha_processing_sse41.c +libwebpdspdecode_sse41_la_SOURCES += dec_sse41.c +libwebpdspdecode_sse41_la_SOURCES += lossless_sse41.c +libwebpdspdecode_sse41_la_SOURCES += upsampling_sse41.c +libwebpdspdecode_sse41_la_SOURCES += yuv_sse41.c +libwebpdspdecode_sse41_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS) +libwebpdspdecode_sse41_la_CFLAGS = $(AM_CFLAGS) $(SSE41_FLAGS) + +libwebpdspdecode_sse2_la_SOURCES = +libwebpdspdecode_sse2_la_SOURCES += alpha_processing_sse2.c +libwebpdspdecode_sse2_la_SOURCES += common_sse2.h +libwebpdspdecode_sse2_la_SOURCES += dec_sse2.c +libwebpdspdecode_sse2_la_SOURCES += filters_sse2.c +libwebpdspdecode_sse2_la_SOURCES += lossless_sse2.c +libwebpdspdecode_sse2_la_SOURCES += rescaler_sse2.c +libwebpdspdecode_sse2_la_SOURCES += upsampling_sse2.c +libwebpdspdecode_sse2_la_SOURCES += yuv_sse2.c +libwebpdspdecode_sse2_la_CPPFLAGS = $(libwebpdsp_sse2_la_CPPFLAGS) +libwebpdspdecode_sse2_la_CFLAGS = $(libwebpdsp_sse2_la_CFLAGS) + +libwebpdspdecode_neon_la_SOURCES = +libwebpdspdecode_neon_la_SOURCES += alpha_processing_neon.c +libwebpdspdecode_neon_la_SOURCES += dec_neon.c +libwebpdspdecode_neon_la_SOURCES += filters_neon.c +libwebpdspdecode_neon_la_SOURCES += lossless_neon.c +libwebpdspdecode_neon_la_SOURCES += neon.h +libwebpdspdecode_neon_la_SOURCES += rescaler_neon.c +libwebpdspdecode_neon_la_SOURCES += upsampling_neon.c +libwebpdspdecode_neon_la_SOURCES += yuv_neon.c +libwebpdspdecode_neon_la_CPPFLAGS = $(libwebpdsp_neon_la_CPPFLAGS) +libwebpdspdecode_neon_la_CFLAGS = $(libwebpdsp_neon_la_CFLAGS) + +libwebpdspdecode_msa_la_SOURCES = +libwebpdspdecode_msa_la_SOURCES += dec_msa.c +libwebpdspdecode_msa_la_SOURCES += filters_msa.c +libwebpdspdecode_msa_la_SOURCES += lossless_msa.c +libwebpdspdecode_msa_la_SOURCES += msa_macro.h +libwebpdspdecode_msa_la_SOURCES += rescaler_msa.c +libwebpdspdecode_msa_la_SOURCES += upsampling_msa.c +libwebpdspdecode_msa_la_CPPFLAGS = $(libwebpdsp_msa_la_CPPFLAGS) +libwebpdspdecode_msa_la_CFLAGS = $(libwebpdsp_msa_la_CFLAGS) + +libwebpdspdecode_mips32_la_SOURCES = +libwebpdspdecode_mips32_la_SOURCES += dec_mips32.c +libwebpdspdecode_mips32_la_SOURCES += mips_macro.h +libwebpdspdecode_mips32_la_SOURCES += rescaler_mips32.c +libwebpdspdecode_mips32_la_SOURCES += yuv_mips32.c +libwebpdspdecode_mips32_la_CPPFLAGS = $(libwebpdsp_mips32_la_CPPFLAGS) +libwebpdspdecode_mips32_la_CFLAGS = $(libwebpdsp_mips32_la_CFLAGS) + +libwebpdspdecode_mips_dsp_r2_la_SOURCES = +libwebpdspdecode_mips_dsp_r2_la_SOURCES += alpha_processing_mips_dsp_r2.c +libwebpdspdecode_mips_dsp_r2_la_SOURCES += dec_mips_dsp_r2.c +libwebpdspdecode_mips_dsp_r2_la_SOURCES += filters_mips_dsp_r2.c +libwebpdspdecode_mips_dsp_r2_la_SOURCES += lossless_mips_dsp_r2.c +libwebpdspdecode_mips_dsp_r2_la_SOURCES += mips_macro.h +libwebpdspdecode_mips_dsp_r2_la_SOURCES += rescaler_mips_dsp_r2.c +libwebpdspdecode_mips_dsp_r2_la_SOURCES += upsampling_mips_dsp_r2.c +libwebpdspdecode_mips_dsp_r2_la_SOURCES += yuv_mips_dsp_r2.c +libwebpdspdecode_mips_dsp_r2_la_CPPFLAGS = $(libwebpdsp_mips_dsp_r2_la_CPPFLAGS) +libwebpdspdecode_mips_dsp_r2_la_CFLAGS = $(libwebpdsp_mips_dsp_r2_la_CFLAGS) + +libwebpdsp_sse2_la_SOURCES = +libwebpdsp_sse2_la_SOURCES += cost_sse2.c +libwebpdsp_sse2_la_SOURCES += enc_sse2.c +libwebpdsp_sse2_la_SOURCES += lossless_enc_sse2.c +libwebpdsp_sse2_la_SOURCES += ssim_sse2.c +libwebpdsp_sse2_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS) +libwebpdsp_sse2_la_CFLAGS = $(AM_CFLAGS) $(SSE2_FLAGS) +libwebpdsp_sse2_la_LIBADD = libwebpdspdecode_sse2.la + +libwebpdsp_sse41_la_SOURCES = +libwebpdsp_sse41_la_SOURCES += enc_sse41.c +libwebpdsp_sse41_la_SOURCES += lossless_enc_sse41.c +libwebpdsp_sse41_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS) +libwebpdsp_sse41_la_CFLAGS = $(AM_CFLAGS) $(SSE41_FLAGS) +libwebpdsp_sse41_la_LIBADD = libwebpdspdecode_sse41.la + +libwebpdsp_neon_la_SOURCES = +libwebpdsp_neon_la_SOURCES += cost_neon.c +libwebpdsp_neon_la_SOURCES += enc_neon.c +libwebpdsp_neon_la_SOURCES += lossless_enc_neon.c +libwebpdsp_neon_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS) +libwebpdsp_neon_la_CFLAGS = $(AM_CFLAGS) $(NEON_FLAGS) +libwebpdsp_neon_la_LIBADD = libwebpdspdecode_neon.la + +libwebpdsp_msa_la_SOURCES = +libwebpdsp_msa_la_SOURCES += enc_msa.c +libwebpdsp_msa_la_SOURCES += lossless_enc_msa.c +libwebpdsp_msa_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS) +libwebpdsp_msa_la_CFLAGS = $(AM_CFLAGS) +libwebpdsp_msa_la_LIBADD = libwebpdspdecode_msa.la + +libwebpdsp_mips32_la_SOURCES = +libwebpdsp_mips32_la_SOURCES += cost_mips32.c +libwebpdsp_mips32_la_SOURCES += enc_mips32.c +libwebpdsp_mips32_la_SOURCES += lossless_enc_mips32.c +libwebpdsp_mips32_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS) +libwebpdsp_mips32_la_CFLAGS = $(AM_CFLAGS) +libwebpdsp_mips32_la_LIBADD = libwebpdspdecode_mips32.la + +libwebpdsp_mips_dsp_r2_la_SOURCES = +libwebpdsp_mips_dsp_r2_la_SOURCES += cost_mips_dsp_r2.c +libwebpdsp_mips_dsp_r2_la_SOURCES += enc_mips_dsp_r2.c +libwebpdsp_mips_dsp_r2_la_SOURCES += lossless_enc_mips_dsp_r2.c +libwebpdsp_mips_dsp_r2_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS) +libwebpdsp_mips_dsp_r2_la_CFLAGS = $(AM_CFLAGS) +libwebpdsp_mips_dsp_r2_la_LIBADD = libwebpdspdecode_mips_dsp_r2.la + +libwebpdsp_la_SOURCES = $(COMMON_SOURCES) $(ENC_SOURCES) + +noinst_HEADERS = +noinst_HEADERS += ../dec/vp8_dec.h +noinst_HEADERS += ../webp/decode.h + +libwebpdsp_la_CPPFLAGS = +libwebpdsp_la_CPPFLAGS += $(AM_CPPFLAGS) +libwebpdsp_la_CPPFLAGS += $(USE_SWAP_16BIT_CSP) +libwebpdsp_la_LDFLAGS = -lm +libwebpdsp_la_LIBADD = +libwebpdsp_la_LIBADD += libwebpdsp_sse2.la +libwebpdsp_la_LIBADD += libwebpdsp_sse41.la +libwebpdsp_la_LIBADD += libwebpdsp_neon.la +libwebpdsp_la_LIBADD += libwebpdsp_msa.la +libwebpdsp_la_LIBADD += libwebpdsp_mips32.la +libwebpdsp_la_LIBADD += libwebpdsp_mips_dsp_r2.la + +if BUILD_LIBWEBPDECODER + libwebpdspdecode_la_SOURCES = $(COMMON_SOURCES) + + libwebpdspdecode_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS) + libwebpdspdecode_la_LDFLAGS = $(libwebpdsp_la_LDFLAGS) + libwebpdspdecode_la_LIBADD = + libwebpdspdecode_la_LIBADD += libwebpdspdecode_sse2.la + libwebpdspdecode_la_LIBADD += libwebpdspdecode_sse41.la + libwebpdspdecode_la_LIBADD += libwebpdspdecode_neon.la + libwebpdspdecode_la_LIBADD += libwebpdspdecode_msa.la + libwebpdspdecode_la_LIBADD += libwebpdspdecode_mips32.la + libwebpdspdecode_la_LIBADD += libwebpdspdecode_mips_dsp_r2.la +endif diff --git a/third-party/webp/libwebp/src/dsp/alpha_processing.c b/third-party/webp/libwebp/src/dsp/alpha_processing.c new file mode 100644 index 0000000000..1d152f24da --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/alpha_processing.c @@ -0,0 +1,496 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Utilities for processing transparent channel. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include "src/dsp/dsp.h" + +// Tables can be faster on some platform but incur some extra binary size (~2k). +#if !defined(USE_TABLES_FOR_ALPHA_MULT) +#define USE_TABLES_FOR_ALPHA_MULT 0 // ALTERNATE_CODE +#endif + + +// ----------------------------------------------------------------------------- + +#define MFIX 24 // 24bit fixed-point arithmetic +#define HALF ((1u << MFIX) >> 1) +#define KINV_255 ((1u << MFIX) / 255u) + +static uint32_t Mult(uint8_t x, uint32_t mult) { + const uint32_t v = (x * mult + HALF) >> MFIX; + assert(v <= 255); // <- 24bit precision is enough to ensure that. + return v; +} + +#if (USE_TABLES_FOR_ALPHA_MULT == 1) + +static const uint32_t kMultTables[2][256] = { + { // (255u << MFIX) / alpha + 0x00000000, 0xff000000, 0x7f800000, 0x55000000, 0x3fc00000, 0x33000000, + 0x2a800000, 0x246db6db, 0x1fe00000, 0x1c555555, 0x19800000, 0x172e8ba2, + 0x15400000, 0x139d89d8, 0x1236db6d, 0x11000000, 0x0ff00000, 0x0f000000, + 0x0e2aaaaa, 0x0d6bca1a, 0x0cc00000, 0x0c249249, 0x0b9745d1, 0x0b1642c8, + 0x0aa00000, 0x0a333333, 0x09cec4ec, 0x0971c71c, 0x091b6db6, 0x08cb08d3, + 0x08800000, 0x0839ce73, 0x07f80000, 0x07ba2e8b, 0x07800000, 0x07492492, + 0x07155555, 0x06e45306, 0x06b5e50d, 0x0689d89d, 0x06600000, 0x063831f3, + 0x06124924, 0x05ee23b8, 0x05cba2e8, 0x05aaaaaa, 0x058b2164, 0x056cefa8, + 0x05500000, 0x05343eb1, 0x05199999, 0x05000000, 0x04e76276, 0x04cfb2b7, + 0x04b8e38e, 0x04a2e8ba, 0x048db6db, 0x0479435e, 0x04658469, 0x045270d0, + 0x04400000, 0x042e29f7, 0x041ce739, 0x040c30c3, 0x03fc0000, 0x03ec4ec4, + 0x03dd1745, 0x03ce540f, 0x03c00000, 0x03b21642, 0x03a49249, 0x03976fc6, + 0x038aaaaa, 0x037e3f1f, 0x03722983, 0x03666666, 0x035af286, 0x034fcace, + 0x0344ec4e, 0x033a5440, 0x03300000, 0x0325ed09, 0x031c18f9, 0x0312818a, + 0x03092492, 0x03000000, 0x02f711dc, 0x02ee5846, 0x02e5d174, 0x02dd7baf, + 0x02d55555, 0x02cd5cd5, 0x02c590b2, 0x02bdef7b, 0x02b677d4, 0x02af286b, + 0x02a80000, 0x02a0fd5c, 0x029a1f58, 0x029364d9, 0x028ccccc, 0x0286562d, + 0x02800000, 0x0279c952, 0x0273b13b, 0x026db6db, 0x0267d95b, 0x026217ec, + 0x025c71c7, 0x0256e62a, 0x0251745d, 0x024c1bac, 0x0246db6d, 0x0241b2f9, + 0x023ca1af, 0x0237a6f4, 0x0232c234, 0x022df2df, 0x02293868, 0x02249249, + 0x02200000, 0x021b810e, 0x021714fb, 0x0212bb51, 0x020e739c, 0x020a3d70, + 0x02061861, 0x02020408, 0x01fe0000, 0x01fa0be8, 0x01f62762, 0x01f25213, + 0x01ee8ba2, 0x01ead3ba, 0x01e72a07, 0x01e38e38, 0x01e00000, 0x01dc7f10, + 0x01d90b21, 0x01d5a3e9, 0x01d24924, 0x01cefa8d, 0x01cbb7e3, 0x01c880e5, + 0x01c55555, 0x01c234f7, 0x01bf1f8f, 0x01bc14e5, 0x01b914c1, 0x01b61eed, + 0x01b33333, 0x01b05160, 0x01ad7943, 0x01aaaaaa, 0x01a7e567, 0x01a5294a, + 0x01a27627, 0x019fcbd2, 0x019d2a20, 0x019a90e7, 0x01980000, 0x01957741, + 0x0192f684, 0x01907da4, 0x018e0c7c, 0x018ba2e8, 0x018940c5, 0x0186e5f0, + 0x01849249, 0x018245ae, 0x01800000, 0x017dc11f, 0x017b88ee, 0x0179574e, + 0x01772c23, 0x01750750, 0x0172e8ba, 0x0170d045, 0x016ebdd7, 0x016cb157, + 0x016aaaaa, 0x0168a9b9, 0x0166ae6a, 0x0164b8a7, 0x0162c859, 0x0160dd67, + 0x015ef7bd, 0x015d1745, 0x015b3bea, 0x01596596, 0x01579435, 0x0155c7b4, + 0x01540000, 0x01523d03, 0x01507eae, 0x014ec4ec, 0x014d0fac, 0x014b5edc, + 0x0149b26c, 0x01480a4a, 0x01466666, 0x0144c6af, 0x01432b16, 0x0141938b, + 0x01400000, 0x013e7063, 0x013ce4a9, 0x013b5cc0, 0x0139d89d, 0x01385830, + 0x0136db6d, 0x01356246, 0x0133ecad, 0x01327a97, 0x01310bf6, 0x012fa0be, + 0x012e38e3, 0x012cd459, 0x012b7315, 0x012a150a, 0x0128ba2e, 0x01276276, + 0x01260dd6, 0x0124bc44, 0x01236db6, 0x01222222, 0x0120d97c, 0x011f93bc, + 0x011e50d7, 0x011d10c4, 0x011bd37a, 0x011a98ef, 0x0119611a, 0x01182bf2, + 0x0116f96f, 0x0115c988, 0x01149c34, 0x0113716a, 0x01124924, 0x01112358, + 0x01100000, 0x010edf12, 0x010dc087, 0x010ca458, 0x010b8a7d, 0x010a72f0, + 0x01095da8, 0x01084a9f, 0x010739ce, 0x01062b2e, 0x01051eb8, 0x01041465, + 0x01030c30, 0x01020612, 0x01010204, 0x01000000 }, + { // alpha * KINV_255 + 0x00000000, 0x00010101, 0x00020202, 0x00030303, 0x00040404, 0x00050505, + 0x00060606, 0x00070707, 0x00080808, 0x00090909, 0x000a0a0a, 0x000b0b0b, + 0x000c0c0c, 0x000d0d0d, 0x000e0e0e, 0x000f0f0f, 0x00101010, 0x00111111, + 0x00121212, 0x00131313, 0x00141414, 0x00151515, 0x00161616, 0x00171717, + 0x00181818, 0x00191919, 0x001a1a1a, 0x001b1b1b, 0x001c1c1c, 0x001d1d1d, + 0x001e1e1e, 0x001f1f1f, 0x00202020, 0x00212121, 0x00222222, 0x00232323, + 0x00242424, 0x00252525, 0x00262626, 0x00272727, 0x00282828, 0x00292929, + 0x002a2a2a, 0x002b2b2b, 0x002c2c2c, 0x002d2d2d, 0x002e2e2e, 0x002f2f2f, + 0x00303030, 0x00313131, 0x00323232, 0x00333333, 0x00343434, 0x00353535, + 0x00363636, 0x00373737, 0x00383838, 0x00393939, 0x003a3a3a, 0x003b3b3b, + 0x003c3c3c, 0x003d3d3d, 0x003e3e3e, 0x003f3f3f, 0x00404040, 0x00414141, + 0x00424242, 0x00434343, 0x00444444, 0x00454545, 0x00464646, 0x00474747, + 0x00484848, 0x00494949, 0x004a4a4a, 0x004b4b4b, 0x004c4c4c, 0x004d4d4d, + 0x004e4e4e, 0x004f4f4f, 0x00505050, 0x00515151, 0x00525252, 0x00535353, + 0x00545454, 0x00555555, 0x00565656, 0x00575757, 0x00585858, 0x00595959, + 0x005a5a5a, 0x005b5b5b, 0x005c5c5c, 0x005d5d5d, 0x005e5e5e, 0x005f5f5f, + 0x00606060, 0x00616161, 0x00626262, 0x00636363, 0x00646464, 0x00656565, + 0x00666666, 0x00676767, 0x00686868, 0x00696969, 0x006a6a6a, 0x006b6b6b, + 0x006c6c6c, 0x006d6d6d, 0x006e6e6e, 0x006f6f6f, 0x00707070, 0x00717171, + 0x00727272, 0x00737373, 0x00747474, 0x00757575, 0x00767676, 0x00777777, + 0x00787878, 0x00797979, 0x007a7a7a, 0x007b7b7b, 0x007c7c7c, 0x007d7d7d, + 0x007e7e7e, 0x007f7f7f, 0x00808080, 0x00818181, 0x00828282, 0x00838383, + 0x00848484, 0x00858585, 0x00868686, 0x00878787, 0x00888888, 0x00898989, + 0x008a8a8a, 0x008b8b8b, 0x008c8c8c, 0x008d8d8d, 0x008e8e8e, 0x008f8f8f, + 0x00909090, 0x00919191, 0x00929292, 0x00939393, 0x00949494, 0x00959595, + 0x00969696, 0x00979797, 0x00989898, 0x00999999, 0x009a9a9a, 0x009b9b9b, + 0x009c9c9c, 0x009d9d9d, 0x009e9e9e, 0x009f9f9f, 0x00a0a0a0, 0x00a1a1a1, + 0x00a2a2a2, 0x00a3a3a3, 0x00a4a4a4, 0x00a5a5a5, 0x00a6a6a6, 0x00a7a7a7, + 0x00a8a8a8, 0x00a9a9a9, 0x00aaaaaa, 0x00ababab, 0x00acacac, 0x00adadad, + 0x00aeaeae, 0x00afafaf, 0x00b0b0b0, 0x00b1b1b1, 0x00b2b2b2, 0x00b3b3b3, + 0x00b4b4b4, 0x00b5b5b5, 0x00b6b6b6, 0x00b7b7b7, 0x00b8b8b8, 0x00b9b9b9, + 0x00bababa, 0x00bbbbbb, 0x00bcbcbc, 0x00bdbdbd, 0x00bebebe, 0x00bfbfbf, + 0x00c0c0c0, 0x00c1c1c1, 0x00c2c2c2, 0x00c3c3c3, 0x00c4c4c4, 0x00c5c5c5, + 0x00c6c6c6, 0x00c7c7c7, 0x00c8c8c8, 0x00c9c9c9, 0x00cacaca, 0x00cbcbcb, + 0x00cccccc, 0x00cdcdcd, 0x00cecece, 0x00cfcfcf, 0x00d0d0d0, 0x00d1d1d1, + 0x00d2d2d2, 0x00d3d3d3, 0x00d4d4d4, 0x00d5d5d5, 0x00d6d6d6, 0x00d7d7d7, + 0x00d8d8d8, 0x00d9d9d9, 0x00dadada, 0x00dbdbdb, 0x00dcdcdc, 0x00dddddd, + 0x00dedede, 0x00dfdfdf, 0x00e0e0e0, 0x00e1e1e1, 0x00e2e2e2, 0x00e3e3e3, + 0x00e4e4e4, 0x00e5e5e5, 0x00e6e6e6, 0x00e7e7e7, 0x00e8e8e8, 0x00e9e9e9, + 0x00eaeaea, 0x00ebebeb, 0x00ececec, 0x00ededed, 0x00eeeeee, 0x00efefef, + 0x00f0f0f0, 0x00f1f1f1, 0x00f2f2f2, 0x00f3f3f3, 0x00f4f4f4, 0x00f5f5f5, + 0x00f6f6f6, 0x00f7f7f7, 0x00f8f8f8, 0x00f9f9f9, 0x00fafafa, 0x00fbfbfb, + 0x00fcfcfc, 0x00fdfdfd, 0x00fefefe, 0x00ffffff } +}; + +static WEBP_INLINE uint32_t GetScale(uint32_t a, int inverse) { + return kMultTables[!inverse][a]; +} + +#else + +static WEBP_INLINE uint32_t GetScale(uint32_t a, int inverse) { + return inverse ? (255u << MFIX) / a : a * KINV_255; +} + +#endif // USE_TABLES_FOR_ALPHA_MULT + +void WebPMultARGBRow_C(uint32_t* const ptr, int width, int inverse) { + int x; + for (x = 0; x < width; ++x) { + const uint32_t argb = ptr[x]; + if (argb < 0xff000000u) { // alpha < 255 + if (argb <= 0x00ffffffu) { // alpha == 0 + ptr[x] = 0; + } else { + const uint32_t alpha = (argb >> 24) & 0xff; + const uint32_t scale = GetScale(alpha, inverse); + uint32_t out = argb & 0xff000000u; + out |= Mult(argb >> 0, scale) << 0; + out |= Mult(argb >> 8, scale) << 8; + out |= Mult(argb >> 16, scale) << 16; + ptr[x] = out; + } + } + } +} + +void WebPMultRow_C(uint8_t* WEBP_RESTRICT const ptr, + const uint8_t* WEBP_RESTRICT const alpha, + int width, int inverse) { + int x; + for (x = 0; x < width; ++x) { + const uint32_t a = alpha[x]; + if (a != 255) { + if (a == 0) { + ptr[x] = 0; + } else { + const uint32_t scale = GetScale(a, inverse); + ptr[x] = Mult(ptr[x], scale); + } + } + } +} + +#undef KINV_255 +#undef HALF +#undef MFIX + +void (*WebPMultARGBRow)(uint32_t* const ptr, int width, int inverse); +void (*WebPMultRow)(uint8_t* WEBP_RESTRICT const ptr, + const uint8_t* WEBP_RESTRICT const alpha, + int width, int inverse); + +//------------------------------------------------------------------------------ +// Generic per-plane calls + +void WebPMultARGBRows(uint8_t* ptr, int stride, int width, int num_rows, + int inverse) { + int n; + for (n = 0; n < num_rows; ++n) { + WebPMultARGBRow((uint32_t*)ptr, width, inverse); + ptr += stride; + } +} + +void WebPMultRows(uint8_t* WEBP_RESTRICT ptr, int stride, + const uint8_t* WEBP_RESTRICT alpha, int alpha_stride, + int width, int num_rows, int inverse) { + int n; + for (n = 0; n < num_rows; ++n) { + WebPMultRow(ptr, alpha, width, inverse); + ptr += stride; + alpha += alpha_stride; + } +} + +//------------------------------------------------------------------------------ +// Premultiplied modes + +// non dithered-modes + +// (x * a * 32897) >> 23 is bit-wise equivalent to (int)(x * a / 255.) +// for all 8bit x or a. For bit-wise equivalence to (int)(x * a / 255. + .5), +// one can use instead: (x * a * 65793 + (1 << 23)) >> 24 +#if 1 // (int)(x * a / 255.) +#define MULTIPLIER(a) ((a) * 32897U) +#define PREMULTIPLY(x, m) (((x) * (m)) >> 23) +#else // (int)(x * a / 255. + .5) +#define MULTIPLIER(a) ((a) * 65793U) +#define PREMULTIPLY(x, m) (((x) * (m) + (1U << 23)) >> 24) +#endif + +#if !WEBP_NEON_OMIT_C_CODE +static void ApplyAlphaMultiply_C(uint8_t* rgba, int alpha_first, + int w, int h, int stride) { + while (h-- > 0) { + uint8_t* const rgb = rgba + (alpha_first ? 1 : 0); + const uint8_t* const alpha = rgba + (alpha_first ? 0 : 3); + int i; + for (i = 0; i < w; ++i) { + const uint32_t a = alpha[4 * i]; + if (a != 0xff) { + const uint32_t mult = MULTIPLIER(a); + rgb[4 * i + 0] = PREMULTIPLY(rgb[4 * i + 0], mult); + rgb[4 * i + 1] = PREMULTIPLY(rgb[4 * i + 1], mult); + rgb[4 * i + 2] = PREMULTIPLY(rgb[4 * i + 2], mult); + } + } + rgba += stride; + } +} +#endif // !WEBP_NEON_OMIT_C_CODE +#undef MULTIPLIER +#undef PREMULTIPLY + +// rgbA4444 + +#define MULTIPLIER(a) ((a) * 0x1111) // 0x1111 ~= (1 << 16) / 15 + +static WEBP_INLINE uint8_t dither_hi(uint8_t x) { + return (x & 0xf0) | (x >> 4); +} + +static WEBP_INLINE uint8_t dither_lo(uint8_t x) { + return (x & 0x0f) | (x << 4); +} + +static WEBP_INLINE uint8_t multiply(uint8_t x, uint32_t m) { + return (x * m) >> 16; +} + +static WEBP_INLINE void ApplyAlphaMultiply4444_C(uint8_t* rgba4444, + int w, int h, int stride, + int rg_byte_pos /* 0 or 1 */) { + while (h-- > 0) { + int i; + for (i = 0; i < w; ++i) { + const uint32_t rg = rgba4444[2 * i + rg_byte_pos]; + const uint32_t ba = rgba4444[2 * i + (rg_byte_pos ^ 1)]; + const uint8_t a = ba & 0x0f; + const uint32_t mult = MULTIPLIER(a); + const uint8_t r = multiply(dither_hi(rg), mult); + const uint8_t g = multiply(dither_lo(rg), mult); + const uint8_t b = multiply(dither_hi(ba), mult); + rgba4444[2 * i + rg_byte_pos] = (r & 0xf0) | ((g >> 4) & 0x0f); + rgba4444[2 * i + (rg_byte_pos ^ 1)] = (b & 0xf0) | a; + } + rgba4444 += stride; + } +} +#undef MULTIPLIER + +static void ApplyAlphaMultiply_16b_C(uint8_t* rgba4444, + int w, int h, int stride) { +#if (WEBP_SWAP_16BIT_CSP == 1) + ApplyAlphaMultiply4444_C(rgba4444, w, h, stride, 1); +#else + ApplyAlphaMultiply4444_C(rgba4444, w, h, stride, 0); +#endif +} + +#if !WEBP_NEON_OMIT_C_CODE +static int DispatchAlpha_C(const uint8_t* WEBP_RESTRICT alpha, int alpha_stride, + int width, int height, + uint8_t* WEBP_RESTRICT dst, int dst_stride) { + uint32_t alpha_mask = 0xff; + int i, j; + + for (j = 0; j < height; ++j) { + for (i = 0; i < width; ++i) { + const uint32_t alpha_value = alpha[i]; + dst[4 * i] = alpha_value; + alpha_mask &= alpha_value; + } + alpha += alpha_stride; + dst += dst_stride; + } + + return (alpha_mask != 0xff); +} + +static void DispatchAlphaToGreen_C(const uint8_t* WEBP_RESTRICT alpha, + int alpha_stride, int width, int height, + uint32_t* WEBP_RESTRICT dst, + int dst_stride) { + int i, j; + for (j = 0; j < height; ++j) { + for (i = 0; i < width; ++i) { + dst[i] = alpha[i] << 8; // leave A/R/B channels zero'd. + } + alpha += alpha_stride; + dst += dst_stride; + } +} + +static int ExtractAlpha_C(const uint8_t* WEBP_RESTRICT argb, int argb_stride, + int width, int height, + uint8_t* WEBP_RESTRICT alpha, int alpha_stride) { + uint8_t alpha_mask = 0xff; + int i, j; + + for (j = 0; j < height; ++j) { + for (i = 0; i < width; ++i) { + const uint8_t alpha_value = argb[4 * i]; + alpha[i] = alpha_value; + alpha_mask &= alpha_value; + } + argb += argb_stride; + alpha += alpha_stride; + } + return (alpha_mask == 0xff); +} + +static void ExtractGreen_C(const uint32_t* WEBP_RESTRICT argb, + uint8_t* WEBP_RESTRICT alpha, int size) { + int i; + for (i = 0; i < size; ++i) alpha[i] = argb[i] >> 8; +} +#endif // !WEBP_NEON_OMIT_C_CODE + +//------------------------------------------------------------------------------ + +static int HasAlpha8b_C(const uint8_t* src, int length) { + while (length-- > 0) if (*src++ != 0xff) return 1; + return 0; +} + +static int HasAlpha32b_C(const uint8_t* src, int length) { + int x; + for (x = 0; length-- > 0; x += 4) if (src[x] != 0xff) return 1; + return 0; +} + +static void AlphaReplace_C(uint32_t* src, int length, uint32_t color) { + int x; + for (x = 0; x < length; ++x) if ((src[x] >> 24) == 0) src[x] = color; +} + +//------------------------------------------------------------------------------ +// Simple channel manipulations. + +static WEBP_INLINE uint32_t MakeARGB32(int a, int r, int g, int b) { + return (((uint32_t)a << 24) | (r << 16) | (g << 8) | b); +} + +#ifdef WORDS_BIGENDIAN +static void PackARGB_C(const uint8_t* WEBP_RESTRICT a, + const uint8_t* WEBP_RESTRICT r, + const uint8_t* WEBP_RESTRICT g, + const uint8_t* WEBP_RESTRICT b, + int len, uint32_t* WEBP_RESTRICT out) { + int i; + for (i = 0; i < len; ++i) { + out[i] = MakeARGB32(a[4 * i], r[4 * i], g[4 * i], b[4 * i]); + } +} +#endif + +static void PackRGB_C(const uint8_t* WEBP_RESTRICT r, + const uint8_t* WEBP_RESTRICT g, + const uint8_t* WEBP_RESTRICT b, + int len, int step, uint32_t* WEBP_RESTRICT out) { + int i, offset = 0; + for (i = 0; i < len; ++i) { + out[i] = MakeARGB32(0xff, r[offset], g[offset], b[offset]); + offset += step; + } +} + +void (*WebPApplyAlphaMultiply)(uint8_t*, int, int, int, int); +void (*WebPApplyAlphaMultiply4444)(uint8_t*, int, int, int); +int (*WebPDispatchAlpha)(const uint8_t* WEBP_RESTRICT, int, int, int, + uint8_t* WEBP_RESTRICT, int); +void (*WebPDispatchAlphaToGreen)(const uint8_t* WEBP_RESTRICT, int, int, int, + uint32_t* WEBP_RESTRICT, int); +int (*WebPExtractAlpha)(const uint8_t* WEBP_RESTRICT, int, int, int, + uint8_t* WEBP_RESTRICT, int); +void (*WebPExtractGreen)(const uint32_t* WEBP_RESTRICT argb, + uint8_t* WEBP_RESTRICT alpha, int size); +#ifdef WORDS_BIGENDIAN +void (*WebPPackARGB)(const uint8_t* a, const uint8_t* r, const uint8_t* g, + const uint8_t* b, int, uint32_t*); +#endif +void (*WebPPackRGB)(const uint8_t* WEBP_RESTRICT r, + const uint8_t* WEBP_RESTRICT g, + const uint8_t* WEBP_RESTRICT b, + int len, int step, uint32_t* WEBP_RESTRICT out); + +int (*WebPHasAlpha8b)(const uint8_t* src, int length); +int (*WebPHasAlpha32b)(const uint8_t* src, int length); +void (*WebPAlphaReplace)(uint32_t* src, int length, uint32_t color); + +//------------------------------------------------------------------------------ +// Init function + +extern VP8CPUInfo VP8GetCPUInfo; +extern void WebPInitAlphaProcessingMIPSdspR2(void); +extern void WebPInitAlphaProcessingSSE2(void); +extern void WebPInitAlphaProcessingSSE41(void); +extern void WebPInitAlphaProcessingNEON(void); + +WEBP_DSP_INIT_FUNC(WebPInitAlphaProcessing) { + WebPMultARGBRow = WebPMultARGBRow_C; + WebPMultRow = WebPMultRow_C; + WebPApplyAlphaMultiply4444 = ApplyAlphaMultiply_16b_C; + +#ifdef WORDS_BIGENDIAN + WebPPackARGB = PackARGB_C; +#endif + WebPPackRGB = PackRGB_C; +#if !WEBP_NEON_OMIT_C_CODE + WebPApplyAlphaMultiply = ApplyAlphaMultiply_C; + WebPDispatchAlpha = DispatchAlpha_C; + WebPDispatchAlphaToGreen = DispatchAlphaToGreen_C; + WebPExtractAlpha = ExtractAlpha_C; + WebPExtractGreen = ExtractGreen_C; +#endif + + WebPHasAlpha8b = HasAlpha8b_C; + WebPHasAlpha32b = HasAlpha32b_C; + WebPAlphaReplace = AlphaReplace_C; + + // If defined, use CPUInfo() to overwrite some pointers with faster versions. + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_HAVE_SSE2) + if (VP8GetCPUInfo(kSSE2)) { + WebPInitAlphaProcessingSSE2(); +#if defined(WEBP_HAVE_SSE41) + if (VP8GetCPUInfo(kSSE4_1)) { + WebPInitAlphaProcessingSSE41(); + } +#endif + } +#endif +#if defined(WEBP_USE_MIPS_DSP_R2) + if (VP8GetCPUInfo(kMIPSdspR2)) { + WebPInitAlphaProcessingMIPSdspR2(); + } +#endif + } + +#if defined(WEBP_HAVE_NEON) + if (WEBP_NEON_OMIT_C_CODE || + (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) { + WebPInitAlphaProcessingNEON(); + } +#endif + + assert(WebPMultARGBRow != NULL); + assert(WebPMultRow != NULL); + assert(WebPApplyAlphaMultiply != NULL); + assert(WebPApplyAlphaMultiply4444 != NULL); + assert(WebPDispatchAlpha != NULL); + assert(WebPDispatchAlphaToGreen != NULL); + assert(WebPExtractAlpha != NULL); + assert(WebPExtractGreen != NULL); +#ifdef WORDS_BIGENDIAN + assert(WebPPackARGB != NULL); +#endif + assert(WebPPackRGB != NULL); + assert(WebPHasAlpha8b != NULL); + assert(WebPHasAlpha32b != NULL); + assert(WebPAlphaReplace != NULL); +} diff --git a/third-party/webp/libwebp/src/dsp/alpha_processing_mips_dsp_r2.c b/third-party/webp/libwebp/src/dsp/alpha_processing_mips_dsp_r2.c new file mode 100644 index 0000000000..0090e87cd1 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/alpha_processing_mips_dsp_r2.c @@ -0,0 +1,228 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Utilities for processing transparent channel. +// +// Author(s): Branimir Vasic (branimir.vasic@imgtec.com) +// Djordje Pesut (djordje.pesut@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MIPS_DSP_R2) + +static int DispatchAlpha_MIPSdspR2(const uint8_t* alpha, int alpha_stride, + int width, int height, + uint8_t* dst, int dst_stride) { + uint32_t alpha_mask = 0xffffffff; + int i, j, temp0; + + for (j = 0; j < height; ++j) { + uint8_t* pdst = dst; + const uint8_t* palpha = alpha; + for (i = 0; i < (width >> 2); ++i) { + int temp1, temp2, temp3; + + __asm__ volatile ( + "ulw %[temp0], 0(%[palpha]) \n\t" + "addiu %[palpha], %[palpha], 4 \n\t" + "addiu %[pdst], %[pdst], 16 \n\t" + "srl %[temp1], %[temp0], 8 \n\t" + "srl %[temp2], %[temp0], 16 \n\t" + "srl %[temp3], %[temp0], 24 \n\t" + "and %[alpha_mask], %[alpha_mask], %[temp0] \n\t" + "sb %[temp0], -16(%[pdst]) \n\t" + "sb %[temp1], -12(%[pdst]) \n\t" + "sb %[temp2], -8(%[pdst]) \n\t" + "sb %[temp3], -4(%[pdst]) \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [palpha]"+r"(palpha), [pdst]"+r"(pdst), + [alpha_mask]"+r"(alpha_mask) + : + : "memory" + ); + } + + for (i = 0; i < (width & 3); ++i) { + __asm__ volatile ( + "lbu %[temp0], 0(%[palpha]) \n\t" + "addiu %[palpha], %[palpha], 1 \n\t" + "sb %[temp0], 0(%[pdst]) \n\t" + "and %[alpha_mask], %[alpha_mask], %[temp0] \n\t" + "addiu %[pdst], %[pdst], 4 \n\t" + : [temp0]"=&r"(temp0), [palpha]"+r"(palpha), [pdst]"+r"(pdst), + [alpha_mask]"+r"(alpha_mask) + : + : "memory" + ); + } + alpha += alpha_stride; + dst += dst_stride; + } + + __asm__ volatile ( + "ext %[temp0], %[alpha_mask], 0, 16 \n\t" + "srl %[alpha_mask], %[alpha_mask], 16 \n\t" + "and %[alpha_mask], %[alpha_mask], %[temp0] \n\t" + "ext %[temp0], %[alpha_mask], 0, 8 \n\t" + "srl %[alpha_mask], %[alpha_mask], 8 \n\t" + "and %[alpha_mask], %[alpha_mask], %[temp0] \n\t" + : [temp0]"=&r"(temp0), [alpha_mask]"+r"(alpha_mask) + : + ); + + return (alpha_mask != 0xff); +} + +static void MultARGBRow_MIPSdspR2(uint32_t* const ptr, int width, + int inverse) { + int x; + const uint32_t c_00ffffff = 0x00ffffffu; + const uint32_t c_ff000000 = 0xff000000u; + const uint32_t c_8000000 = 0x00800000u; + const uint32_t c_8000080 = 0x00800080u; + for (x = 0; x < width; ++x) { + const uint32_t argb = ptr[x]; + if (argb < 0xff000000u) { // alpha < 255 + if (argb <= 0x00ffffffu) { // alpha == 0 + ptr[x] = 0; + } else { + int temp0, temp1, temp2, temp3, alpha; + __asm__ volatile ( + "srl %[alpha], %[argb], 24 \n\t" + "replv.qb %[temp0], %[alpha] \n\t" + "and %[temp0], %[temp0], %[c_00ffffff] \n\t" + "beqz %[inverse], 0f \n\t" + "divu $zero, %[c_ff000000], %[alpha] \n\t" + "mflo %[temp0] \n\t" + "0: \n\t" + "andi %[temp1], %[argb], 0xff \n\t" + "ext %[temp2], %[argb], 8, 8 \n\t" + "ext %[temp3], %[argb], 16, 8 \n\t" + "mul %[temp1], %[temp1], %[temp0] \n\t" + "mul %[temp2], %[temp2], %[temp0] \n\t" + "mul %[temp3], %[temp3], %[temp0] \n\t" + "precrq.ph.w %[temp1], %[temp2], %[temp1] \n\t" + "addu %[temp3], %[temp3], %[c_8000000] \n\t" + "addu %[temp1], %[temp1], %[c_8000080] \n\t" + "precrq.ph.w %[temp3], %[argb], %[temp3] \n\t" + "precrq.qb.ph %[temp1], %[temp3], %[temp1] \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [alpha]"=&r"(alpha) + : [inverse]"r"(inverse), [c_00ffffff]"r"(c_00ffffff), + [c_8000000]"r"(c_8000000), [c_8000080]"r"(c_8000080), + [c_ff000000]"r"(c_ff000000), [argb]"r"(argb) + : "memory", "hi", "lo" + ); + ptr[x] = temp1; + } + } + } +} + +#ifdef WORDS_BIGENDIAN +static void PackARGB_MIPSdspR2(const uint8_t* a, const uint8_t* r, + const uint8_t* g, const uint8_t* b, int len, + uint32_t* out) { + int temp0, temp1, temp2, temp3, offset; + const int rest = len & 1; + const uint32_t* const loop_end = out + len - rest; + const int step = 4; + __asm__ volatile ( + "xor %[offset], %[offset], %[offset] \n\t" + "beq %[loop_end], %[out], 0f \n\t" + "2: \n\t" + "lbux %[temp0], %[offset](%[a]) \n\t" + "lbux %[temp1], %[offset](%[r]) \n\t" + "lbux %[temp2], %[offset](%[g]) \n\t" + "lbux %[temp3], %[offset](%[b]) \n\t" + "ins %[temp1], %[temp0], 16, 16 \n\t" + "ins %[temp3], %[temp2], 16, 16 \n\t" + "addiu %[out], %[out], 4 \n\t" + "precr.qb.ph %[temp0], %[temp1], %[temp3] \n\t" + "sw %[temp0], -4(%[out]) \n\t" + "addu %[offset], %[offset], %[step] \n\t" + "bne %[loop_end], %[out], 2b \n\t" + "0: \n\t" + "beq %[rest], $zero, 1f \n\t" + "lbux %[temp0], %[offset](%[a]) \n\t" + "lbux %[temp1], %[offset](%[r]) \n\t" + "lbux %[temp2], %[offset](%[g]) \n\t" + "lbux %[temp3], %[offset](%[b]) \n\t" + "ins %[temp1], %[temp0], 16, 16 \n\t" + "ins %[temp3], %[temp2], 16, 16 \n\t" + "precr.qb.ph %[temp0], %[temp1], %[temp3] \n\t" + "sw %[temp0], 0(%[out]) \n\t" + "1: \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [offset]"=&r"(offset), [out]"+&r"(out) + : [a]"r"(a), [r]"r"(r), [g]"r"(g), [b]"r"(b), [step]"r"(step), + [loop_end]"r"(loop_end), [rest]"r"(rest) + : "memory" + ); +} +#endif // WORDS_BIGENDIAN + +static void PackRGB_MIPSdspR2(const uint8_t* r, const uint8_t* g, + const uint8_t* b, int len, int step, + uint32_t* out) { + int temp0, temp1, temp2, offset; + const int rest = len & 1; + const int a = 0xff; + const uint32_t* const loop_end = out + len - rest; + __asm__ volatile ( + "xor %[offset], %[offset], %[offset] \n\t" + "beq %[loop_end], %[out], 0f \n\t" + "2: \n\t" + "lbux %[temp0], %[offset](%[r]) \n\t" + "lbux %[temp1], %[offset](%[g]) \n\t" + "lbux %[temp2], %[offset](%[b]) \n\t" + "ins %[temp0], %[a], 16, 16 \n\t" + "ins %[temp2], %[temp1], 16, 16 \n\t" + "addiu %[out], %[out], 4 \n\t" + "precr.qb.ph %[temp0], %[temp0], %[temp2] \n\t" + "sw %[temp0], -4(%[out]) \n\t" + "addu %[offset], %[offset], %[step] \n\t" + "bne %[loop_end], %[out], 2b \n\t" + "0: \n\t" + "beq %[rest], $zero, 1f \n\t" + "lbux %[temp0], %[offset](%[r]) \n\t" + "lbux %[temp1], %[offset](%[g]) \n\t" + "lbux %[temp2], %[offset](%[b]) \n\t" + "ins %[temp0], %[a], 16, 16 \n\t" + "ins %[temp2], %[temp1], 16, 16 \n\t" + "precr.qb.ph %[temp0], %[temp0], %[temp2] \n\t" + "sw %[temp0], 0(%[out]) \n\t" + "1: \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [offset]"=&r"(offset), [out]"+&r"(out) + : [a]"r"(a), [r]"r"(r), [g]"r"(g), [b]"r"(b), [step]"r"(step), + [loop_end]"r"(loop_end), [rest]"r"(rest) + : "memory" + ); +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void WebPInitAlphaProcessingMIPSdspR2(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessingMIPSdspR2(void) { + WebPDispatchAlpha = DispatchAlpha_MIPSdspR2; + WebPMultARGBRow = MultARGBRow_MIPSdspR2; +#ifdef WORDS_BIGENDIAN + WebPPackARGB = PackARGB_MIPSdspR2; +#endif + WebPPackRGB = PackRGB_MIPSdspR2; +} + +#else // !WEBP_USE_MIPS_DSP_R2 + +WEBP_DSP_INIT_STUB(WebPInitAlphaProcessingMIPSdspR2) + +#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/third-party/webp/libwebp/src/dsp/alpha_processing_neon.c b/third-party/webp/libwebp/src/dsp/alpha_processing_neon.c new file mode 100644 index 0000000000..6716fb77f0 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/alpha_processing_neon.c @@ -0,0 +1,194 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Utilities for processing transparent channel, NEON version. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_NEON) + +#include "src/dsp/neon.h" + +//------------------------------------------------------------------------------ + +#define MULTIPLIER(a) ((a) * 0x8081) +#define PREMULTIPLY(x, m) (((x) * (m)) >> 23) + +#define MULTIPLY_BY_ALPHA(V, ALPHA, OTHER) do { \ + const uint8x8_t alpha = (V).val[(ALPHA)]; \ + const uint16x8_t r1 = vmull_u8((V).val[1], alpha); \ + const uint16x8_t g1 = vmull_u8((V).val[2], alpha); \ + const uint16x8_t b1 = vmull_u8((V).val[(OTHER)], alpha); \ + /* we use: v / 255 = (v + 1 + (v >> 8)) >> 8 */ \ + const uint16x8_t r2 = vsraq_n_u16(r1, r1, 8); \ + const uint16x8_t g2 = vsraq_n_u16(g1, g1, 8); \ + const uint16x8_t b2 = vsraq_n_u16(b1, b1, 8); \ + const uint16x8_t r3 = vaddq_u16(r2, kOne); \ + const uint16x8_t g3 = vaddq_u16(g2, kOne); \ + const uint16x8_t b3 = vaddq_u16(b2, kOne); \ + (V).val[1] = vshrn_n_u16(r3, 8); \ + (V).val[2] = vshrn_n_u16(g3, 8); \ + (V).val[(OTHER)] = vshrn_n_u16(b3, 8); \ +} while (0) + +static void ApplyAlphaMultiply_NEON(uint8_t* rgba, int alpha_first, + int w, int h, int stride) { + const uint16x8_t kOne = vdupq_n_u16(1u); + while (h-- > 0) { + uint32_t* const rgbx = (uint32_t*)rgba; + int i = 0; + if (alpha_first) { + for (; i + 8 <= w; i += 8) { + // load aaaa...|rrrr...|gggg...|bbbb... + uint8x8x4_t RGBX = vld4_u8((const uint8_t*)(rgbx + i)); + MULTIPLY_BY_ALPHA(RGBX, 0, 3); + vst4_u8((uint8_t*)(rgbx + i), RGBX); + } + } else { + for (; i + 8 <= w; i += 8) { + uint8x8x4_t RGBX = vld4_u8((const uint8_t*)(rgbx + i)); + MULTIPLY_BY_ALPHA(RGBX, 3, 0); + vst4_u8((uint8_t*)(rgbx + i), RGBX); + } + } + // Finish with left-overs. + for (; i < w; ++i) { + uint8_t* const rgb = rgba + (alpha_first ? 1 : 0); + const uint8_t* const alpha = rgba + (alpha_first ? 0 : 3); + const uint32_t a = alpha[4 * i]; + if (a != 0xff) { + const uint32_t mult = MULTIPLIER(a); + rgb[4 * i + 0] = PREMULTIPLY(rgb[4 * i + 0], mult); + rgb[4 * i + 1] = PREMULTIPLY(rgb[4 * i + 1], mult); + rgb[4 * i + 2] = PREMULTIPLY(rgb[4 * i + 2], mult); + } + } + rgba += stride; + } +} +#undef MULTIPLY_BY_ALPHA +#undef MULTIPLIER +#undef PREMULTIPLY + +//------------------------------------------------------------------------------ + +static int DispatchAlpha_NEON(const uint8_t* WEBP_RESTRICT alpha, + int alpha_stride, int width, int height, + uint8_t* WEBP_RESTRICT dst, int dst_stride) { + uint32_t alpha_mask = 0xffu; + uint8x8_t mask8 = vdup_n_u8(0xff); + uint32_t tmp[2]; + int i, j; + for (j = 0; j < height; ++j) { + // We don't know if alpha is first or last in dst[] (depending on rgbA/Argb + // mode). So we must be sure dst[4*i + 8 - 1] is writable for the store. + // Hence the test with 'width - 1' instead of just 'width'. + for (i = 0; i + 8 <= width - 1; i += 8) { + uint8x8x4_t rgbX = vld4_u8((const uint8_t*)(dst + 4 * i)); + const uint8x8_t alphas = vld1_u8(alpha + i); + rgbX.val[0] = alphas; + vst4_u8((uint8_t*)(dst + 4 * i), rgbX); + mask8 = vand_u8(mask8, alphas); + } + for (; i < width; ++i) { + const uint32_t alpha_value = alpha[i]; + dst[4 * i] = alpha_value; + alpha_mask &= alpha_value; + } + alpha += alpha_stride; + dst += dst_stride; + } + vst1_u8((uint8_t*)tmp, mask8); + alpha_mask *= 0x01010101; + alpha_mask &= tmp[0]; + alpha_mask &= tmp[1]; + return (alpha_mask != 0xffffffffu); +} + +static void DispatchAlphaToGreen_NEON(const uint8_t* WEBP_RESTRICT alpha, + int alpha_stride, int width, int height, + uint32_t* WEBP_RESTRICT dst, + int dst_stride) { + int i, j; + uint8x8x4_t greens; // leave A/R/B channels zero'd. + greens.val[0] = vdup_n_u8(0); + greens.val[2] = vdup_n_u8(0); + greens.val[3] = vdup_n_u8(0); + for (j = 0; j < height; ++j) { + for (i = 0; i + 8 <= width; i += 8) { + greens.val[1] = vld1_u8(alpha + i); + vst4_u8((uint8_t*)(dst + i), greens); + } + for (; i < width; ++i) dst[i] = alpha[i] << 8; + alpha += alpha_stride; + dst += dst_stride; + } +} + +static int ExtractAlpha_NEON(const uint8_t* WEBP_RESTRICT argb, int argb_stride, + int width, int height, + uint8_t* WEBP_RESTRICT alpha, int alpha_stride) { + uint32_t alpha_mask = 0xffu; + uint8x8_t mask8 = vdup_n_u8(0xff); + uint32_t tmp[2]; + int i, j; + for (j = 0; j < height; ++j) { + // We don't know if alpha is first or last in dst[] (depending on rgbA/Argb + // mode). So we must be sure dst[4*i + 8 - 1] is writable for the store. + // Hence the test with 'width - 1' instead of just 'width'. + for (i = 0; i + 8 <= width - 1; i += 8) { + const uint8x8x4_t rgbX = vld4_u8((const uint8_t*)(argb + 4 * i)); + const uint8x8_t alphas = rgbX.val[0]; + vst1_u8((uint8_t*)(alpha + i), alphas); + mask8 = vand_u8(mask8, alphas); + } + for (; i < width; ++i) { + alpha[i] = argb[4 * i]; + alpha_mask &= alpha[i]; + } + argb += argb_stride; + alpha += alpha_stride; + } + vst1_u8((uint8_t*)tmp, mask8); + alpha_mask *= 0x01010101; + alpha_mask &= tmp[0]; + alpha_mask &= tmp[1]; + return (alpha_mask == 0xffffffffu); +} + +static void ExtractGreen_NEON(const uint32_t* WEBP_RESTRICT argb, + uint8_t* WEBP_RESTRICT alpha, int size) { + int i; + for (i = 0; i + 16 <= size; i += 16) { + const uint8x16x4_t rgbX = vld4q_u8((const uint8_t*)(argb + i)); + const uint8x16_t greens = rgbX.val[1]; + vst1q_u8(alpha + i, greens); + } + for (; i < size; ++i) alpha[i] = (argb[i] >> 8) & 0xff; +} + +//------------------------------------------------------------------------------ + +extern void WebPInitAlphaProcessingNEON(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessingNEON(void) { + WebPApplyAlphaMultiply = ApplyAlphaMultiply_NEON; + WebPDispatchAlpha = DispatchAlpha_NEON; + WebPDispatchAlphaToGreen = DispatchAlphaToGreen_NEON; + WebPExtractAlpha = ExtractAlpha_NEON; + WebPExtractGreen = ExtractGreen_NEON; +} + +#else // !WEBP_USE_NEON + +WEBP_DSP_INIT_STUB(WebPInitAlphaProcessingNEON) + +#endif // WEBP_USE_NEON diff --git a/third-party/webp/libwebp/src/dsp/alpha_processing_sse2.c b/third-party/webp/libwebp/src/dsp/alpha_processing_sse2.c new file mode 100644 index 0000000000..aa0cc2848a --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/alpha_processing_sse2.c @@ -0,0 +1,408 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Utilities for processing transparent channel. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE2) +#include + +//------------------------------------------------------------------------------ + +static int DispatchAlpha_SSE2(const uint8_t* WEBP_RESTRICT alpha, + int alpha_stride, int width, int height, + uint8_t* WEBP_RESTRICT dst, int dst_stride) { + // alpha_and stores an 'and' operation of all the alpha[] values. The final + // value is not 0xff if any of the alpha[] is not equal to 0xff. + uint32_t alpha_and = 0xff; + int i, j; + const __m128i zero = _mm_setzero_si128(); + const __m128i rgb_mask = _mm_set1_epi32((int)0xffffff00); // to preserve RGB + const __m128i all_0xff = _mm_set_epi32(0, 0, ~0, ~0); + __m128i all_alphas = all_0xff; + + // We must be able to access 3 extra bytes after the last written byte + // 'dst[4 * width - 4]', because we don't know if alpha is the first or the + // last byte of the quadruplet. + const int limit = (width - 1) & ~7; + + for (j = 0; j < height; ++j) { + __m128i* out = (__m128i*)dst; + for (i = 0; i < limit; i += 8) { + // load 8 alpha bytes + const __m128i a0 = _mm_loadl_epi64((const __m128i*)&alpha[i]); + const __m128i a1 = _mm_unpacklo_epi8(a0, zero); + const __m128i a2_lo = _mm_unpacklo_epi16(a1, zero); + const __m128i a2_hi = _mm_unpackhi_epi16(a1, zero); + // load 8 dst pixels (32 bytes) + const __m128i b0_lo = _mm_loadu_si128(out + 0); + const __m128i b0_hi = _mm_loadu_si128(out + 1); + // mask dst alpha values + const __m128i b1_lo = _mm_and_si128(b0_lo, rgb_mask); + const __m128i b1_hi = _mm_and_si128(b0_hi, rgb_mask); + // combine + const __m128i b2_lo = _mm_or_si128(b1_lo, a2_lo); + const __m128i b2_hi = _mm_or_si128(b1_hi, a2_hi); + // store + _mm_storeu_si128(out + 0, b2_lo); + _mm_storeu_si128(out + 1, b2_hi); + // accumulate eight alpha 'and' in parallel + all_alphas = _mm_and_si128(all_alphas, a0); + out += 2; + } + for (; i < width; ++i) { + const uint32_t alpha_value = alpha[i]; + dst[4 * i] = alpha_value; + alpha_and &= alpha_value; + } + alpha += alpha_stride; + dst += dst_stride; + } + // Combine the eight alpha 'and' into a 8-bit mask. + alpha_and &= _mm_movemask_epi8(_mm_cmpeq_epi8(all_alphas, all_0xff)); + return (alpha_and != 0xff); +} + +static void DispatchAlphaToGreen_SSE2(const uint8_t* WEBP_RESTRICT alpha, + int alpha_stride, int width, int height, + uint32_t* WEBP_RESTRICT dst, + int dst_stride) { + int i, j; + const __m128i zero = _mm_setzero_si128(); + const int limit = width & ~15; + for (j = 0; j < height; ++j) { + for (i = 0; i < limit; i += 16) { // process 16 alpha bytes + const __m128i a0 = _mm_loadu_si128((const __m128i*)&alpha[i]); + const __m128i a1 = _mm_unpacklo_epi8(zero, a0); // note the 'zero' first! + const __m128i b1 = _mm_unpackhi_epi8(zero, a0); + const __m128i a2_lo = _mm_unpacklo_epi16(a1, zero); + const __m128i b2_lo = _mm_unpacklo_epi16(b1, zero); + const __m128i a2_hi = _mm_unpackhi_epi16(a1, zero); + const __m128i b2_hi = _mm_unpackhi_epi16(b1, zero); + _mm_storeu_si128((__m128i*)&dst[i + 0], a2_lo); + _mm_storeu_si128((__m128i*)&dst[i + 4], a2_hi); + _mm_storeu_si128((__m128i*)&dst[i + 8], b2_lo); + _mm_storeu_si128((__m128i*)&dst[i + 12], b2_hi); + } + for (; i < width; ++i) dst[i] = alpha[i] << 8; + alpha += alpha_stride; + dst += dst_stride; + } +} + +static int ExtractAlpha_SSE2(const uint8_t* WEBP_RESTRICT argb, int argb_stride, + int width, int height, + uint8_t* WEBP_RESTRICT alpha, int alpha_stride) { + // alpha_and stores an 'and' operation of all the alpha[] values. The final + // value is not 0xff if any of the alpha[] is not equal to 0xff. + uint32_t alpha_and = 0xff; + int i, j; + const __m128i a_mask = _mm_set1_epi32(0xff); // to preserve alpha + const __m128i all_0xff = _mm_set_epi32(0, 0, ~0, ~0); + __m128i all_alphas = all_0xff; + + // We must be able to access 3 extra bytes after the last written byte + // 'src[4 * width - 4]', because we don't know if alpha is the first or the + // last byte of the quadruplet. + const int limit = (width - 1) & ~7; + + for (j = 0; j < height; ++j) { + const __m128i* src = (const __m128i*)argb; + for (i = 0; i < limit; i += 8) { + // load 32 argb bytes + const __m128i a0 = _mm_loadu_si128(src + 0); + const __m128i a1 = _mm_loadu_si128(src + 1); + const __m128i b0 = _mm_and_si128(a0, a_mask); + const __m128i b1 = _mm_and_si128(a1, a_mask); + const __m128i c0 = _mm_packs_epi32(b0, b1); + const __m128i d0 = _mm_packus_epi16(c0, c0); + // store + _mm_storel_epi64((__m128i*)&alpha[i], d0); + // accumulate eight alpha 'and' in parallel + all_alphas = _mm_and_si128(all_alphas, d0); + src += 2; + } + for (; i < width; ++i) { + const uint32_t alpha_value = argb[4 * i]; + alpha[i] = alpha_value; + alpha_and &= alpha_value; + } + argb += argb_stride; + alpha += alpha_stride; + } + // Combine the eight alpha 'and' into a 8-bit mask. + alpha_and &= _mm_movemask_epi8(_mm_cmpeq_epi8(all_alphas, all_0xff)); + return (alpha_and == 0xff); +} + +static void ExtractGreen_SSE2(const uint32_t* WEBP_RESTRICT argb, + uint8_t* WEBP_RESTRICT alpha, int size) { + int i; + const __m128i mask = _mm_set1_epi32(0xff); + const __m128i* src = (const __m128i*)argb; + + for (i = 0; i + 16 <= size; i += 16, src += 4) { + const __m128i a0 = _mm_loadu_si128(src + 0); + const __m128i a1 = _mm_loadu_si128(src + 1); + const __m128i a2 = _mm_loadu_si128(src + 2); + const __m128i a3 = _mm_loadu_si128(src + 3); + const __m128i b0 = _mm_srli_epi32(a0, 8); + const __m128i b1 = _mm_srli_epi32(a1, 8); + const __m128i b2 = _mm_srli_epi32(a2, 8); + const __m128i b3 = _mm_srli_epi32(a3, 8); + const __m128i c0 = _mm_and_si128(b0, mask); + const __m128i c1 = _mm_and_si128(b1, mask); + const __m128i c2 = _mm_and_si128(b2, mask); + const __m128i c3 = _mm_and_si128(b3, mask); + const __m128i d0 = _mm_packs_epi32(c0, c1); + const __m128i d1 = _mm_packs_epi32(c2, c3); + const __m128i e = _mm_packus_epi16(d0, d1); + // store + _mm_storeu_si128((__m128i*)&alpha[i], e); + } + if (i + 8 <= size) { + const __m128i a0 = _mm_loadu_si128(src + 0); + const __m128i a1 = _mm_loadu_si128(src + 1); + const __m128i b0 = _mm_srli_epi32(a0, 8); + const __m128i b1 = _mm_srli_epi32(a1, 8); + const __m128i c0 = _mm_and_si128(b0, mask); + const __m128i c1 = _mm_and_si128(b1, mask); + const __m128i d = _mm_packs_epi32(c0, c1); + const __m128i e = _mm_packus_epi16(d, d); + _mm_storel_epi64((__m128i*)&alpha[i], e); + i += 8; + } + for (; i < size; ++i) alpha[i] = argb[i] >> 8; +} + +//------------------------------------------------------------------------------ +// Non-dither premultiplied modes + +#define MULTIPLIER(a) ((a) * 0x8081) +#define PREMULTIPLY(x, m) (((x) * (m)) >> 23) + +// We can't use a 'const int' for the SHUFFLE value, because it has to be an +// immediate in the _mm_shufflexx_epi16() instruction. We really need a macro. +// We use: v / 255 = (v * 0x8081) >> 23, where v = alpha * {r,g,b} is a 16bit +// value. +#define APPLY_ALPHA(RGBX, SHUFFLE) do { \ + const __m128i argb0 = _mm_loadu_si128((const __m128i*)&(RGBX)); \ + const __m128i argb1_lo = _mm_unpacklo_epi8(argb0, zero); \ + const __m128i argb1_hi = _mm_unpackhi_epi8(argb0, zero); \ + const __m128i alpha0_lo = _mm_or_si128(argb1_lo, kMask); \ + const __m128i alpha0_hi = _mm_or_si128(argb1_hi, kMask); \ + const __m128i alpha1_lo = _mm_shufflelo_epi16(alpha0_lo, SHUFFLE); \ + const __m128i alpha1_hi = _mm_shufflelo_epi16(alpha0_hi, SHUFFLE); \ + const __m128i alpha2_lo = _mm_shufflehi_epi16(alpha1_lo, SHUFFLE); \ + const __m128i alpha2_hi = _mm_shufflehi_epi16(alpha1_hi, SHUFFLE); \ + /* alpha2 = [ff a0 a0 a0][ff a1 a1 a1] */ \ + const __m128i A0_lo = _mm_mullo_epi16(alpha2_lo, argb1_lo); \ + const __m128i A0_hi = _mm_mullo_epi16(alpha2_hi, argb1_hi); \ + const __m128i A1_lo = _mm_mulhi_epu16(A0_lo, kMult); \ + const __m128i A1_hi = _mm_mulhi_epu16(A0_hi, kMult); \ + const __m128i A2_lo = _mm_srli_epi16(A1_lo, 7); \ + const __m128i A2_hi = _mm_srli_epi16(A1_hi, 7); \ + const __m128i A3 = _mm_packus_epi16(A2_lo, A2_hi); \ + _mm_storeu_si128((__m128i*)&(RGBX), A3); \ +} while (0) + +static void ApplyAlphaMultiply_SSE2(uint8_t* rgba, int alpha_first, + int w, int h, int stride) { + const __m128i zero = _mm_setzero_si128(); + const __m128i kMult = _mm_set1_epi16((short)0x8081); + const __m128i kMask = _mm_set_epi16(0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0); + const int kSpan = 4; + while (h-- > 0) { + uint32_t* const rgbx = (uint32_t*)rgba; + int i; + if (!alpha_first) { + for (i = 0; i + kSpan <= w; i += kSpan) { + APPLY_ALPHA(rgbx[i], _MM_SHUFFLE(2, 3, 3, 3)); + } + } else { + for (i = 0; i + kSpan <= w; i += kSpan) { + APPLY_ALPHA(rgbx[i], _MM_SHUFFLE(0, 0, 0, 1)); + } + } + // Finish with left-overs. + for (; i < w; ++i) { + uint8_t* const rgb = rgba + (alpha_first ? 1 : 0); + const uint8_t* const alpha = rgba + (alpha_first ? 0 : 3); + const uint32_t a = alpha[4 * i]; + if (a != 0xff) { + const uint32_t mult = MULTIPLIER(a); + rgb[4 * i + 0] = PREMULTIPLY(rgb[4 * i + 0], mult); + rgb[4 * i + 1] = PREMULTIPLY(rgb[4 * i + 1], mult); + rgb[4 * i + 2] = PREMULTIPLY(rgb[4 * i + 2], mult); + } + } + rgba += stride; + } +} +#undef MULTIPLIER +#undef PREMULTIPLY + +//------------------------------------------------------------------------------ +// Alpha detection + +static int HasAlpha8b_SSE2(const uint8_t* src, int length) { + const __m128i all_0xff = _mm_set1_epi8((char)0xff); + int i = 0; + for (; i + 16 <= length; i += 16) { + const __m128i v = _mm_loadu_si128((const __m128i*)(src + i)); + const __m128i bits = _mm_cmpeq_epi8(v, all_0xff); + const int mask = _mm_movemask_epi8(bits); + if (mask != 0xffff) return 1; + } + for (; i < length; ++i) if (src[i] != 0xff) return 1; + return 0; +} + +static int HasAlpha32b_SSE2(const uint8_t* src, int length) { + const __m128i alpha_mask = _mm_set1_epi32(0xff); + const __m128i all_0xff = _mm_set1_epi8((char)0xff); + int i = 0; + // We don't know if we can access the last 3 bytes after the last alpha + // value 'src[4 * length - 4]' (because we don't know if alpha is the first + // or the last byte of the quadruplet). Hence the '-3' protection below. + length = length * 4 - 3; // size in bytes + for (; i + 64 <= length; i += 64) { + const __m128i a0 = _mm_loadu_si128((const __m128i*)(src + i + 0)); + const __m128i a1 = _mm_loadu_si128((const __m128i*)(src + i + 16)); + const __m128i a2 = _mm_loadu_si128((const __m128i*)(src + i + 32)); + const __m128i a3 = _mm_loadu_si128((const __m128i*)(src + i + 48)); + const __m128i b0 = _mm_and_si128(a0, alpha_mask); + const __m128i b1 = _mm_and_si128(a1, alpha_mask); + const __m128i b2 = _mm_and_si128(a2, alpha_mask); + const __m128i b3 = _mm_and_si128(a3, alpha_mask); + const __m128i c0 = _mm_packs_epi32(b0, b1); + const __m128i c1 = _mm_packs_epi32(b2, b3); + const __m128i d = _mm_packus_epi16(c0, c1); + const __m128i bits = _mm_cmpeq_epi8(d, all_0xff); + const int mask = _mm_movemask_epi8(bits); + if (mask != 0xffff) return 1; + } + for (; i + 32 <= length; i += 32) { + const __m128i a0 = _mm_loadu_si128((const __m128i*)(src + i + 0)); + const __m128i a1 = _mm_loadu_si128((const __m128i*)(src + i + 16)); + const __m128i b0 = _mm_and_si128(a0, alpha_mask); + const __m128i b1 = _mm_and_si128(a1, alpha_mask); + const __m128i c = _mm_packs_epi32(b0, b1); + const __m128i d = _mm_packus_epi16(c, c); + const __m128i bits = _mm_cmpeq_epi8(d, all_0xff); + const int mask = _mm_movemask_epi8(bits); + if (mask != 0xffff) return 1; + } + for (; i <= length; i += 4) if (src[i] != 0xff) return 1; + return 0; +} + +static void AlphaReplace_SSE2(uint32_t* src, int length, uint32_t color) { + const __m128i m_color = _mm_set1_epi32((int)color); + const __m128i zero = _mm_setzero_si128(); + int i = 0; + for (; i + 8 <= length; i += 8) { + const __m128i a0 = _mm_loadu_si128((const __m128i*)(src + i + 0)); + const __m128i a1 = _mm_loadu_si128((const __m128i*)(src + i + 4)); + const __m128i b0 = _mm_srai_epi32(a0, 24); + const __m128i b1 = _mm_srai_epi32(a1, 24); + const __m128i c0 = _mm_cmpeq_epi32(b0, zero); + const __m128i c1 = _mm_cmpeq_epi32(b1, zero); + const __m128i d0 = _mm_and_si128(c0, m_color); + const __m128i d1 = _mm_and_si128(c1, m_color); + const __m128i e0 = _mm_andnot_si128(c0, a0); + const __m128i e1 = _mm_andnot_si128(c1, a1); + _mm_storeu_si128((__m128i*)(src + i + 0), _mm_or_si128(d0, e0)); + _mm_storeu_si128((__m128i*)(src + i + 4), _mm_or_si128(d1, e1)); + } + for (; i < length; ++i) if ((src[i] >> 24) == 0) src[i] = color; +} + +// ----------------------------------------------------------------------------- +// Apply alpha value to rows + +static void MultARGBRow_SSE2(uint32_t* const ptr, int width, int inverse) { + int x = 0; + if (!inverse) { + const int kSpan = 2; + const __m128i zero = _mm_setzero_si128(); + const __m128i k128 = _mm_set1_epi16(128); + const __m128i kMult = _mm_set1_epi16(0x0101); + const __m128i kMask = _mm_set_epi16(0, 0xff, 0, 0, 0, 0xff, 0, 0); + for (x = 0; x + kSpan <= width; x += kSpan) { + // To compute 'result = (int)(a * x / 255. + .5)', we use: + // tmp = a * v + 128, result = (tmp * 0x0101u) >> 16 + const __m128i A0 = _mm_loadl_epi64((const __m128i*)&ptr[x]); + const __m128i A1 = _mm_unpacklo_epi8(A0, zero); + const __m128i A2 = _mm_or_si128(A1, kMask); + const __m128i A3 = _mm_shufflelo_epi16(A2, _MM_SHUFFLE(2, 3, 3, 3)); + const __m128i A4 = _mm_shufflehi_epi16(A3, _MM_SHUFFLE(2, 3, 3, 3)); + // here, A4 = [ff a0 a0 a0][ff a1 a1 a1] + const __m128i A5 = _mm_mullo_epi16(A4, A1); + const __m128i A6 = _mm_add_epi16(A5, k128); + const __m128i A7 = _mm_mulhi_epu16(A6, kMult); + const __m128i A10 = _mm_packus_epi16(A7, zero); + _mm_storel_epi64((__m128i*)&ptr[x], A10); + } + } + width -= x; + if (width > 0) WebPMultARGBRow_C(ptr + x, width, inverse); +} + +static void MultRow_SSE2(uint8_t* WEBP_RESTRICT const ptr, + const uint8_t* WEBP_RESTRICT const alpha, + int width, int inverse) { + int x = 0; + if (!inverse) { + const __m128i zero = _mm_setzero_si128(); + const __m128i k128 = _mm_set1_epi16(128); + const __m128i kMult = _mm_set1_epi16(0x0101); + for (x = 0; x + 8 <= width; x += 8) { + const __m128i v0 = _mm_loadl_epi64((__m128i*)&ptr[x]); + const __m128i a0 = _mm_loadl_epi64((const __m128i*)&alpha[x]); + const __m128i v1 = _mm_unpacklo_epi8(v0, zero); + const __m128i a1 = _mm_unpacklo_epi8(a0, zero); + const __m128i v2 = _mm_mullo_epi16(v1, a1); + const __m128i v3 = _mm_add_epi16(v2, k128); + const __m128i v4 = _mm_mulhi_epu16(v3, kMult); + const __m128i v5 = _mm_packus_epi16(v4, zero); + _mm_storel_epi64((__m128i*)&ptr[x], v5); + } + } + width -= x; + if (width > 0) WebPMultRow_C(ptr + x, alpha + x, width, inverse); +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void WebPInitAlphaProcessingSSE2(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessingSSE2(void) { + WebPMultARGBRow = MultARGBRow_SSE2; + WebPMultRow = MultRow_SSE2; + WebPApplyAlphaMultiply = ApplyAlphaMultiply_SSE2; + WebPDispatchAlpha = DispatchAlpha_SSE2; + WebPDispatchAlphaToGreen = DispatchAlphaToGreen_SSE2; + WebPExtractAlpha = ExtractAlpha_SSE2; + WebPExtractGreen = ExtractGreen_SSE2; + + WebPHasAlpha8b = HasAlpha8b_SSE2; + WebPHasAlpha32b = HasAlpha32b_SSE2; + WebPAlphaReplace = AlphaReplace_SSE2; +} + +#else // !WEBP_USE_SSE2 + +WEBP_DSP_INIT_STUB(WebPInitAlphaProcessingSSE2) + +#endif // WEBP_USE_SSE2 diff --git a/third-party/webp/libwebp/src/dsp/alpha_processing_sse41.c b/third-party/webp/libwebp/src/dsp/alpha_processing_sse41.c new file mode 100644 index 0000000000..1156ac3417 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/alpha_processing_sse41.c @@ -0,0 +1,92 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Utilities for processing transparent channel, SSE4.1 variant. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE41) + +#include + +//------------------------------------------------------------------------------ + +static int ExtractAlpha_SSE41(const uint8_t* WEBP_RESTRICT argb, + int argb_stride, int width, int height, + uint8_t* WEBP_RESTRICT alpha, int alpha_stride) { + // alpha_and stores an 'and' operation of all the alpha[] values. The final + // value is not 0xff if any of the alpha[] is not equal to 0xff. + uint32_t alpha_and = 0xff; + int i, j; + const __m128i all_0xff = _mm_set1_epi32(~0); + __m128i all_alphas = all_0xff; + + // We must be able to access 3 extra bytes after the last written byte + // 'src[4 * width - 4]', because we don't know if alpha is the first or the + // last byte of the quadruplet. + const int limit = (width - 1) & ~15; + const __m128i kCstAlpha0 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 12, 8, 4, 0); + const __m128i kCstAlpha1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, + 12, 8, 4, 0, -1, -1, -1, -1); + const __m128i kCstAlpha2 = _mm_set_epi8(-1, -1, -1, -1, 12, 8, 4, 0, + -1, -1, -1, -1, -1, -1, -1, -1); + const __m128i kCstAlpha3 = _mm_set_epi8(12, 8, 4, 0, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1); + for (j = 0; j < height; ++j) { + const __m128i* src = (const __m128i*)argb; + for (i = 0; i < limit; i += 16) { + // load 64 argb bytes + const __m128i a0 = _mm_loadu_si128(src + 0); + const __m128i a1 = _mm_loadu_si128(src + 1); + const __m128i a2 = _mm_loadu_si128(src + 2); + const __m128i a3 = _mm_loadu_si128(src + 3); + const __m128i b0 = _mm_shuffle_epi8(a0, kCstAlpha0); + const __m128i b1 = _mm_shuffle_epi8(a1, kCstAlpha1); + const __m128i b2 = _mm_shuffle_epi8(a2, kCstAlpha2); + const __m128i b3 = _mm_shuffle_epi8(a3, kCstAlpha3); + const __m128i c0 = _mm_or_si128(b0, b1); + const __m128i c1 = _mm_or_si128(b2, b3); + const __m128i d0 = _mm_or_si128(c0, c1); + // store + _mm_storeu_si128((__m128i*)&alpha[i], d0); + // accumulate sixteen alpha 'and' in parallel + all_alphas = _mm_and_si128(all_alphas, d0); + src += 4; + } + for (; i < width; ++i) { + const uint32_t alpha_value = argb[4 * i]; + alpha[i] = alpha_value; + alpha_and &= alpha_value; + } + argb += argb_stride; + alpha += alpha_stride; + } + // Combine the sixteen alpha 'and' into an 8-bit mask. + alpha_and |= 0xff00u; // pretend the upper bits [8..15] were tested ok. + alpha_and &= _mm_movemask_epi8(_mm_cmpeq_epi8(all_alphas, all_0xff)); + return (alpha_and == 0xffffu); +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void WebPInitAlphaProcessingSSE41(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessingSSE41(void) { + WebPExtractAlpha = ExtractAlpha_SSE41; +} + +#else // !WEBP_USE_SSE41 + +WEBP_DSP_INIT_STUB(WebPInitAlphaProcessingSSE41) + +#endif // WEBP_USE_SSE41 diff --git a/third-party/webp/libwebp/src/dsp/common_sse2.h b/third-party/webp/libwebp/src/dsp/common_sse2.h new file mode 100644 index 0000000000..e9f1ebff44 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/common_sse2.h @@ -0,0 +1,194 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE2 code common to several files. +// +// Author: Vincent Rabaud (vrabaud@google.com) + +#ifndef WEBP_DSP_COMMON_SSE2_H_ +#define WEBP_DSP_COMMON_SSE2_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(WEBP_USE_SSE2) + +#include + +//------------------------------------------------------------------------------ +// Quite useful macro for debugging. Left here for convenience. + +#if 0 +#include +static WEBP_INLINE void PrintReg(const __m128i r, const char* const name, + int size) { + int n; + union { + __m128i r; + uint8_t i8[16]; + uint16_t i16[8]; + uint32_t i32[4]; + uint64_t i64[2]; + } tmp; + tmp.r = r; + fprintf(stderr, "%s\t: ", name); + if (size == 8) { + for (n = 0; n < 16; ++n) fprintf(stderr, "%.2x ", tmp.i8[n]); + } else if (size == 16) { + for (n = 0; n < 8; ++n) fprintf(stderr, "%.4x ", tmp.i16[n]); + } else if (size == 32) { + for (n = 0; n < 4; ++n) fprintf(stderr, "%.8x ", tmp.i32[n]); + } else { + for (n = 0; n < 2; ++n) fprintf(stderr, "%.16lx ", tmp.i64[n]); + } + fprintf(stderr, "\n"); +} +#endif + +//------------------------------------------------------------------------------ +// Math functions. + +// Return the sum of all the 8b in the register. +static WEBP_INLINE int VP8HorizontalAdd8b(const __m128i* const a) { + const __m128i zero = _mm_setzero_si128(); + const __m128i sad8x2 = _mm_sad_epu8(*a, zero); + // sum the two sads: sad8x2[0:1] + sad8x2[8:9] + const __m128i sum = _mm_add_epi32(sad8x2, _mm_shuffle_epi32(sad8x2, 2)); + return _mm_cvtsi128_si32(sum); +} + +// Transpose two 4x4 16b matrices horizontally stored in registers. +static WEBP_INLINE void VP8Transpose_2_4x4_16b( + const __m128i* const in0, const __m128i* const in1, + const __m128i* const in2, const __m128i* const in3, __m128i* const out0, + __m128i* const out1, __m128i* const out2, __m128i* const out3) { + // Transpose the two 4x4. + // a00 a01 a02 a03 b00 b01 b02 b03 + // a10 a11 a12 a13 b10 b11 b12 b13 + // a20 a21 a22 a23 b20 b21 b22 b23 + // a30 a31 a32 a33 b30 b31 b32 b33 + const __m128i transpose0_0 = _mm_unpacklo_epi16(*in0, *in1); + const __m128i transpose0_1 = _mm_unpacklo_epi16(*in2, *in3); + const __m128i transpose0_2 = _mm_unpackhi_epi16(*in0, *in1); + const __m128i transpose0_3 = _mm_unpackhi_epi16(*in2, *in3); + // a00 a10 a01 a11 a02 a12 a03 a13 + // a20 a30 a21 a31 a22 a32 a23 a33 + // b00 b10 b01 b11 b02 b12 b03 b13 + // b20 b30 b21 b31 b22 b32 b23 b33 + const __m128i transpose1_0 = _mm_unpacklo_epi32(transpose0_0, transpose0_1); + const __m128i transpose1_1 = _mm_unpacklo_epi32(transpose0_2, transpose0_3); + const __m128i transpose1_2 = _mm_unpackhi_epi32(transpose0_0, transpose0_1); + const __m128i transpose1_3 = _mm_unpackhi_epi32(transpose0_2, transpose0_3); + // a00 a10 a20 a30 a01 a11 a21 a31 + // b00 b10 b20 b30 b01 b11 b21 b31 + // a02 a12 a22 a32 a03 a13 a23 a33 + // b02 b12 a22 b32 b03 b13 b23 b33 + *out0 = _mm_unpacklo_epi64(transpose1_0, transpose1_1); + *out1 = _mm_unpackhi_epi64(transpose1_0, transpose1_1); + *out2 = _mm_unpacklo_epi64(transpose1_2, transpose1_3); + *out3 = _mm_unpackhi_epi64(transpose1_2, transpose1_3); + // a00 a10 a20 a30 b00 b10 b20 b30 + // a01 a11 a21 a31 b01 b11 b21 b31 + // a02 a12 a22 a32 b02 b12 b22 b32 + // a03 a13 a23 a33 b03 b13 b23 b33 +} + +//------------------------------------------------------------------------------ +// Channel mixing. + +// Function used several times in VP8PlanarTo24b. +// It samples the in buffer as follows: one every two unsigned char is stored +// at the beginning of the buffer, while the other half is stored at the end. +#define VP8PlanarTo24bHelper(IN, OUT) \ + do { \ + const __m128i v_mask = _mm_set1_epi16(0x00ff); \ + /* Take one every two upper 8b values.*/ \ + (OUT##0) = _mm_packus_epi16(_mm_and_si128((IN##0), v_mask), \ + _mm_and_si128((IN##1), v_mask)); \ + (OUT##1) = _mm_packus_epi16(_mm_and_si128((IN##2), v_mask), \ + _mm_and_si128((IN##3), v_mask)); \ + (OUT##2) = _mm_packus_epi16(_mm_and_si128((IN##4), v_mask), \ + _mm_and_si128((IN##5), v_mask)); \ + /* Take one every two lower 8b values.*/ \ + (OUT##3) = _mm_packus_epi16(_mm_srli_epi16((IN##0), 8), \ + _mm_srli_epi16((IN##1), 8)); \ + (OUT##4) = _mm_packus_epi16(_mm_srli_epi16((IN##2), 8), \ + _mm_srli_epi16((IN##3), 8)); \ + (OUT##5) = _mm_packus_epi16(_mm_srli_epi16((IN##4), 8), \ + _mm_srli_epi16((IN##5), 8)); \ + } while (0) + +// Pack the planar buffers +// rrrr... rrrr... gggg... gggg... bbbb... bbbb.... +// triplet by triplet in the output buffer rgb as rgbrgbrgbrgb ... +static WEBP_INLINE void VP8PlanarTo24b_SSE2( + __m128i* const in0, __m128i* const in1, __m128i* const in2, + __m128i* const in3, __m128i* const in4, __m128i* const in5) { + // The input is 6 registers of sixteen 8b but for the sake of explanation, + // let's take 6 registers of four 8b values. + // To pack, we will keep taking one every two 8b integer and move it + // around as follows: + // Input: + // r0r1r2r3 | r4r5r6r7 | g0g1g2g3 | g4g5g6g7 | b0b1b2b3 | b4b5b6b7 + // Split the 6 registers in two sets of 3 registers: the first set as the even + // 8b bytes, the second the odd ones: + // r0r2r4r6 | g0g2g4g6 | b0b2b4b6 | r1r3r5r7 | g1g3g5g7 | b1b3b5b7 + // Repeat the same permutations twice more: + // r0r4g0g4 | b0b4r1r5 | g1g5b1b5 | r2r6g2g6 | b2b6r3r7 | g3g7b3b7 + // r0g0b0r1 | g1b1r2g2 | b2r3g3b3 | r4g4b4r5 | g5b5r6g6 | b6r7g7b7 + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + VP8PlanarTo24bHelper(*in, tmp); + VP8PlanarTo24bHelper(tmp, *in); + VP8PlanarTo24bHelper(*in, tmp); + // We need to do it two more times than the example as we have sixteen bytes. + { + __m128i out0, out1, out2, out3, out4, out5; + VP8PlanarTo24bHelper(tmp, out); + VP8PlanarTo24bHelper(out, *in); + } +} + +#undef VP8PlanarTo24bHelper + +// Convert four packed four-channel buffers like argbargbargbargb... into the +// split channels aaaaa ... rrrr ... gggg .... bbbbb ...... +static WEBP_INLINE void VP8L32bToPlanar_SSE2(__m128i* const in0, + __m128i* const in1, + __m128i* const in2, + __m128i* const in3) { + // Column-wise transpose. + const __m128i A0 = _mm_unpacklo_epi8(*in0, *in1); + const __m128i A1 = _mm_unpackhi_epi8(*in0, *in1); + const __m128i A2 = _mm_unpacklo_epi8(*in2, *in3); + const __m128i A3 = _mm_unpackhi_epi8(*in2, *in3); + const __m128i B0 = _mm_unpacklo_epi8(A0, A1); + const __m128i B1 = _mm_unpackhi_epi8(A0, A1); + const __m128i B2 = _mm_unpacklo_epi8(A2, A3); + const __m128i B3 = _mm_unpackhi_epi8(A2, A3); + // C0 = g7 g6 ... g1 g0 | b7 b6 ... b1 b0 + // C1 = a7 a6 ... a1 a0 | r7 r6 ... r1 r0 + const __m128i C0 = _mm_unpacklo_epi8(B0, B1); + const __m128i C1 = _mm_unpackhi_epi8(B0, B1); + const __m128i C2 = _mm_unpacklo_epi8(B2, B3); + const __m128i C3 = _mm_unpackhi_epi8(B2, B3); + // Gather the channels. + *in0 = _mm_unpackhi_epi64(C1, C3); + *in1 = _mm_unpacklo_epi64(C1, C3); + *in2 = _mm_unpackhi_epi64(C0, C2); + *in3 = _mm_unpacklo_epi64(C0, C2); +} + +#endif // WEBP_USE_SSE2 + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_DSP_COMMON_SSE2_H_ diff --git a/third-party/webp/libwebp/src/dsp/common_sse41.h b/third-party/webp/libwebp/src/dsp/common_sse41.h new file mode 100644 index 0000000000..2f173c024a --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/common_sse41.h @@ -0,0 +1,132 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE4 code common to several files. +// +// Author: Vincent Rabaud (vrabaud@google.com) + +#ifndef WEBP_DSP_COMMON_SSE41_H_ +#define WEBP_DSP_COMMON_SSE41_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(WEBP_USE_SSE41) +#include + +//------------------------------------------------------------------------------ +// Channel mixing. +// Shuffles the input buffer as A0 0 0 A1 0 0 A2 ... +#define WEBP_SSE41_SHUFF(OUT, IN0, IN1) \ + OUT##0 = _mm_shuffle_epi8(*IN0, shuff0); \ + OUT##1 = _mm_shuffle_epi8(*IN0, shuff1); \ + OUT##2 = _mm_shuffle_epi8(*IN0, shuff2); \ + OUT##3 = _mm_shuffle_epi8(*IN1, shuff0); \ + OUT##4 = _mm_shuffle_epi8(*IN1, shuff1); \ + OUT##5 = _mm_shuffle_epi8(*IN1, shuff2); + +// Pack the planar buffers +// rrrr... rrrr... gggg... gggg... bbbb... bbbb.... +// triplet by triplet in the output buffer rgb as rgbrgbrgbrgb ... +static WEBP_INLINE void VP8PlanarTo24b_SSE41( + __m128i* const in0, __m128i* const in1, __m128i* const in2, + __m128i* const in3, __m128i* const in4, __m128i* const in5) { + __m128i R0, R1, R2, R3, R4, R5; + __m128i G0, G1, G2, G3, G4, G5; + __m128i B0, B1, B2, B3, B4, B5; + + // Process R. + { + const __m128i shuff0 = _mm_set_epi8( + 5, -1, -1, 4, -1, -1, 3, -1, -1, 2, -1, -1, 1, -1, -1, 0); + const __m128i shuff1 = _mm_set_epi8( + -1, 10, -1, -1, 9, -1, -1, 8, -1, -1, 7, -1, -1, 6, -1, -1); + const __m128i shuff2 = _mm_set_epi8( + -1, -1, 15, -1, -1, 14, -1, -1, 13, -1, -1, 12, -1, -1, 11, -1); + WEBP_SSE41_SHUFF(R, in0, in1) + } + + // Process G. + { + // Same as before, just shifted to the left by one and including the right + // padding. + const __m128i shuff0 = _mm_set_epi8( + -1, -1, 4, -1, -1, 3, -1, -1, 2, -1, -1, 1, -1, -1, 0, -1); + const __m128i shuff1 = _mm_set_epi8( + 10, -1, -1, 9, -1, -1, 8, -1, -1, 7, -1, -1, 6, -1, -1, 5); + const __m128i shuff2 = _mm_set_epi8( + -1, 15, -1, -1, 14, -1, -1, 13, -1, -1, 12, -1, -1, 11, -1, -1); + WEBP_SSE41_SHUFF(G, in2, in3) + } + + // Process B. + { + const __m128i shuff0 = _mm_set_epi8( + -1, 4, -1, -1, 3, -1, -1, 2, -1, -1, 1, -1, -1, 0, -1, -1); + const __m128i shuff1 = _mm_set_epi8( + -1, -1, 9, -1, -1, 8, -1, -1, 7, -1, -1, 6, -1, -1, 5, -1); + const __m128i shuff2 = _mm_set_epi8( + 15, -1, -1, 14, -1, -1, 13, -1, -1, 12, -1, -1, 11, -1, -1, 10); + WEBP_SSE41_SHUFF(B, in4, in5) + } + + // OR the different channels. + { + const __m128i RG0 = _mm_or_si128(R0, G0); + const __m128i RG1 = _mm_or_si128(R1, G1); + const __m128i RG2 = _mm_or_si128(R2, G2); + const __m128i RG3 = _mm_or_si128(R3, G3); + const __m128i RG4 = _mm_or_si128(R4, G4); + const __m128i RG5 = _mm_or_si128(R5, G5); + *in0 = _mm_or_si128(RG0, B0); + *in1 = _mm_or_si128(RG1, B1); + *in2 = _mm_or_si128(RG2, B2); + *in3 = _mm_or_si128(RG3, B3); + *in4 = _mm_or_si128(RG4, B4); + *in5 = _mm_or_si128(RG5, B5); + } +} + +#undef WEBP_SSE41_SHUFF + +// Convert four packed four-channel buffers like argbargbargbargb... into the +// split channels aaaaa ... rrrr ... gggg .... bbbbb ...... +static WEBP_INLINE void VP8L32bToPlanar_SSE41(__m128i* const in0, + __m128i* const in1, + __m128i* const in2, + __m128i* const in3) { + // aaaarrrrggggbbbb + const __m128i shuff0 = + _mm_set_epi8(15, 11, 7, 3, 14, 10, 6, 2, 13, 9, 5, 1, 12, 8, 4, 0); + const __m128i A0 = _mm_shuffle_epi8(*in0, shuff0); + const __m128i A1 = _mm_shuffle_epi8(*in1, shuff0); + const __m128i A2 = _mm_shuffle_epi8(*in2, shuff0); + const __m128i A3 = _mm_shuffle_epi8(*in3, shuff0); + // A0A1R0R1 + // G0G1B0B1 + // A2A3R2R3 + // G0G1B0B1 + const __m128i B0 = _mm_unpacklo_epi32(A0, A1); + const __m128i B1 = _mm_unpackhi_epi32(A0, A1); + const __m128i B2 = _mm_unpacklo_epi32(A2, A3); + const __m128i B3 = _mm_unpackhi_epi32(A2, A3); + *in3 = _mm_unpacklo_epi64(B0, B2); + *in2 = _mm_unpackhi_epi64(B0, B2); + *in1 = _mm_unpacklo_epi64(B1, B3); + *in0 = _mm_unpackhi_epi64(B1, B3); +} + +#endif // WEBP_USE_SSE41 + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_DSP_COMMON_SSE41_H_ diff --git a/third-party/webp/libwebp/src/dsp/cost.c b/third-party/webp/libwebp/src/dsp/cost.c new file mode 100644 index 0000000000..73d2140177 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/cost.c @@ -0,0 +1,412 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" +#include "src/enc/cost_enc.h" + +//------------------------------------------------------------------------------ +// Boolean-cost cost table + +const uint16_t VP8EntropyCost[256] = { + 1792, 1792, 1792, 1536, 1536, 1408, 1366, 1280, 1280, 1216, + 1178, 1152, 1110, 1076, 1061, 1024, 1024, 992, 968, 951, + 939, 911, 896, 878, 871, 854, 838, 820, 811, 794, + 786, 768, 768, 752, 740, 732, 720, 709, 704, 690, + 683, 672, 666, 655, 647, 640, 631, 622, 615, 607, + 598, 592, 586, 576, 572, 564, 559, 555, 547, 541, + 534, 528, 522, 512, 512, 504, 500, 494, 488, 483, + 477, 473, 467, 461, 458, 452, 448, 443, 438, 434, + 427, 424, 419, 415, 410, 406, 403, 399, 394, 390, + 384, 384, 377, 374, 370, 366, 362, 359, 355, 351, + 347, 342, 342, 336, 333, 330, 326, 323, 320, 316, + 312, 308, 305, 302, 299, 296, 293, 288, 287, 283, + 280, 277, 274, 272, 268, 266, 262, 256, 256, 256, + 251, 248, 245, 242, 240, 237, 234, 232, 228, 226, + 223, 221, 218, 216, 214, 211, 208, 205, 203, 201, + 198, 196, 192, 191, 188, 187, 183, 181, 179, 176, + 175, 171, 171, 168, 165, 163, 160, 159, 156, 154, + 152, 150, 148, 146, 144, 142, 139, 138, 135, 133, + 131, 128, 128, 125, 123, 121, 119, 117, 115, 113, + 111, 110, 107, 105, 103, 102, 100, 98, 96, 94, + 92, 91, 89, 86, 86, 83, 82, 80, 77, 76, + 74, 73, 71, 69, 67, 66, 64, 63, 61, 59, + 57, 55, 54, 52, 51, 49, 47, 46, 44, 43, + 41, 40, 38, 36, 35, 33, 32, 30, 29, 27, + 25, 24, 22, 21, 19, 18, 16, 15, 13, 12, + 10, 9, 7, 6, 4, 3 +}; + +//------------------------------------------------------------------------------ +// Level cost tables + +// fixed costs for coding levels, deduce from the coding tree. +// This is only the part that doesn't depend on the probability state. +const uint16_t VP8LevelFixedCosts[MAX_LEVEL + 1] = { + 0, 256, 256, 256, 256, 432, 618, 630, + 731, 640, 640, 828, 901, 948, 1021, 1101, + 1174, 1221, 1294, 1042, 1085, 1115, 1158, 1202, + 1245, 1275, 1318, 1337, 1380, 1410, 1453, 1497, + 1540, 1570, 1613, 1280, 1295, 1317, 1332, 1358, + 1373, 1395, 1410, 1454, 1469, 1491, 1506, 1532, + 1547, 1569, 1584, 1601, 1616, 1638, 1653, 1679, + 1694, 1716, 1731, 1775, 1790, 1812, 1827, 1853, + 1868, 1890, 1905, 1727, 1733, 1742, 1748, 1759, + 1765, 1774, 1780, 1800, 1806, 1815, 1821, 1832, + 1838, 1847, 1853, 1878, 1884, 1893, 1899, 1910, + 1916, 1925, 1931, 1951, 1957, 1966, 1972, 1983, + 1989, 1998, 2004, 2027, 2033, 2042, 2048, 2059, + 2065, 2074, 2080, 2100, 2106, 2115, 2121, 2132, + 2138, 2147, 2153, 2178, 2184, 2193, 2199, 2210, + 2216, 2225, 2231, 2251, 2257, 2266, 2272, 2283, + 2289, 2298, 2304, 2168, 2174, 2183, 2189, 2200, + 2206, 2215, 2221, 2241, 2247, 2256, 2262, 2273, + 2279, 2288, 2294, 2319, 2325, 2334, 2340, 2351, + 2357, 2366, 2372, 2392, 2398, 2407, 2413, 2424, + 2430, 2439, 2445, 2468, 2474, 2483, 2489, 2500, + 2506, 2515, 2521, 2541, 2547, 2556, 2562, 2573, + 2579, 2588, 2594, 2619, 2625, 2634, 2640, 2651, + 2657, 2666, 2672, 2692, 2698, 2707, 2713, 2724, + 2730, 2739, 2745, 2540, 2546, 2555, 2561, 2572, + 2578, 2587, 2593, 2613, 2619, 2628, 2634, 2645, + 2651, 2660, 2666, 2691, 2697, 2706, 2712, 2723, + 2729, 2738, 2744, 2764, 2770, 2779, 2785, 2796, + 2802, 2811, 2817, 2840, 2846, 2855, 2861, 2872, + 2878, 2887, 2893, 2913, 2919, 2928, 2934, 2945, + 2951, 2960, 2966, 2991, 2997, 3006, 3012, 3023, + 3029, 3038, 3044, 3064, 3070, 3079, 3085, 3096, + 3102, 3111, 3117, 2981, 2987, 2996, 3002, 3013, + 3019, 3028, 3034, 3054, 3060, 3069, 3075, 3086, + 3092, 3101, 3107, 3132, 3138, 3147, 3153, 3164, + 3170, 3179, 3185, 3205, 3211, 3220, 3226, 3237, + 3243, 3252, 3258, 3281, 3287, 3296, 3302, 3313, + 3319, 3328, 3334, 3354, 3360, 3369, 3375, 3386, + 3392, 3401, 3407, 3432, 3438, 3447, 3453, 3464, + 3470, 3479, 3485, 3505, 3511, 3520, 3526, 3537, + 3543, 3552, 3558, 2816, 2822, 2831, 2837, 2848, + 2854, 2863, 2869, 2889, 2895, 2904, 2910, 2921, + 2927, 2936, 2942, 2967, 2973, 2982, 2988, 2999, + 3005, 3014, 3020, 3040, 3046, 3055, 3061, 3072, + 3078, 3087, 3093, 3116, 3122, 3131, 3137, 3148, + 3154, 3163, 3169, 3189, 3195, 3204, 3210, 3221, + 3227, 3236, 3242, 3267, 3273, 3282, 3288, 3299, + 3305, 3314, 3320, 3340, 3346, 3355, 3361, 3372, + 3378, 3387, 3393, 3257, 3263, 3272, 3278, 3289, + 3295, 3304, 3310, 3330, 3336, 3345, 3351, 3362, + 3368, 3377, 3383, 3408, 3414, 3423, 3429, 3440, + 3446, 3455, 3461, 3481, 3487, 3496, 3502, 3513, + 3519, 3528, 3534, 3557, 3563, 3572, 3578, 3589, + 3595, 3604, 3610, 3630, 3636, 3645, 3651, 3662, + 3668, 3677, 3683, 3708, 3714, 3723, 3729, 3740, + 3746, 3755, 3761, 3781, 3787, 3796, 3802, 3813, + 3819, 3828, 3834, 3629, 3635, 3644, 3650, 3661, + 3667, 3676, 3682, 3702, 3708, 3717, 3723, 3734, + 3740, 3749, 3755, 3780, 3786, 3795, 3801, 3812, + 3818, 3827, 3833, 3853, 3859, 3868, 3874, 3885, + 3891, 3900, 3906, 3929, 3935, 3944, 3950, 3961, + 3967, 3976, 3982, 4002, 4008, 4017, 4023, 4034, + 4040, 4049, 4055, 4080, 4086, 4095, 4101, 4112, + 4118, 4127, 4133, 4153, 4159, 4168, 4174, 4185, + 4191, 4200, 4206, 4070, 4076, 4085, 4091, 4102, + 4108, 4117, 4123, 4143, 4149, 4158, 4164, 4175, + 4181, 4190, 4196, 4221, 4227, 4236, 4242, 4253, + 4259, 4268, 4274, 4294, 4300, 4309, 4315, 4326, + 4332, 4341, 4347, 4370, 4376, 4385, 4391, 4402, + 4408, 4417, 4423, 4443, 4449, 4458, 4464, 4475, + 4481, 4490, 4496, 4521, 4527, 4536, 4542, 4553, + 4559, 4568, 4574, 4594, 4600, 4609, 4615, 4626, + 4632, 4641, 4647, 3515, 3521, 3530, 3536, 3547, + 3553, 3562, 3568, 3588, 3594, 3603, 3609, 3620, + 3626, 3635, 3641, 3666, 3672, 3681, 3687, 3698, + 3704, 3713, 3719, 3739, 3745, 3754, 3760, 3771, + 3777, 3786, 3792, 3815, 3821, 3830, 3836, 3847, + 3853, 3862, 3868, 3888, 3894, 3903, 3909, 3920, + 3926, 3935, 3941, 3966, 3972, 3981, 3987, 3998, + 4004, 4013, 4019, 4039, 4045, 4054, 4060, 4071, + 4077, 4086, 4092, 3956, 3962, 3971, 3977, 3988, + 3994, 4003, 4009, 4029, 4035, 4044, 4050, 4061, + 4067, 4076, 4082, 4107, 4113, 4122, 4128, 4139, + 4145, 4154, 4160, 4180, 4186, 4195, 4201, 4212, + 4218, 4227, 4233, 4256, 4262, 4271, 4277, 4288, + 4294, 4303, 4309, 4329, 4335, 4344, 4350, 4361, + 4367, 4376, 4382, 4407, 4413, 4422, 4428, 4439, + 4445, 4454, 4460, 4480, 4486, 4495, 4501, 4512, + 4518, 4527, 4533, 4328, 4334, 4343, 4349, 4360, + 4366, 4375, 4381, 4401, 4407, 4416, 4422, 4433, + 4439, 4448, 4454, 4479, 4485, 4494, 4500, 4511, + 4517, 4526, 4532, 4552, 4558, 4567, 4573, 4584, + 4590, 4599, 4605, 4628, 4634, 4643, 4649, 4660, + 4666, 4675, 4681, 4701, 4707, 4716, 4722, 4733, + 4739, 4748, 4754, 4779, 4785, 4794, 4800, 4811, + 4817, 4826, 4832, 4852, 4858, 4867, 4873, 4884, + 4890, 4899, 4905, 4769, 4775, 4784, 4790, 4801, + 4807, 4816, 4822, 4842, 4848, 4857, 4863, 4874, + 4880, 4889, 4895, 4920, 4926, 4935, 4941, 4952, + 4958, 4967, 4973, 4993, 4999, 5008, 5014, 5025, + 5031, 5040, 5046, 5069, 5075, 5084, 5090, 5101, + 5107, 5116, 5122, 5142, 5148, 5157, 5163, 5174, + 5180, 5189, 5195, 5220, 5226, 5235, 5241, 5252, + 5258, 5267, 5273, 5293, 5299, 5308, 5314, 5325, + 5331, 5340, 5346, 4604, 4610, 4619, 4625, 4636, + 4642, 4651, 4657, 4677, 4683, 4692, 4698, 4709, + 4715, 4724, 4730, 4755, 4761, 4770, 4776, 4787, + 4793, 4802, 4808, 4828, 4834, 4843, 4849, 4860, + 4866, 4875, 4881, 4904, 4910, 4919, 4925, 4936, + 4942, 4951, 4957, 4977, 4983, 4992, 4998, 5009, + 5015, 5024, 5030, 5055, 5061, 5070, 5076, 5087, + 5093, 5102, 5108, 5128, 5134, 5143, 5149, 5160, + 5166, 5175, 5181, 5045, 5051, 5060, 5066, 5077, + 5083, 5092, 5098, 5118, 5124, 5133, 5139, 5150, + 5156, 5165, 5171, 5196, 5202, 5211, 5217, 5228, + 5234, 5243, 5249, 5269, 5275, 5284, 5290, 5301, + 5307, 5316, 5322, 5345, 5351, 5360, 5366, 5377, + 5383, 5392, 5398, 5418, 5424, 5433, 5439, 5450, + 5456, 5465, 5471, 5496, 5502, 5511, 5517, 5528, + 5534, 5543, 5549, 5569, 5575, 5584, 5590, 5601, + 5607, 5616, 5622, 5417, 5423, 5432, 5438, 5449, + 5455, 5464, 5470, 5490, 5496, 5505, 5511, 5522, + 5528, 5537, 5543, 5568, 5574, 5583, 5589, 5600, + 5606, 5615, 5621, 5641, 5647, 5656, 5662, 5673, + 5679, 5688, 5694, 5717, 5723, 5732, 5738, 5749, + 5755, 5764, 5770, 5790, 5796, 5805, 5811, 5822, + 5828, 5837, 5843, 5868, 5874, 5883, 5889, 5900, + 5906, 5915, 5921, 5941, 5947, 5956, 5962, 5973, + 5979, 5988, 5994, 5858, 5864, 5873, 5879, 5890, + 5896, 5905, 5911, 5931, 5937, 5946, 5952, 5963, + 5969, 5978, 5984, 6009, 6015, 6024, 6030, 6041, + 6047, 6056, 6062, 6082, 6088, 6097, 6103, 6114, + 6120, 6129, 6135, 6158, 6164, 6173, 6179, 6190, + 6196, 6205, 6211, 6231, 6237, 6246, 6252, 6263, + 6269, 6278, 6284, 6309, 6315, 6324, 6330, 6341, + 6347, 6356, 6362, 6382, 6388, 6397, 6403, 6414, + 6420, 6429, 6435, 3515, 3521, 3530, 3536, 3547, + 3553, 3562, 3568, 3588, 3594, 3603, 3609, 3620, + 3626, 3635, 3641, 3666, 3672, 3681, 3687, 3698, + 3704, 3713, 3719, 3739, 3745, 3754, 3760, 3771, + 3777, 3786, 3792, 3815, 3821, 3830, 3836, 3847, + 3853, 3862, 3868, 3888, 3894, 3903, 3909, 3920, + 3926, 3935, 3941, 3966, 3972, 3981, 3987, 3998, + 4004, 4013, 4019, 4039, 4045, 4054, 4060, 4071, + 4077, 4086, 4092, 3956, 3962, 3971, 3977, 3988, + 3994, 4003, 4009, 4029, 4035, 4044, 4050, 4061, + 4067, 4076, 4082, 4107, 4113, 4122, 4128, 4139, + 4145, 4154, 4160, 4180, 4186, 4195, 4201, 4212, + 4218, 4227, 4233, 4256, 4262, 4271, 4277, 4288, + 4294, 4303, 4309, 4329, 4335, 4344, 4350, 4361, + 4367, 4376, 4382, 4407, 4413, 4422, 4428, 4439, + 4445, 4454, 4460, 4480, 4486, 4495, 4501, 4512, + 4518, 4527, 4533, 4328, 4334, 4343, 4349, 4360, + 4366, 4375, 4381, 4401, 4407, 4416, 4422, 4433, + 4439, 4448, 4454, 4479, 4485, 4494, 4500, 4511, + 4517, 4526, 4532, 4552, 4558, 4567, 4573, 4584, + 4590, 4599, 4605, 4628, 4634, 4643, 4649, 4660, + 4666, 4675, 4681, 4701, 4707, 4716, 4722, 4733, + 4739, 4748, 4754, 4779, 4785, 4794, 4800, 4811, + 4817, 4826, 4832, 4852, 4858, 4867, 4873, 4884, + 4890, 4899, 4905, 4769, 4775, 4784, 4790, 4801, + 4807, 4816, 4822, 4842, 4848, 4857, 4863, 4874, + 4880, 4889, 4895, 4920, 4926, 4935, 4941, 4952, + 4958, 4967, 4973, 4993, 4999, 5008, 5014, 5025, + 5031, 5040, 5046, 5069, 5075, 5084, 5090, 5101, + 5107, 5116, 5122, 5142, 5148, 5157, 5163, 5174, + 5180, 5189, 5195, 5220, 5226, 5235, 5241, 5252, + 5258, 5267, 5273, 5293, 5299, 5308, 5314, 5325, + 5331, 5340, 5346, 4604, 4610, 4619, 4625, 4636, + 4642, 4651, 4657, 4677, 4683, 4692, 4698, 4709, + 4715, 4724, 4730, 4755, 4761, 4770, 4776, 4787, + 4793, 4802, 4808, 4828, 4834, 4843, 4849, 4860, + 4866, 4875, 4881, 4904, 4910, 4919, 4925, 4936, + 4942, 4951, 4957, 4977, 4983, 4992, 4998, 5009, + 5015, 5024, 5030, 5055, 5061, 5070, 5076, 5087, + 5093, 5102, 5108, 5128, 5134, 5143, 5149, 5160, + 5166, 5175, 5181, 5045, 5051, 5060, 5066, 5077, + 5083, 5092, 5098, 5118, 5124, 5133, 5139, 5150, + 5156, 5165, 5171, 5196, 5202, 5211, 5217, 5228, + 5234, 5243, 5249, 5269, 5275, 5284, 5290, 5301, + 5307, 5316, 5322, 5345, 5351, 5360, 5366, 5377, + 5383, 5392, 5398, 5418, 5424, 5433, 5439, 5450, + 5456, 5465, 5471, 5496, 5502, 5511, 5517, 5528, + 5534, 5543, 5549, 5569, 5575, 5584, 5590, 5601, + 5607, 5616, 5622, 5417, 5423, 5432, 5438, 5449, + 5455, 5464, 5470, 5490, 5496, 5505, 5511, 5522, + 5528, 5537, 5543, 5568, 5574, 5583, 5589, 5600, + 5606, 5615, 5621, 5641, 5647, 5656, 5662, 5673, + 5679, 5688, 5694, 5717, 5723, 5732, 5738, 5749, + 5755, 5764, 5770, 5790, 5796, 5805, 5811, 5822, + 5828, 5837, 5843, 5868, 5874, 5883, 5889, 5900, + 5906, 5915, 5921, 5941, 5947, 5956, 5962, 5973, + 5979, 5988, 5994, 5858, 5864, 5873, 5879, 5890, + 5896, 5905, 5911, 5931, 5937, 5946, 5952, 5963, + 5969, 5978, 5984, 6009, 6015, 6024, 6030, 6041, + 6047, 6056, 6062, 6082, 6088, 6097, 6103, 6114, + 6120, 6129, 6135, 6158, 6164, 6173, 6179, 6190, + 6196, 6205, 6211, 6231, 6237, 6246, 6252, 6263, + 6269, 6278, 6284, 6309, 6315, 6324, 6330, 6341, + 6347, 6356, 6362, 6382, 6388, 6397, 6403, 6414, + 6420, 6429, 6435, 5303, 5309, 5318, 5324, 5335, + 5341, 5350, 5356, 5376, 5382, 5391, 5397, 5408, + 5414, 5423, 5429, 5454, 5460, 5469, 5475, 5486, + 5492, 5501, 5507, 5527, 5533, 5542, 5548, 5559, + 5565, 5574, 5580, 5603, 5609, 5618, 5624, 5635, + 5641, 5650, 5656, 5676, 5682, 5691, 5697, 5708, + 5714, 5723, 5729, 5754, 5760, 5769, 5775, 5786, + 5792, 5801, 5807, 5827, 5833, 5842, 5848, 5859, + 5865, 5874, 5880, 5744, 5750, 5759, 5765, 5776, + 5782, 5791, 5797, 5817, 5823, 5832, 5838, 5849, + 5855, 5864, 5870, 5895, 5901, 5910, 5916, 5927, + 5933, 5942, 5948, 5968, 5974, 5983, 5989, 6000, + 6006, 6015, 6021, 6044, 6050, 6059, 6065, 6076, + 6082, 6091, 6097, 6117, 6123, 6132, 6138, 6149, + 6155, 6164, 6170, 6195, 6201, 6210, 6216, 6227, + 6233, 6242, 6248, 6268, 6274, 6283, 6289, 6300, + 6306, 6315, 6321, 6116, 6122, 6131, 6137, 6148, + 6154, 6163, 6169, 6189, 6195, 6204, 6210, 6221, + 6227, 6236, 6242, 6267, 6273, 6282, 6288, 6299, + 6305, 6314, 6320, 6340, 6346, 6355, 6361, 6372, + 6378, 6387, 6393, 6416, 6422, 6431, 6437, 6448, + 6454, 6463, 6469, 6489, 6495, 6504, 6510, 6521, + 6527, 6536, 6542, 6567, 6573, 6582, 6588, 6599, + 6605, 6614, 6620, 6640, 6646, 6655, 6661, 6672, + 6678, 6687, 6693, 6557, 6563, 6572, 6578, 6589, + 6595, 6604, 6610, 6630, 6636, 6645, 6651, 6662, + 6668, 6677, 6683, 6708, 6714, 6723, 6729, 6740, + 6746, 6755, 6761, 6781, 6787, 6796, 6802, 6813, + 6819, 6828, 6834, 6857, 6863, 6872, 6878, 6889, + 6895, 6904, 6910, 6930, 6936, 6945, 6951, 6962, + 6968, 6977, 6983, 7008, 7014, 7023, 7029, 7040, + 7046, 7055, 7061, 7081, 7087, 7096, 7102, 7113, + 7119, 7128, 7134, 6392, 6398, 6407, 6413, 6424, + 6430, 6439, 6445, 6465, 6471, 6480, 6486, 6497, + 6503, 6512, 6518, 6543, 6549, 6558, 6564, 6575, + 6581, 6590, 6596, 6616, 6622, 6631, 6637, 6648, + 6654, 6663, 6669, 6692, 6698, 6707, 6713, 6724, + 6730, 6739, 6745, 6765, 6771, 6780, 6786, 6797, + 6803, 6812, 6818, 6843, 6849, 6858, 6864, 6875, + 6881, 6890, 6896, 6916, 6922, 6931, 6937, 6948, + 6954, 6963, 6969, 6833, 6839, 6848, 6854, 6865, + 6871, 6880, 6886, 6906, 6912, 6921, 6927, 6938, + 6944, 6953, 6959, 6984, 6990, 6999, 7005, 7016, + 7022, 7031, 7037, 7057, 7063, 7072, 7078, 7089, + 7095, 7104, 7110, 7133, 7139, 7148, 7154, 7165, + 7171, 7180, 7186, 7206, 7212, 7221, 7227, 7238, + 7244, 7253, 7259, 7284, 7290, 7299, 7305, 7316, + 7322, 7331, 7337, 7357, 7363, 7372, 7378, 7389, + 7395, 7404, 7410, 7205, 7211, 7220, 7226, 7237, + 7243, 7252, 7258, 7278, 7284, 7293, 7299, 7310, + 7316, 7325, 7331, 7356, 7362, 7371, 7377, 7388, + 7394, 7403, 7409, 7429, 7435, 7444, 7450, 7461, + 7467, 7476, 7482, 7505, 7511, 7520, 7526, 7537, + 7543, 7552, 7558, 7578, 7584, 7593, 7599, 7610, + 7616, 7625, 7631, 7656, 7662, 7671, 7677, 7688, + 7694, 7703, 7709, 7729, 7735, 7744, 7750, 7761 +}; + +//------------------------------------------------------------------------------ +// Tables for level coding + +const uint8_t VP8EncBands[16 + 1] = { + 0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, + 0 // sentinel +}; + +//------------------------------------------------------------------------------ +// Mode costs + +static int GetResidualCost_C(int ctx0, const VP8Residual* const res) { + int n = res->first; + // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 + const int p0 = res->prob[n][ctx0][0]; + CostArrayPtr const costs = res->costs; + const uint16_t* t = costs[n][ctx0]; + // bit_cost(1, p0) is already incorporated in t[] tables, but only if ctx != 0 + // (as required by the syntax). For ctx0 == 0, we need to add it here or it'll + // be missing during the loop. + int cost = (ctx0 == 0) ? VP8BitCost(1, p0) : 0; + + if (res->last < 0) { + return VP8BitCost(0, p0); + } + for (; n < res->last; ++n) { + const int v = abs(res->coeffs[n]); + const int ctx = (v >= 2) ? 2 : v; + cost += VP8LevelCost(t, v); + t = costs[n + 1][ctx]; + } + // Last coefficient is always non-zero + { + const int v = abs(res->coeffs[n]); + assert(v != 0); + cost += VP8LevelCost(t, v); + if (n < 15) { + const int b = VP8EncBands[n + 1]; + const int ctx = (v == 1) ? 1 : 2; + const int last_p0 = res->prob[b][ctx][0]; + cost += VP8BitCost(0, last_p0); + } + } + return cost; +} + +static void SetResidualCoeffs_C(const int16_t* const coeffs, + VP8Residual* const res) { + int n; + res->last = -1; + assert(res->first == 0 || coeffs[0] == 0); + for (n = 15; n >= 0; --n) { + if (coeffs[n]) { + res->last = n; + break; + } + } + res->coeffs = coeffs; +} + +//------------------------------------------------------------------------------ +// init function + +VP8GetResidualCostFunc VP8GetResidualCost; +VP8SetResidualCoeffsFunc VP8SetResidualCoeffs; + +extern VP8CPUInfo VP8GetCPUInfo; +extern void VP8EncDspCostInitMIPS32(void); +extern void VP8EncDspCostInitMIPSdspR2(void); +extern void VP8EncDspCostInitSSE2(void); +extern void VP8EncDspCostInitNEON(void); + +WEBP_DSP_INIT_FUNC(VP8EncDspCostInit) { + VP8GetResidualCost = GetResidualCost_C; + VP8SetResidualCoeffs = SetResidualCoeffs_C; + + // If defined, use CPUInfo() to overwrite some pointers with faster versions. + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_USE_MIPS32) + if (VP8GetCPUInfo(kMIPS32)) { + VP8EncDspCostInitMIPS32(); + } +#endif +#if defined(WEBP_USE_MIPS_DSP_R2) + if (VP8GetCPUInfo(kMIPSdspR2)) { + VP8EncDspCostInitMIPSdspR2(); + } +#endif +#if defined(WEBP_HAVE_SSE2) + if (VP8GetCPUInfo(kSSE2)) { + VP8EncDspCostInitSSE2(); + } +#endif +#if defined(WEBP_HAVE_NEON) + if (VP8GetCPUInfo(kNEON)) { + VP8EncDspCostInitNEON(); + } +#endif + } +} + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/src/dsp/cost_mips32.c b/third-party/webp/libwebp/src/dsp/cost_mips32.c new file mode 100644 index 0000000000..0500f88c13 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/cost_mips32.c @@ -0,0 +1,154 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Djordje Pesut (djordje.pesut@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MIPS32) + +#include "src/enc/cost_enc.h" + +static int GetResidualCost_MIPS32(int ctx0, const VP8Residual* const res) { + int temp0, temp1; + int v_reg, ctx_reg; + int n = res->first; + // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 + int p0 = res->prob[n][ctx0][0]; + CostArrayPtr const costs = res->costs; + const uint16_t* t = costs[n][ctx0]; + // bit_cost(1, p0) is already incorporated in t[] tables, but only if ctx != 0 + // (as required by the syntax). For ctx0 == 0, we need to add it here or it'll + // be missing during the loop. + int cost = (ctx0 == 0) ? VP8BitCost(1, p0) : 0; + const int16_t* res_coeffs = res->coeffs; + const int res_last = res->last; + const int const_max_level = MAX_VARIABLE_LEVEL; + const int const_2 = 2; + const uint16_t** p_costs = &costs[n][0]; + const size_t inc_p_costs = NUM_CTX * sizeof(*p_costs); + + if (res->last < 0) { + return VP8BitCost(0, p0); + } + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "subu %[temp1], %[res_last], %[n] \n\t" + "sll %[temp0], %[n], 1 \n\t" + "blez %[temp1], 2f \n\t" + " addu %[res_coeffs], %[res_coeffs], %[temp0] \n\t" + "1: \n\t" + "lh %[v_reg], 0(%[res_coeffs]) \n\t" + "addiu %[n], %[n], 1 \n\t" + "negu %[temp0], %[v_reg] \n\t" + "slti %[temp1], %[v_reg], 0 \n\t" + "movn %[v_reg], %[temp0], %[temp1] \n\t" + "sltiu %[temp0], %[v_reg], 2 \n\t" + "move %[ctx_reg], %[v_reg] \n\t" + "movz %[ctx_reg], %[const_2], %[temp0] \n\t" + "sll %[temp1], %[v_reg], 1 \n\t" + "addu %[temp1], %[temp1], %[VP8LevelFixedCosts] \n\t" + "lhu %[temp1], 0(%[temp1]) \n\t" + "slt %[temp0], %[v_reg], %[const_max_level] \n\t" + "movz %[v_reg], %[const_max_level], %[temp0] \n\t" + "addu %[cost], %[cost], %[temp1] \n\t" + "sll %[v_reg], %[v_reg], 1 \n\t" + "sll %[ctx_reg], %[ctx_reg], 2 \n\t" + "addu %[v_reg], %[v_reg], %[t] \n\t" + "lhu %[temp0], 0(%[v_reg]) \n\t" + "addu %[p_costs], %[p_costs], %[inc_p_costs] \n\t" + "addu %[t], %[p_costs], %[ctx_reg] \n\t" + "addu %[cost], %[cost], %[temp0] \n\t" + "addiu %[res_coeffs], %[res_coeffs], 2 \n\t" + "bne %[n], %[res_last], 1b \n\t" + " lw %[t], 0(%[t]) \n\t" + "2: \n\t" + ".set pop \n\t" + : [cost]"+&r"(cost), [t]"+&r"(t), [n]"+&r"(n), [v_reg]"=&r"(v_reg), + [ctx_reg]"=&r"(ctx_reg), [p_costs]"+&r"(p_costs), [temp0]"=&r"(temp0), + [temp1]"=&r"(temp1), [res_coeffs]"+&r"(res_coeffs) + : [const_2]"r"(const_2), [const_max_level]"r"(const_max_level), + [VP8LevelFixedCosts]"r"(VP8LevelFixedCosts), [res_last]"r"(res_last), + [inc_p_costs]"r"(inc_p_costs) + : "memory" + ); + + // Last coefficient is always non-zero + { + const int v = abs(res->coeffs[n]); + assert(v != 0); + cost += VP8LevelCost(t, v); + if (n < 15) { + const int b = VP8EncBands[n + 1]; + const int ctx = (v == 1) ? 1 : 2; + const int last_p0 = res->prob[b][ctx][0]; + cost += VP8BitCost(0, last_p0); + } + } + return cost; +} + +static void SetResidualCoeffs_MIPS32(const int16_t* const coeffs, + VP8Residual* const res) { + const int16_t* p_coeffs = (int16_t*)coeffs; + int temp0, temp1, temp2, n, n1; + assert(res->first == 0 || coeffs[0] == 0); + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "addiu %[p_coeffs], %[p_coeffs], 28 \n\t" + "li %[n], 15 \n\t" + "li %[temp2], -1 \n\t" + "0: \n\t" + "ulw %[temp0], 0(%[p_coeffs]) \n\t" + "beqz %[temp0], 1f \n\t" +#if defined(WORDS_BIGENDIAN) + " sll %[temp1], %[temp0], 16 \n\t" +#else + " srl %[temp1], %[temp0], 16 \n\t" +#endif + "addiu %[n1], %[n], -1 \n\t" + "movz %[temp0], %[n1], %[temp1] \n\t" + "movn %[temp0], %[n], %[temp1] \n\t" + "j 2f \n\t" + " addiu %[temp2], %[temp0], 0 \n\t" + "1: \n\t" + "addiu %[n], %[n], -2 \n\t" + "bgtz %[n], 0b \n\t" + " addiu %[p_coeffs], %[p_coeffs], -4 \n\t" + "2: \n\t" + ".set pop \n\t" + : [p_coeffs]"+&r"(p_coeffs), [temp0]"=&r"(temp0), + [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [n]"=&r"(n), [n1]"=&r"(n1) + : + : "memory" + ); + res->last = temp2; + res->coeffs = coeffs; +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8EncDspCostInitMIPS32(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInitMIPS32(void) { + VP8GetResidualCost = GetResidualCost_MIPS32; + VP8SetResidualCoeffs = SetResidualCoeffs_MIPS32; +} + +#else // !WEBP_USE_MIPS32 + +WEBP_DSP_INIT_STUB(VP8EncDspCostInitMIPS32) + +#endif // WEBP_USE_MIPS32 diff --git a/third-party/webp/libwebp/src/dsp/cost_mips_dsp_r2.c b/third-party/webp/libwebp/src/dsp/cost_mips_dsp_r2.c new file mode 100644 index 0000000000..51248de7a1 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/cost_mips_dsp_r2.c @@ -0,0 +1,107 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Djordje Pesut (djordje.pesut@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MIPS_DSP_R2) + +#include "src/enc/cost_enc.h" + +static int GetResidualCost_MIPSdspR2(int ctx0, const VP8Residual* const res) { + int temp0, temp1; + int v_reg, ctx_reg; + int n = res->first; + // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 + int p0 = res->prob[n][ctx0][0]; + CostArrayPtr const costs = res->costs; + const uint16_t* t = costs[n][ctx0]; + // bit_cost(1, p0) is already incorporated in t[] tables, but only if ctx != 0 + // (as required by the syntax). For ctx0 == 0, we need to add it here or it'll + // be missing during the loop. + int cost = (ctx0 == 0) ? VP8BitCost(1, p0) : 0; + const int16_t* res_coeffs = res->coeffs; + const int res_last = res->last; + const int const_max_level = MAX_VARIABLE_LEVEL; + const int const_2 = 2; + const uint16_t** p_costs = &costs[n][0]; + const size_t inc_p_costs = NUM_CTX * sizeof(*p_costs); + + if (res->last < 0) { + return VP8BitCost(0, p0); + } + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "subu %[temp1], %[res_last], %[n] \n\t" + "blez %[temp1], 2f \n\t" + " nop \n\t" + "1: \n\t" + "sll %[temp0], %[n], 1 \n\t" + "lhx %[v_reg], %[temp0](%[res_coeffs]) \n\t" + "addiu %[n], %[n], 1 \n\t" + "absq_s.w %[v_reg], %[v_reg] \n\t" + "sltiu %[temp0], %[v_reg], 2 \n\t" + "move %[ctx_reg], %[v_reg] \n\t" + "movz %[ctx_reg], %[const_2], %[temp0] \n\t" + "sll %[temp1], %[v_reg], 1 \n\t" + "lhx %[temp1], %[temp1](%[VP8LevelFixedCosts]) \n\t" + "slt %[temp0], %[v_reg], %[const_max_level] \n\t" + "movz %[v_reg], %[const_max_level], %[temp0] \n\t" + "addu %[cost], %[cost], %[temp1] \n\t" + "sll %[v_reg], %[v_reg], 1 \n\t" + "sll %[ctx_reg], %[ctx_reg], 2 \n\t" + "lhx %[temp0], %[v_reg](%[t]) \n\t" + "addu %[p_costs], %[p_costs], %[inc_p_costs] \n\t" + "addu %[t], %[p_costs], %[ctx_reg] \n\t" + "addu %[cost], %[cost], %[temp0] \n\t" + "bne %[n], %[res_last], 1b \n\t" + " lw %[t], 0(%[t]) \n\t" + "2: \n\t" + ".set pop \n\t" + : [cost]"+&r"(cost), [t]"+&r"(t), [n]"+&r"(n), [v_reg]"=&r"(v_reg), + [ctx_reg]"=&r"(ctx_reg), [p_costs]"+&r"(p_costs), [temp0]"=&r"(temp0), + [temp1]"=&r"(temp1) + : [const_2]"r"(const_2), [const_max_level]"r"(const_max_level), + [VP8LevelFixedCosts]"r"(VP8LevelFixedCosts), [res_last]"r"(res_last), + [res_coeffs]"r"(res_coeffs), [inc_p_costs]"r"(inc_p_costs) + : "memory" + ); + + // Last coefficient is always non-zero + { + const int v = abs(res->coeffs[n]); + assert(v != 0); + cost += VP8LevelCost(t, v); + if (n < 15) { + const int b = VP8EncBands[n + 1]; + const int ctx = (v == 1) ? 1 : 2; + const int last_p0 = res->prob[b][ctx][0]; + cost += VP8BitCost(0, last_p0); + } + } + return cost; +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8EncDspCostInitMIPSdspR2(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInitMIPSdspR2(void) { + VP8GetResidualCost = GetResidualCost_MIPSdspR2; +} + +#else // !WEBP_USE_MIPS_DSP_R2 + +WEBP_DSP_INIT_STUB(VP8EncDspCostInitMIPSdspR2) + +#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/third-party/webp/libwebp/src/dsp/cost_neon.c b/third-party/webp/libwebp/src/dsp/cost_neon.c new file mode 100644 index 0000000000..6582669cb3 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/cost_neon.c @@ -0,0 +1,122 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// ARM NEON version of cost functions + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_NEON) + +#include "src/dsp/neon.h" +#include "src/enc/cost_enc.h" + +static const uint8_t position[16] = { 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16 }; + +static void SetResidualCoeffs_NEON(const int16_t* const coeffs, + VP8Residual* const res) { + const int16x8_t minus_one = vdupq_n_s16(-1); + const int16x8_t coeffs_0 = vld1q_s16(coeffs); + const int16x8_t coeffs_1 = vld1q_s16(coeffs + 8); + const uint16x8_t eob_0 = vtstq_s16(coeffs_0, minus_one); + const uint16x8_t eob_1 = vtstq_s16(coeffs_1, minus_one); + const uint8x16_t eob = vcombine_u8(vqmovn_u16(eob_0), vqmovn_u16(eob_1)); + const uint8x16_t masked = vandq_u8(eob, vld1q_u8(position)); + +#if WEBP_AARCH64 + res->last = vmaxvq_u8(masked) - 1; +#else + const uint8x8_t eob_8x8 = vmax_u8(vget_low_u8(masked), vget_high_u8(masked)); + const uint16x8_t eob_16x8 = vmovl_u8(eob_8x8); + const uint16x4_t eob_16x4 = + vmax_u16(vget_low_u16(eob_16x8), vget_high_u16(eob_16x8)); + const uint32x4_t eob_32x4 = vmovl_u16(eob_16x4); + uint32x2_t eob_32x2 = + vmax_u32(vget_low_u32(eob_32x4), vget_high_u32(eob_32x4)); + eob_32x2 = vpmax_u32(eob_32x2, eob_32x2); + + vst1_lane_s32(&res->last, vreinterpret_s32_u32(eob_32x2), 0); + --res->last; +#endif // WEBP_AARCH64 + + res->coeffs = coeffs; +} + +static int GetResidualCost_NEON(int ctx0, const VP8Residual* const res) { + uint8_t levels[16], ctxs[16]; + uint16_t abs_levels[16]; + int n = res->first; + // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 + const int p0 = res->prob[n][ctx0][0]; + CostArrayPtr const costs = res->costs; + const uint16_t* t = costs[n][ctx0]; + // bit_cost(1, p0) is already incorporated in t[] tables, but only if ctx != 0 + // (as required by the syntax). For ctx0 == 0, we need to add it here or it'll + // be missing during the loop. + int cost = (ctx0 == 0) ? VP8BitCost(1, p0) : 0; + + if (res->last < 0) { + return VP8BitCost(0, p0); + } + + { // precompute clamped levels and contexts, packed to 8b. + const uint8x16_t kCst2 = vdupq_n_u8(2); + const uint8x16_t kCst67 = vdupq_n_u8(MAX_VARIABLE_LEVEL); + const int16x8_t c0 = vld1q_s16(res->coeffs); + const int16x8_t c1 = vld1q_s16(res->coeffs + 8); + const uint16x8_t E0 = vreinterpretq_u16_s16(vabsq_s16(c0)); + const uint16x8_t E1 = vreinterpretq_u16_s16(vabsq_s16(c1)); + const uint8x16_t F = vcombine_u8(vqmovn_u16(E0), vqmovn_u16(E1)); + const uint8x16_t G = vminq_u8(F, kCst2); // context = 0,1,2 + const uint8x16_t H = vminq_u8(F, kCst67); // clamp_level in [0..67] + + vst1q_u8(ctxs, G); + vst1q_u8(levels, H); + + vst1q_u16(abs_levels, E0); + vst1q_u16(abs_levels + 8, E1); + } + for (; n < res->last; ++n) { + const int ctx = ctxs[n]; + const int level = levels[n]; + const int flevel = abs_levels[n]; // full level + cost += VP8LevelFixedCosts[flevel] + t[level]; // simplified VP8LevelCost() + t = costs[n + 1][ctx]; + } + // Last coefficient is always non-zero + { + const int level = levels[n]; + const int flevel = abs_levels[n]; + assert(flevel != 0); + cost += VP8LevelFixedCosts[flevel] + t[level]; + if (n < 15) { + const int b = VP8EncBands[n + 1]; + const int ctx = ctxs[n]; + const int last_p0 = res->prob[b][ctx][0]; + cost += VP8BitCost(0, last_p0); + } + } + return cost; +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8EncDspCostInitNEON(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInitNEON(void) { + VP8SetResidualCoeffs = SetResidualCoeffs_NEON; + VP8GetResidualCost = GetResidualCost_NEON; +} + +#else // !WEBP_USE_NEON + +WEBP_DSP_INIT_STUB(VP8EncDspCostInitNEON) + +#endif // WEBP_USE_NEON diff --git a/third-party/webp/libwebp/src/dsp/cost_sse2.c b/third-party/webp/libwebp/src/dsp/cost_sse2.c new file mode 100644 index 0000000000..487a079921 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/cost_sse2.c @@ -0,0 +1,119 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE2 version of cost functions +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE2) +#include + +#include "src/enc/cost_enc.h" +#include "src/enc/vp8i_enc.h" +#include "src/utils/utils.h" + +//------------------------------------------------------------------------------ + +static void SetResidualCoeffs_SSE2(const int16_t* const coeffs, + VP8Residual* const res) { + const __m128i c0 = _mm_loadu_si128((const __m128i*)(coeffs + 0)); + const __m128i c1 = _mm_loadu_si128((const __m128i*)(coeffs + 8)); + // Use SSE2 to compare 16 values with a single instruction. + const __m128i zero = _mm_setzero_si128(); + const __m128i m0 = _mm_packs_epi16(c0, c1); + const __m128i m1 = _mm_cmpeq_epi8(m0, zero); + // Get the comparison results as a bitmask into 16bits. Negate the mask to get + // the position of entries that are not equal to zero. We don't need to mask + // out least significant bits according to res->first, since coeffs[0] is 0 + // if res->first > 0. + const uint32_t mask = 0x0000ffffu ^ (uint32_t)_mm_movemask_epi8(m1); + // The position of the most significant non-zero bit indicates the position of + // the last non-zero value. + assert(res->first == 0 || coeffs[0] == 0); + res->last = mask ? BitsLog2Floor(mask) : -1; + res->coeffs = coeffs; +} + +static int GetResidualCost_SSE2(int ctx0, const VP8Residual* const res) { + uint8_t levels[16], ctxs[16]; + uint16_t abs_levels[16]; + int n = res->first; + // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 + const int p0 = res->prob[n][ctx0][0]; + CostArrayPtr const costs = res->costs; + const uint16_t* t = costs[n][ctx0]; + // bit_cost(1, p0) is already incorporated in t[] tables, but only if ctx != 0 + // (as required by the syntax). For ctx0 == 0, we need to add it here or it'll + // be missing during the loop. + int cost = (ctx0 == 0) ? VP8BitCost(1, p0) : 0; + + if (res->last < 0) { + return VP8BitCost(0, p0); + } + + { // precompute clamped levels and contexts, packed to 8b. + const __m128i zero = _mm_setzero_si128(); + const __m128i kCst2 = _mm_set1_epi8(2); + const __m128i kCst67 = _mm_set1_epi8(MAX_VARIABLE_LEVEL); + const __m128i c0 = _mm_loadu_si128((const __m128i*)&res->coeffs[0]); + const __m128i c1 = _mm_loadu_si128((const __m128i*)&res->coeffs[8]); + const __m128i D0 = _mm_sub_epi16(zero, c0); + const __m128i D1 = _mm_sub_epi16(zero, c1); + const __m128i E0 = _mm_max_epi16(c0, D0); // abs(v), 16b + const __m128i E1 = _mm_max_epi16(c1, D1); + const __m128i F = _mm_packs_epi16(E0, E1); + const __m128i G = _mm_min_epu8(F, kCst2); // context = 0,1,2 + const __m128i H = _mm_min_epu8(F, kCst67); // clamp_level in [0..67] + + _mm_storeu_si128((__m128i*)&ctxs[0], G); + _mm_storeu_si128((__m128i*)&levels[0], H); + + _mm_storeu_si128((__m128i*)&abs_levels[0], E0); + _mm_storeu_si128((__m128i*)&abs_levels[8], E1); + } + for (; n < res->last; ++n) { + const int ctx = ctxs[n]; + const int level = levels[n]; + const int flevel = abs_levels[n]; // full level + cost += VP8LevelFixedCosts[flevel] + t[level]; // simplified VP8LevelCost() + t = costs[n + 1][ctx]; + } + // Last coefficient is always non-zero + { + const int level = levels[n]; + const int flevel = abs_levels[n]; + assert(flevel != 0); + cost += VP8LevelFixedCosts[flevel] + t[level]; + if (n < 15) { + const int b = VP8EncBands[n + 1]; + const int ctx = ctxs[n]; + const int last_p0 = res->prob[b][ctx][0]; + cost += VP8BitCost(0, last_p0); + } + } + return cost; +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8EncDspCostInitSSE2(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInitSSE2(void) { + VP8SetResidualCoeffs = SetResidualCoeffs_SSE2; + VP8GetResidualCost = GetResidualCost_SSE2; +} + +#else // !WEBP_USE_SSE2 + +WEBP_DSP_INIT_STUB(VP8EncDspCostInitSSE2) + +#endif // WEBP_USE_SSE2 diff --git a/third-party/webp/libwebp/src/dsp/cpu.c b/third-party/webp/libwebp/src/dsp/cpu.c new file mode 100644 index 0000000000..2234c77b35 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/cpu.c @@ -0,0 +1,259 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// CPU detection +// +// Author: Christian Duvivier (cduvivier@google.com) + +#include "src/dsp/cpu.h" + +#if defined(WEBP_HAVE_NEON_RTCD) +#include +#include +#endif + +#if defined(WEBP_ANDROID_NEON) +#include +#endif + +//------------------------------------------------------------------------------ +// SSE2 detection. +// + +// apple/darwin gcc-4.0.1 defines __PIC__, but not __pic__ with -fPIC. +#if (defined(__pic__) || defined(__PIC__)) && defined(__i386__) +static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) { + __asm__ volatile ( + "mov %%ebx, %%edi\n" + "cpuid\n" + "xchg %%edi, %%ebx\n" + : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3]) + : "a"(info_type), "c"(0)); +} +#elif defined(__x86_64__) && \ + (defined(__code_model_medium__) || defined(__code_model_large__)) && \ + defined(__PIC__) +static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) { + __asm__ volatile ( + "xchg{q}\t{%%rbx}, %q1\n" + "cpuid\n" + "xchg{q}\t{%%rbx}, %q1\n" + : "=a"(cpu_info[0]), "=&r"(cpu_info[1]), "=c"(cpu_info[2]), + "=d"(cpu_info[3]) + : "a"(info_type), "c"(0)); +} +#elif defined(__i386__) || defined(__x86_64__) +static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) { + __asm__ volatile ( + "cpuid\n" + : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3]) + : "a"(info_type), "c"(0)); +} +#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86)) + +#if defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 150030729 // >= VS2008 SP1 +#include +#define GetCPUInfo(info, type) __cpuidex(info, type, 0) // set ecx=0 +#define WEBP_HAVE_MSC_CPUID +#elif _MSC_VER > 1310 +#include +#define GetCPUInfo __cpuid +#define WEBP_HAVE_MSC_CPUID +#endif + +#endif + +// NaCl has no support for xgetbv or the raw opcode. +#if !defined(__native_client__) && (defined(__i386__) || defined(__x86_64__)) +static WEBP_INLINE uint64_t xgetbv(void) { + const uint32_t ecx = 0; + uint32_t eax, edx; + // Use the raw opcode for xgetbv for compatibility with older toolchains. + __asm__ volatile ( + ".byte 0x0f, 0x01, 0xd0\n" + : "=a"(eax), "=d"(edx) : "c" (ecx)); + return ((uint64_t)edx << 32) | eax; +} +#elif (defined(_M_X64) || defined(_M_IX86)) && \ + defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 160040219 // >= VS2010 SP1 +#include +#define xgetbv() _xgetbv(0) +#elif defined(_MSC_VER) && defined(_M_IX86) +static WEBP_INLINE uint64_t xgetbv(void) { + uint32_t eax_, edx_; + __asm { + xor ecx, ecx // ecx = 0 + // Use the raw opcode for xgetbv for compatibility with older toolchains. + __asm _emit 0x0f __asm _emit 0x01 __asm _emit 0xd0 + mov eax_, eax + mov edx_, edx + } + return ((uint64_t)edx_ << 32) | eax_; +} +#else +#define xgetbv() 0U // no AVX for older x64 or unrecognized toolchains. +#endif + +#if defined(__i386__) || defined(__x86_64__) || defined(WEBP_HAVE_MSC_CPUID) + +// helper function for run-time detection of slow SSSE3 platforms +static int CheckSlowModel(int info) { + // Table listing display models with longer latencies for the bsr instruction + // (ie 2 cycles vs 10/16 cycles) and some SSSE3 instructions like pshufb. + // Refer to Intel 64 and IA-32 Architectures Optimization Reference Manual. + static const uint8_t kSlowModels[] = { + 0x37, 0x4a, 0x4d, // Silvermont Microarchitecture + 0x1c, 0x26, 0x27 // Atom Microarchitecture + }; + const uint32_t model = ((info & 0xf0000) >> 12) | ((info >> 4) & 0xf); + const uint32_t family = (info >> 8) & 0xf; + if (family == 0x06) { + size_t i; + for (i = 0; i < sizeof(kSlowModels) / sizeof(kSlowModels[0]); ++i) { + if (model == kSlowModels[i]) return 1; + } + } + return 0; +} + +static int x86CPUInfo(CPUFeature feature) { + int max_cpuid_value; + int cpu_info[4]; + int is_intel = 0; + + // get the highest feature value cpuid supports + GetCPUInfo(cpu_info, 0); + max_cpuid_value = cpu_info[0]; + if (max_cpuid_value < 1) { + return 0; + } else { + const int VENDOR_ID_INTEL_EBX = 0x756e6547; // uneG + const int VENDOR_ID_INTEL_EDX = 0x49656e69; // Ieni + const int VENDOR_ID_INTEL_ECX = 0x6c65746e; // letn + is_intel = (cpu_info[1] == VENDOR_ID_INTEL_EBX && + cpu_info[2] == VENDOR_ID_INTEL_ECX && + cpu_info[3] == VENDOR_ID_INTEL_EDX); // genuine Intel? + } + + GetCPUInfo(cpu_info, 1); + if (feature == kSSE2) { + return !!(cpu_info[3] & (1 << 26)); + } + if (feature == kSSE3) { + return !!(cpu_info[2] & (1 << 0)); + } + if (feature == kSlowSSSE3) { + if (is_intel && (cpu_info[2] & (1 << 9))) { // SSSE3? + return CheckSlowModel(cpu_info[0]); + } + return 0; + } + + if (feature == kSSE4_1) { + return !!(cpu_info[2] & (1 << 19)); + } + if (feature == kAVX) { + // bits 27 (OSXSAVE) & 28 (256-bit AVX) + if ((cpu_info[2] & 0x18000000) == 0x18000000) { + // XMM state and YMM state enabled by the OS. + return (xgetbv() & 0x6) == 0x6; + } + } + if (feature == kAVX2) { + if (x86CPUInfo(kAVX) && max_cpuid_value >= 7) { + GetCPUInfo(cpu_info, 7); + return !!(cpu_info[1] & (1 << 5)); + } + } + return 0; +} +WEBP_EXTERN VP8CPUInfo VP8GetCPUInfo; +VP8CPUInfo VP8GetCPUInfo = x86CPUInfo; +#elif defined(WEBP_ANDROID_NEON) // NB: needs to be before generic NEON test. +static int AndroidCPUInfo(CPUFeature feature) { + const AndroidCpuFamily cpu_family = android_getCpuFamily(); + const uint64_t cpu_features = android_getCpuFeatures(); + if (feature == kNEON) { + return cpu_family == ANDROID_CPU_FAMILY_ARM && + (cpu_features & ANDROID_CPU_ARM_FEATURE_NEON) != 0; + } + return 0; +} +WEBP_EXTERN VP8CPUInfo VP8GetCPUInfo; +VP8CPUInfo VP8GetCPUInfo = AndroidCPUInfo; +#elif defined(EMSCRIPTEN) // also needs to be before generic NEON test +// Use compile flags as an indicator of SIMD support instead of a runtime check. +static int wasmCPUInfo(CPUFeature feature) { + switch (feature) { +#ifdef WEBP_HAVE_SSE2 + case kSSE2: + return 1; +#endif +#ifdef WEBP_HAVE_SSE41 + case kSSE3: + case kSlowSSSE3: + case kSSE4_1: + return 1; +#endif +#ifdef WEBP_HAVE_NEON + case kNEON: + return 1; +#endif + default: + break; + } + return 0; +} +WEBP_EXTERN VP8CPUInfo VP8GetCPUInfo; +VP8CPUInfo VP8GetCPUInfo = wasmCPUInfo; +#elif defined(WEBP_HAVE_NEON) +// In most cases this function doesn't check for NEON support (it's assumed by +// the configuration), but enables turning off NEON at runtime, for testing +// purposes, by setting VP8GetCPUInfo = NULL. +static int armCPUInfo(CPUFeature feature) { + if (feature != kNEON) return 0; +#if defined(__linux__) && defined(WEBP_HAVE_NEON_RTCD) + { + int has_neon = 0; + char line[200]; + FILE* const cpuinfo = fopen("/proc/cpuinfo", "r"); + if (cpuinfo == NULL) return 0; + while (fgets(line, sizeof(line), cpuinfo)) { + if (!strncmp(line, "Features", 8)) { + if (strstr(line, " neon ") != NULL) { + has_neon = 1; + break; + } + } + } + fclose(cpuinfo); + return has_neon; + } +#else + return 1; +#endif +} +WEBP_EXTERN VP8CPUInfo VP8GetCPUInfo; +VP8CPUInfo VP8GetCPUInfo = armCPUInfo; +#elif defined(WEBP_USE_MIPS32) || defined(WEBP_USE_MIPS_DSP_R2) || \ + defined(WEBP_USE_MSA) +static int mipsCPUInfo(CPUFeature feature) { + if ((feature == kMIPS32) || (feature == kMIPSdspR2) || (feature == kMSA)) { + return 1; + } else { + return 0; + } + +} +WEBP_EXTERN VP8CPUInfo VP8GetCPUInfo; +VP8CPUInfo VP8GetCPUInfo = mipsCPUInfo; +#else +WEBP_EXTERN VP8CPUInfo VP8GetCPUInfo; +VP8CPUInfo VP8GetCPUInfo = NULL; +#endif diff --git a/third-party/webp/libwebp/src/dsp/cpu.h b/third-party/webp/libwebp/src/dsp/cpu.h new file mode 100644 index 0000000000..c86540f280 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/cpu.h @@ -0,0 +1,266 @@ +// Copyright 2022 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// CPU detection functions and macros. +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_DSP_CPU_H_ +#define WEBP_DSP_CPU_H_ + +#include + +#ifdef HAVE_CONFIG_H +#include "src/webp/config.h" +#endif + +#include "src/webp/types.h" + +#if defined(__GNUC__) +#define LOCAL_GCC_VERSION ((__GNUC__ << 8) | __GNUC_MINOR__) +#define LOCAL_GCC_PREREQ(maj, min) (LOCAL_GCC_VERSION >= (((maj) << 8) | (min))) +#else +#define LOCAL_GCC_VERSION 0 +#define LOCAL_GCC_PREREQ(maj, min) 0 +#endif + +#if defined(__clang__) +#define LOCAL_CLANG_VERSION ((__clang_major__ << 8) | __clang_minor__) +#define LOCAL_CLANG_PREREQ(maj, min) \ + (LOCAL_CLANG_VERSION >= (((maj) << 8) | (min))) +#else +#define LOCAL_CLANG_VERSION 0 +#define LOCAL_CLANG_PREREQ(maj, min) 0 +#endif + +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif + +//------------------------------------------------------------------------------ +// x86 defines. + +#if !defined(HAVE_CONFIG_H) +#if defined(_MSC_VER) && _MSC_VER > 1310 && \ + (defined(_M_X64) || defined(_M_IX86)) +#define WEBP_MSC_SSE2 // Visual C++ SSE2 targets +#endif + +#if defined(_MSC_VER) && _MSC_VER >= 1500 && \ + (defined(_M_X64) || defined(_M_IX86)) +#define WEBP_MSC_SSE41 // Visual C++ SSE4.1 targets +#endif +#endif + +// WEBP_HAVE_* are used to indicate the presence of the instruction set in dsp +// files without intrinsics, allowing the corresponding Init() to be called. +// Files containing intrinsics will need to be built targeting the instruction +// set so should succeed on one of the earlier tests. +#if (defined(__SSE2__) || defined(WEBP_MSC_SSE2)) && \ + (!defined(HAVE_CONFIG_H) || defined(WEBP_HAVE_SSE2)) +#define WEBP_USE_SSE2 +#endif + +#if defined(WEBP_USE_SSE2) && !defined(WEBP_HAVE_SSE2) +#define WEBP_HAVE_SSE2 +#endif + +#if (defined(__SSE4_1__) || defined(WEBP_MSC_SSE41)) && \ + (!defined(HAVE_CONFIG_H) || defined(WEBP_HAVE_SSE41)) +#define WEBP_USE_SSE41 +#endif + +#if defined(WEBP_USE_SSE41) && !defined(WEBP_HAVE_SSE41) +#define WEBP_HAVE_SSE41 +#endif + +#undef WEBP_MSC_SSE41 +#undef WEBP_MSC_SSE2 + +//------------------------------------------------------------------------------ +// Arm defines. + +// The intrinsics currently cause compiler errors with arm-nacl-gcc and the +// inline assembly would need to be modified for use with Native Client. +#if ((defined(__ARM_NEON__) || defined(__aarch64__)) && \ + (!defined(HAVE_CONFIG_H) || defined(WEBP_HAVE_NEON))) && \ + !defined(__native_client__) +#define WEBP_USE_NEON +#endif + +#if !defined(WEBP_USE_NEON) && defined(__ANDROID__) && \ + defined(__ARM_ARCH_7A__) && defined(HAVE_CPU_FEATURES_H) +#define WEBP_ANDROID_NEON // Android targets that may have NEON +#define WEBP_USE_NEON +#endif + +// Note: ARM64 is supported in Visual Studio 2017, but requires the direct +// inclusion of arm64_neon.h; Visual Studio 2019 includes this file in +// arm_neon.h. Compile errors were seen with Visual Studio 2019 16.4 with +// vtbl4_u8(); a fix was made in 16.6. +#if defined(_MSC_VER) && \ + ((_MSC_VER >= 1700 && defined(_M_ARM)) || \ + (_MSC_VER >= 1926 && (defined(_M_ARM64) || defined(_M_ARM64EC)))) +#define WEBP_USE_NEON +#define WEBP_USE_INTRINSICS +#endif + +#if defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC) +#define WEBP_AARCH64 1 +#else +#define WEBP_AARCH64 0 +#endif + +#if defined(WEBP_USE_NEON) && !defined(WEBP_HAVE_NEON) +#define WEBP_HAVE_NEON +#endif + +//------------------------------------------------------------------------------ +// MIPS defines. + +#if defined(__mips__) && !defined(__mips64) && defined(__mips_isa_rev) && \ + (__mips_isa_rev >= 1) && (__mips_isa_rev < 6) +#define WEBP_USE_MIPS32 +#if (__mips_isa_rev >= 2) +#define WEBP_USE_MIPS32_R2 +#if defined(__mips_dspr2) || (defined(__mips_dsp_rev) && __mips_dsp_rev >= 2) +#define WEBP_USE_MIPS_DSP_R2 +#endif +#endif +#endif + +#if defined(__mips_msa) && defined(__mips_isa_rev) && (__mips_isa_rev >= 5) +#define WEBP_USE_MSA +#endif + +//------------------------------------------------------------------------------ + +#ifndef WEBP_DSP_OMIT_C_CODE +#define WEBP_DSP_OMIT_C_CODE 1 +#endif + +#if defined(WEBP_USE_NEON) && WEBP_DSP_OMIT_C_CODE +#define WEBP_NEON_OMIT_C_CODE 1 +#else +#define WEBP_NEON_OMIT_C_CODE 0 +#endif + +#if !(LOCAL_CLANG_PREREQ(3, 8) || LOCAL_GCC_PREREQ(4, 8) || WEBP_AARCH64) +#define WEBP_NEON_WORK_AROUND_GCC 1 +#else +#define WEBP_NEON_WORK_AROUND_GCC 0 +#endif + +//------------------------------------------------------------------------------ + +// This macro prevents thread_sanitizer from reporting known concurrent writes. +#define WEBP_TSAN_IGNORE_FUNCTION +#if defined(__has_feature) +#if __has_feature(thread_sanitizer) +#undef WEBP_TSAN_IGNORE_FUNCTION +#define WEBP_TSAN_IGNORE_FUNCTION __attribute__((no_sanitize_thread)) +#endif +#endif + +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +#define WEBP_MSAN +#endif +#endif + +#if defined(WEBP_USE_THREAD) && !defined(_WIN32) +#include // NOLINT + +#define WEBP_DSP_INIT(func) \ + do { \ + static volatile VP8CPUInfo func##_last_cpuinfo_used = \ + (VP8CPUInfo)&func##_last_cpuinfo_used; \ + static pthread_mutex_t func##_lock = PTHREAD_MUTEX_INITIALIZER; \ + if (pthread_mutex_lock(&func##_lock)) break; \ + if (func##_last_cpuinfo_used != VP8GetCPUInfo) func(); \ + func##_last_cpuinfo_used = VP8GetCPUInfo; \ + (void)pthread_mutex_unlock(&func##_lock); \ + } while (0) +#else // !(defined(WEBP_USE_THREAD) && !defined(_WIN32)) +#define WEBP_DSP_INIT(func) \ + do { \ + static volatile VP8CPUInfo func##_last_cpuinfo_used = \ + (VP8CPUInfo)&func##_last_cpuinfo_used; \ + if (func##_last_cpuinfo_used == VP8GetCPUInfo) break; \ + func(); \ + func##_last_cpuinfo_used = VP8GetCPUInfo; \ + } while (0) +#endif // defined(WEBP_USE_THREAD) && !defined(_WIN32) + +// Defines an Init + helper function that control multiple initialization of +// function pointers / tables. +/* Usage: + WEBP_DSP_INIT_FUNC(InitFunc) { + ...function body + } +*/ +#define WEBP_DSP_INIT_FUNC(name) \ + static WEBP_TSAN_IGNORE_FUNCTION void name##_body(void); \ + WEBP_TSAN_IGNORE_FUNCTION void name(void) { WEBP_DSP_INIT(name##_body); } \ + static WEBP_TSAN_IGNORE_FUNCTION void name##_body(void) + +#define WEBP_UBSAN_IGNORE_UNDEF +#define WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW +#if defined(__clang__) && defined(__has_attribute) +#if __has_attribute(no_sanitize) +// This macro prevents the undefined behavior sanitizer from reporting +// failures. This is only meant to silence unaligned loads on platforms that +// are known to support them. +#undef WEBP_UBSAN_IGNORE_UNDEF +#define WEBP_UBSAN_IGNORE_UNDEF __attribute__((no_sanitize("undefined"))) + +// This macro prevents the undefined behavior sanitizer from reporting +// failures related to unsigned integer overflows. This is only meant to +// silence cases where this well defined behavior is expected. +#undef WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW +#define WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW \ + __attribute__((no_sanitize("unsigned-integer-overflow"))) +#endif +#endif + +// If 'ptr' is NULL, returns NULL. Otherwise returns 'ptr + off'. +// Prevents undefined behavior sanitizer nullptr-with-nonzero-offset warning. +#if !defined(WEBP_OFFSET_PTR) +#define WEBP_OFFSET_PTR(ptr, off) (((ptr) == NULL) ? NULL : ((ptr) + (off))) +#endif + +// Regularize the definition of WEBP_SWAP_16BIT_CSP (backward compatibility) +#if !defined(WEBP_SWAP_16BIT_CSP) +#define WEBP_SWAP_16BIT_CSP 0 +#endif + +// some endian fix (e.g.: mips-gcc doesn't define __BIG_ENDIAN__) +#if !defined(WORDS_BIGENDIAN) && \ + (defined(__BIG_ENDIAN__) || defined(_M_PPC) || \ + (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))) +#define WORDS_BIGENDIAN +#endif + +typedef enum { + kSSE2, + kSSE3, + kSlowSSSE3, // special feature for slow SSSE3 architectures + kSSE4_1, + kAVX, + kAVX2, + kNEON, + kMIPS32, + kMIPSdspR2, + kMSA +} CPUFeature; + +// returns true if the CPU supports the feature. +typedef int (*VP8CPUInfo)(CPUFeature feature); + +#endif // WEBP_DSP_CPU_H_ diff --git a/third-party/webp/libwebp/src/dsp/dec.c b/third-party/webp/libwebp/src/dsp/dec.c new file mode 100644 index 0000000000..33d8df8a62 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/dec.c @@ -0,0 +1,888 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Speed-critical decoding functions, default plain-C implementations. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include + +#include "src/dsp/dsp.h" +#include "src/dec/vp8i_dec.h" +#include "src/utils/utils.h" + +//------------------------------------------------------------------------------ + +static WEBP_INLINE uint8_t clip_8b(int v) { + return (!(v & ~0xff)) ? v : (v < 0) ? 0 : 255; +} + +//------------------------------------------------------------------------------ +// Transforms (Paragraph 14.4) + +#define STORE(x, y, v) \ + dst[(x) + (y) * BPS] = clip_8b(dst[(x) + (y) * BPS] + ((v) >> 3)) + +#define STORE2(y, dc, d, c) do { \ + const int DC = (dc); \ + STORE(0, y, DC + (d)); \ + STORE(1, y, DC + (c)); \ + STORE(2, y, DC - (c)); \ + STORE(3, y, DC - (d)); \ +} while (0) + +#define MUL1(a) ((((a) * 20091) >> 16) + (a)) +#define MUL2(a) (((a) * 35468) >> 16) + +#if !WEBP_NEON_OMIT_C_CODE +static void TransformOne_C(const int16_t* in, uint8_t* dst) { + int C[4 * 4], *tmp; + int i; + tmp = C; + for (i = 0; i < 4; ++i) { // vertical pass + const int a = in[0] + in[8]; // [-4096, 4094] + const int b = in[0] - in[8]; // [-4095, 4095] + const int c = MUL2(in[4]) - MUL1(in[12]); // [-3783, 3783] + const int d = MUL1(in[4]) + MUL2(in[12]); // [-3785, 3781] + tmp[0] = a + d; // [-7881, 7875] + tmp[1] = b + c; // [-7878, 7878] + tmp[2] = b - c; // [-7878, 7878] + tmp[3] = a - d; // [-7877, 7879] + tmp += 4; + in++; + } + // Each pass is expanding the dynamic range by ~3.85 (upper bound). + // The exact value is (2. + (20091 + 35468) / 65536). + // After the second pass, maximum interval is [-3794, 3794], assuming + // an input in [-2048, 2047] interval. We then need to add a dst value + // in the [0, 255] range. + // In the worst case scenario, the input to clip_8b() can be as large as + // [-60713, 60968]. + tmp = C; + for (i = 0; i < 4; ++i) { // horizontal pass + const int dc = tmp[0] + 4; + const int a = dc + tmp[8]; + const int b = dc - tmp[8]; + const int c = MUL2(tmp[4]) - MUL1(tmp[12]); + const int d = MUL1(tmp[4]) + MUL2(tmp[12]); + STORE(0, 0, a + d); + STORE(1, 0, b + c); + STORE(2, 0, b - c); + STORE(3, 0, a - d); + tmp++; + dst += BPS; + } +} + +// Simplified transform when only in[0], in[1] and in[4] are non-zero +static void TransformAC3_C(const int16_t* in, uint8_t* dst) { + const int a = in[0] + 4; + const int c4 = MUL2(in[4]); + const int d4 = MUL1(in[4]); + const int c1 = MUL2(in[1]); + const int d1 = MUL1(in[1]); + STORE2(0, a + d4, d1, c1); + STORE2(1, a + c4, d1, c1); + STORE2(2, a - c4, d1, c1); + STORE2(3, a - d4, d1, c1); +} +#undef MUL1 +#undef MUL2 +#undef STORE2 + +static void TransformTwo_C(const int16_t* in, uint8_t* dst, int do_two) { + TransformOne_C(in, dst); + if (do_two) { + TransformOne_C(in + 16, dst + 4); + } +} +#endif // !WEBP_NEON_OMIT_C_CODE + +static void TransformUV_C(const int16_t* in, uint8_t* dst) { + VP8Transform(in + 0 * 16, dst, 1); + VP8Transform(in + 2 * 16, dst + 4 * BPS, 1); +} + +#if !WEBP_NEON_OMIT_C_CODE +static void TransformDC_C(const int16_t* in, uint8_t* dst) { + const int DC = in[0] + 4; + int i, j; + for (j = 0; j < 4; ++j) { + for (i = 0; i < 4; ++i) { + STORE(i, j, DC); + } + } +} +#endif // !WEBP_NEON_OMIT_C_CODE + +static void TransformDCUV_C(const int16_t* in, uint8_t* dst) { + if (in[0 * 16]) VP8TransformDC(in + 0 * 16, dst); + if (in[1 * 16]) VP8TransformDC(in + 1 * 16, dst + 4); + if (in[2 * 16]) VP8TransformDC(in + 2 * 16, dst + 4 * BPS); + if (in[3 * 16]) VP8TransformDC(in + 3 * 16, dst + 4 * BPS + 4); +} + +#undef STORE + +//------------------------------------------------------------------------------ +// Paragraph 14.3 + +#if !WEBP_NEON_OMIT_C_CODE +static void TransformWHT_C(const int16_t* in, int16_t* out) { + int tmp[16]; + int i; + for (i = 0; i < 4; ++i) { + const int a0 = in[0 + i] + in[12 + i]; + const int a1 = in[4 + i] + in[ 8 + i]; + const int a2 = in[4 + i] - in[ 8 + i]; + const int a3 = in[0 + i] - in[12 + i]; + tmp[0 + i] = a0 + a1; + tmp[8 + i] = a0 - a1; + tmp[4 + i] = a3 + a2; + tmp[12 + i] = a3 - a2; + } + for (i = 0; i < 4; ++i) { + const int dc = tmp[0 + i * 4] + 3; // w/ rounder + const int a0 = dc + tmp[3 + i * 4]; + const int a1 = tmp[1 + i * 4] + tmp[2 + i * 4]; + const int a2 = tmp[1 + i * 4] - tmp[2 + i * 4]; + const int a3 = dc - tmp[3 + i * 4]; + out[ 0] = (a0 + a1) >> 3; + out[16] = (a3 + a2) >> 3; + out[32] = (a0 - a1) >> 3; + out[48] = (a3 - a2) >> 3; + out += 64; + } +} +#endif // !WEBP_NEON_OMIT_C_CODE + +void (*VP8TransformWHT)(const int16_t* in, int16_t* out); + +//------------------------------------------------------------------------------ +// Intra predictions + +#define DST(x, y) dst[(x) + (y) * BPS] + +#if !WEBP_NEON_OMIT_C_CODE +static WEBP_INLINE void TrueMotion(uint8_t* dst, int size) { + const uint8_t* top = dst - BPS; + const uint8_t* const clip0 = VP8kclip1 - top[-1]; + int y; + for (y = 0; y < size; ++y) { + const uint8_t* const clip = clip0 + dst[-1]; + int x; + for (x = 0; x < size; ++x) { + dst[x] = clip[top[x]]; + } + dst += BPS; + } +} +static void TM4_C(uint8_t* dst) { TrueMotion(dst, 4); } +static void TM8uv_C(uint8_t* dst) { TrueMotion(dst, 8); } +static void TM16_C(uint8_t* dst) { TrueMotion(dst, 16); } + +//------------------------------------------------------------------------------ +// 16x16 + +static void VE16_C(uint8_t* dst) { // vertical + int j; + for (j = 0; j < 16; ++j) { + memcpy(dst + j * BPS, dst - BPS, 16); + } +} + +static void HE16_C(uint8_t* dst) { // horizontal + int j; + for (j = 16; j > 0; --j) { + memset(dst, dst[-1], 16); + dst += BPS; + } +} + +static WEBP_INLINE void Put16(int v, uint8_t* dst) { + int j; + for (j = 0; j < 16; ++j) { + memset(dst + j * BPS, v, 16); + } +} + +static void DC16_C(uint8_t* dst) { // DC + int DC = 16; + int j; + for (j = 0; j < 16; ++j) { + DC += dst[-1 + j * BPS] + dst[j - BPS]; + } + Put16(DC >> 5, dst); +} + +static void DC16NoTop_C(uint8_t* dst) { // DC with top samples not available + int DC = 8; + int j; + for (j = 0; j < 16; ++j) { + DC += dst[-1 + j * BPS]; + } + Put16(DC >> 4, dst); +} + +static void DC16NoLeft_C(uint8_t* dst) { // DC with left samples not available + int DC = 8; + int i; + for (i = 0; i < 16; ++i) { + DC += dst[i - BPS]; + } + Put16(DC >> 4, dst); +} + +static void DC16NoTopLeft_C(uint8_t* dst) { // DC with no top and left samples + Put16(0x80, dst); +} +#endif // !WEBP_NEON_OMIT_C_CODE + +VP8PredFunc VP8PredLuma16[NUM_B_DC_MODES]; + +//------------------------------------------------------------------------------ +// 4x4 + +#define AVG3(a, b, c) ((uint8_t)(((a) + 2 * (b) + (c) + 2) >> 2)) +#define AVG2(a, b) (((a) + (b) + 1) >> 1) + +#if !WEBP_NEON_OMIT_C_CODE +static void VE4_C(uint8_t* dst) { // vertical + const uint8_t* top = dst - BPS; + const uint8_t vals[4] = { + AVG3(top[-1], top[0], top[1]), + AVG3(top[ 0], top[1], top[2]), + AVG3(top[ 1], top[2], top[3]), + AVG3(top[ 2], top[3], top[4]) + }; + int i; + for (i = 0; i < 4; ++i) { + memcpy(dst + i * BPS, vals, sizeof(vals)); + } +} +#endif // !WEBP_NEON_OMIT_C_CODE + +static void HE4_C(uint8_t* dst) { // horizontal + const int A = dst[-1 - BPS]; + const int B = dst[-1]; + const int C = dst[-1 + BPS]; + const int D = dst[-1 + 2 * BPS]; + const int E = dst[-1 + 3 * BPS]; + WebPUint32ToMem(dst + 0 * BPS, 0x01010101U * AVG3(A, B, C)); + WebPUint32ToMem(dst + 1 * BPS, 0x01010101U * AVG3(B, C, D)); + WebPUint32ToMem(dst + 2 * BPS, 0x01010101U * AVG3(C, D, E)); + WebPUint32ToMem(dst + 3 * BPS, 0x01010101U * AVG3(D, E, E)); +} + +#if !WEBP_NEON_OMIT_C_CODE +static void DC4_C(uint8_t* dst) { // DC + uint32_t dc = 4; + int i; + for (i = 0; i < 4; ++i) dc += dst[i - BPS] + dst[-1 + i * BPS]; + dc >>= 3; + for (i = 0; i < 4; ++i) memset(dst + i * BPS, dc, 4); +} + +static void RD4_C(uint8_t* dst) { // Down-right + const int I = dst[-1 + 0 * BPS]; + const int J = dst[-1 + 1 * BPS]; + const int K = dst[-1 + 2 * BPS]; + const int L = dst[-1 + 3 * BPS]; + const int X = dst[-1 - BPS]; + const int A = dst[0 - BPS]; + const int B = dst[1 - BPS]; + const int C = dst[2 - BPS]; + const int D = dst[3 - BPS]; + DST(0, 3) = AVG3(J, K, L); + DST(1, 3) = DST(0, 2) = AVG3(I, J, K); + DST(2, 3) = DST(1, 2) = DST(0, 1) = AVG3(X, I, J); + DST(3, 3) = DST(2, 2) = DST(1, 1) = DST(0, 0) = AVG3(A, X, I); + DST(3, 2) = DST(2, 1) = DST(1, 0) = AVG3(B, A, X); + DST(3, 1) = DST(2, 0) = AVG3(C, B, A); + DST(3, 0) = AVG3(D, C, B); +} + +static void LD4_C(uint8_t* dst) { // Down-Left + const int A = dst[0 - BPS]; + const int B = dst[1 - BPS]; + const int C = dst[2 - BPS]; + const int D = dst[3 - BPS]; + const int E = dst[4 - BPS]; + const int F = dst[5 - BPS]; + const int G = dst[6 - BPS]; + const int H = dst[7 - BPS]; + DST(0, 0) = AVG3(A, B, C); + DST(1, 0) = DST(0, 1) = AVG3(B, C, D); + DST(2, 0) = DST(1, 1) = DST(0, 2) = AVG3(C, D, E); + DST(3, 0) = DST(2, 1) = DST(1, 2) = DST(0, 3) = AVG3(D, E, F); + DST(3, 1) = DST(2, 2) = DST(1, 3) = AVG3(E, F, G); + DST(3, 2) = DST(2, 3) = AVG3(F, G, H); + DST(3, 3) = AVG3(G, H, H); +} +#endif // !WEBP_NEON_OMIT_C_CODE + +static void VR4_C(uint8_t* dst) { // Vertical-Right + const int I = dst[-1 + 0 * BPS]; + const int J = dst[-1 + 1 * BPS]; + const int K = dst[-1 + 2 * BPS]; + const int X = dst[-1 - BPS]; + const int A = dst[0 - BPS]; + const int B = dst[1 - BPS]; + const int C = dst[2 - BPS]; + const int D = dst[3 - BPS]; + DST(0, 0) = DST(1, 2) = AVG2(X, A); + DST(1, 0) = DST(2, 2) = AVG2(A, B); + DST(2, 0) = DST(3, 2) = AVG2(B, C); + DST(3, 0) = AVG2(C, D); + + DST(0, 3) = AVG3(K, J, I); + DST(0, 2) = AVG3(J, I, X); + DST(0, 1) = DST(1, 3) = AVG3(I, X, A); + DST(1, 1) = DST(2, 3) = AVG3(X, A, B); + DST(2, 1) = DST(3, 3) = AVG3(A, B, C); + DST(3, 1) = AVG3(B, C, D); +} + +static void VL4_C(uint8_t* dst) { // Vertical-Left + const int A = dst[0 - BPS]; + const int B = dst[1 - BPS]; + const int C = dst[2 - BPS]; + const int D = dst[3 - BPS]; + const int E = dst[4 - BPS]; + const int F = dst[5 - BPS]; + const int G = dst[6 - BPS]; + const int H = dst[7 - BPS]; + DST(0, 0) = AVG2(A, B); + DST(1, 0) = DST(0, 2) = AVG2(B, C); + DST(2, 0) = DST(1, 2) = AVG2(C, D); + DST(3, 0) = DST(2, 2) = AVG2(D, E); + + DST(0, 1) = AVG3(A, B, C); + DST(1, 1) = DST(0, 3) = AVG3(B, C, D); + DST(2, 1) = DST(1, 3) = AVG3(C, D, E); + DST(3, 1) = DST(2, 3) = AVG3(D, E, F); + DST(3, 2) = AVG3(E, F, G); + DST(3, 3) = AVG3(F, G, H); +} + +static void HU4_C(uint8_t* dst) { // Horizontal-Up + const int I = dst[-1 + 0 * BPS]; + const int J = dst[-1 + 1 * BPS]; + const int K = dst[-1 + 2 * BPS]; + const int L = dst[-1 + 3 * BPS]; + DST(0, 0) = AVG2(I, J); + DST(2, 0) = DST(0, 1) = AVG2(J, K); + DST(2, 1) = DST(0, 2) = AVG2(K, L); + DST(1, 0) = AVG3(I, J, K); + DST(3, 0) = DST(1, 1) = AVG3(J, K, L); + DST(3, 1) = DST(1, 2) = AVG3(K, L, L); + DST(3, 2) = DST(2, 2) = + DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L; +} + +static void HD4_C(uint8_t* dst) { // Horizontal-Down + const int I = dst[-1 + 0 * BPS]; + const int J = dst[-1 + 1 * BPS]; + const int K = dst[-1 + 2 * BPS]; + const int L = dst[-1 + 3 * BPS]; + const int X = dst[-1 - BPS]; + const int A = dst[0 - BPS]; + const int B = dst[1 - BPS]; + const int C = dst[2 - BPS]; + + DST(0, 0) = DST(2, 1) = AVG2(I, X); + DST(0, 1) = DST(2, 2) = AVG2(J, I); + DST(0, 2) = DST(2, 3) = AVG2(K, J); + DST(0, 3) = AVG2(L, K); + + DST(3, 0) = AVG3(A, B, C); + DST(2, 0) = AVG3(X, A, B); + DST(1, 0) = DST(3, 1) = AVG3(I, X, A); + DST(1, 1) = DST(3, 2) = AVG3(J, I, X); + DST(1, 2) = DST(3, 3) = AVG3(K, J, I); + DST(1, 3) = AVG3(L, K, J); +} + +#undef DST +#undef AVG3 +#undef AVG2 + +VP8PredFunc VP8PredLuma4[NUM_BMODES]; + +//------------------------------------------------------------------------------ +// Chroma + +#if !WEBP_NEON_OMIT_C_CODE +static void VE8uv_C(uint8_t* dst) { // vertical + int j; + for (j = 0; j < 8; ++j) { + memcpy(dst + j * BPS, dst - BPS, 8); + } +} + +static void HE8uv_C(uint8_t* dst) { // horizontal + int j; + for (j = 0; j < 8; ++j) { + memset(dst, dst[-1], 8); + dst += BPS; + } +} + +// helper for chroma-DC predictions +static WEBP_INLINE void Put8x8uv(uint8_t value, uint8_t* dst) { + int j; + for (j = 0; j < 8; ++j) { + memset(dst + j * BPS, value, 8); + } +} + +static void DC8uv_C(uint8_t* dst) { // DC + int dc0 = 8; + int i; + for (i = 0; i < 8; ++i) { + dc0 += dst[i - BPS] + dst[-1 + i * BPS]; + } + Put8x8uv(dc0 >> 4, dst); +} + +static void DC8uvNoLeft_C(uint8_t* dst) { // DC with no left samples + int dc0 = 4; + int i; + for (i = 0; i < 8; ++i) { + dc0 += dst[i - BPS]; + } + Put8x8uv(dc0 >> 3, dst); +} + +static void DC8uvNoTop_C(uint8_t* dst) { // DC with no top samples + int dc0 = 4; + int i; + for (i = 0; i < 8; ++i) { + dc0 += dst[-1 + i * BPS]; + } + Put8x8uv(dc0 >> 3, dst); +} + +static void DC8uvNoTopLeft_C(uint8_t* dst) { // DC with nothing + Put8x8uv(0x80, dst); +} +#endif // !WEBP_NEON_OMIT_C_CODE + +VP8PredFunc VP8PredChroma8[NUM_B_DC_MODES]; + +//------------------------------------------------------------------------------ +// Edge filtering functions + +#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC +// 4 pixels in, 2 pixels out +static WEBP_INLINE void DoFilter2_C(uint8_t* p, int step) { + const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step]; + const int a = 3 * (q0 - p0) + VP8ksclip1[p1 - q1]; // in [-893,892] + const int a1 = VP8ksclip2[(a + 4) >> 3]; // in [-16,15] + const int a2 = VP8ksclip2[(a + 3) >> 3]; + p[-step] = VP8kclip1[p0 + a2]; + p[ 0] = VP8kclip1[q0 - a1]; +} + +// 4 pixels in, 4 pixels out +static WEBP_INLINE void DoFilter4_C(uint8_t* p, int step) { + const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step]; + const int a = 3 * (q0 - p0); + const int a1 = VP8ksclip2[(a + 4) >> 3]; + const int a2 = VP8ksclip2[(a + 3) >> 3]; + const int a3 = (a1 + 1) >> 1; + p[-2*step] = VP8kclip1[p1 + a3]; + p[- step] = VP8kclip1[p0 + a2]; + p[ 0] = VP8kclip1[q0 - a1]; + p[ step] = VP8kclip1[q1 - a3]; +} + +// 6 pixels in, 6 pixels out +static WEBP_INLINE void DoFilter6_C(uint8_t* p, int step) { + const int p2 = p[-3*step], p1 = p[-2*step], p0 = p[-step]; + const int q0 = p[0], q1 = p[step], q2 = p[2*step]; + const int a = VP8ksclip1[3 * (q0 - p0) + VP8ksclip1[p1 - q1]]; + // a is in [-128,127], a1 in [-27,27], a2 in [-18,18] and a3 in [-9,9] + const int a1 = (27 * a + 63) >> 7; // eq. to ((3 * a + 7) * 9) >> 7 + const int a2 = (18 * a + 63) >> 7; // eq. to ((2 * a + 7) * 9) >> 7 + const int a3 = (9 * a + 63) >> 7; // eq. to ((1 * a + 7) * 9) >> 7 + p[-3*step] = VP8kclip1[p2 + a3]; + p[-2*step] = VP8kclip1[p1 + a2]; + p[- step] = VP8kclip1[p0 + a1]; + p[ 0] = VP8kclip1[q0 - a1]; + p[ step] = VP8kclip1[q1 - a2]; + p[ 2*step] = VP8kclip1[q2 - a3]; +} + +static WEBP_INLINE int Hev(const uint8_t* p, int step, int thresh) { + const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step]; + return (VP8kabs0[p1 - p0] > thresh) || (VP8kabs0[q1 - q0] > thresh); +} +#endif // !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC + +#if !WEBP_NEON_OMIT_C_CODE +static WEBP_INLINE int NeedsFilter_C(const uint8_t* p, int step, int t) { + const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step]; + return ((4 * VP8kabs0[p0 - q0] + VP8kabs0[p1 - q1]) <= t); +} +#endif // !WEBP_NEON_OMIT_C_CODE + +#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC +static WEBP_INLINE int NeedsFilter2_C(const uint8_t* p, + int step, int t, int it) { + const int p3 = p[-4 * step], p2 = p[-3 * step], p1 = p[-2 * step]; + const int p0 = p[-step], q0 = p[0]; + const int q1 = p[step], q2 = p[2 * step], q3 = p[3 * step]; + if ((4 * VP8kabs0[p0 - q0] + VP8kabs0[p1 - q1]) > t) return 0; + return VP8kabs0[p3 - p2] <= it && VP8kabs0[p2 - p1] <= it && + VP8kabs0[p1 - p0] <= it && VP8kabs0[q3 - q2] <= it && + VP8kabs0[q2 - q1] <= it && VP8kabs0[q1 - q0] <= it; +} +#endif // !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC + +//------------------------------------------------------------------------------ +// Simple In-loop filtering (Paragraph 15.2) + +#if !WEBP_NEON_OMIT_C_CODE +static void SimpleVFilter16_C(uint8_t* p, int stride, int thresh) { + int i; + const int thresh2 = 2 * thresh + 1; + for (i = 0; i < 16; ++i) { + if (NeedsFilter_C(p + i, stride, thresh2)) { + DoFilter2_C(p + i, stride); + } + } +} + +static void SimpleHFilter16_C(uint8_t* p, int stride, int thresh) { + int i; + const int thresh2 = 2 * thresh + 1; + for (i = 0; i < 16; ++i) { + if (NeedsFilter_C(p + i * stride, 1, thresh2)) { + DoFilter2_C(p + i * stride, 1); + } + } +} + +static void SimpleVFilter16i_C(uint8_t* p, int stride, int thresh) { + int k; + for (k = 3; k > 0; --k) { + p += 4 * stride; + SimpleVFilter16_C(p, stride, thresh); + } +} + +static void SimpleHFilter16i_C(uint8_t* p, int stride, int thresh) { + int k; + for (k = 3; k > 0; --k) { + p += 4; + SimpleHFilter16_C(p, stride, thresh); + } +} +#endif // !WEBP_NEON_OMIT_C_CODE + +//------------------------------------------------------------------------------ +// Complex In-loop filtering (Paragraph 15.3) + +#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC +static WEBP_INLINE void FilterLoop26_C(uint8_t* p, + int hstride, int vstride, int size, + int thresh, int ithresh, + int hev_thresh) { + const int thresh2 = 2 * thresh + 1; + while (size-- > 0) { + if (NeedsFilter2_C(p, hstride, thresh2, ithresh)) { + if (Hev(p, hstride, hev_thresh)) { + DoFilter2_C(p, hstride); + } else { + DoFilter6_C(p, hstride); + } + } + p += vstride; + } +} + +static WEBP_INLINE void FilterLoop24_C(uint8_t* p, + int hstride, int vstride, int size, + int thresh, int ithresh, + int hev_thresh) { + const int thresh2 = 2 * thresh + 1; + while (size-- > 0) { + if (NeedsFilter2_C(p, hstride, thresh2, ithresh)) { + if (Hev(p, hstride, hev_thresh)) { + DoFilter2_C(p, hstride); + } else { + DoFilter4_C(p, hstride); + } + } + p += vstride; + } +} +#endif // !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC + +#if !WEBP_NEON_OMIT_C_CODE +// on macroblock edges +static void VFilter16_C(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop26_C(p, stride, 1, 16, thresh, ithresh, hev_thresh); +} + +static void HFilter16_C(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop26_C(p, 1, stride, 16, thresh, ithresh, hev_thresh); +} + +// on three inner edges +static void VFilter16i_C(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + int k; + for (k = 3; k > 0; --k) { + p += 4 * stride; + FilterLoop24_C(p, stride, 1, 16, thresh, ithresh, hev_thresh); + } +} +#endif // !WEBP_NEON_OMIT_C_CODE + +#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC +static void HFilter16i_C(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + int k; + for (k = 3; k > 0; --k) { + p += 4; + FilterLoop24_C(p, 1, stride, 16, thresh, ithresh, hev_thresh); + } +} +#endif // !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC + +#if !WEBP_NEON_OMIT_C_CODE +// 8-pixels wide variant, for chroma filtering +static void VFilter8_C(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop26_C(u, stride, 1, 8, thresh, ithresh, hev_thresh); + FilterLoop26_C(v, stride, 1, 8, thresh, ithresh, hev_thresh); +} +#endif // !WEBP_NEON_OMIT_C_CODE + +#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC +static void HFilter8_C(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop26_C(u, 1, stride, 8, thresh, ithresh, hev_thresh); + FilterLoop26_C(v, 1, stride, 8, thresh, ithresh, hev_thresh); +} +#endif // !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC + +#if !WEBP_NEON_OMIT_C_CODE +static void VFilter8i_C(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop24_C(u + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh); + FilterLoop24_C(v + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh); +} +#endif // !WEBP_NEON_OMIT_C_CODE + +#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC +static void HFilter8i_C(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop24_C(u + 4, 1, stride, 8, thresh, ithresh, hev_thresh); + FilterLoop24_C(v + 4, 1, stride, 8, thresh, ithresh, hev_thresh); +} +#endif // !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC + +//------------------------------------------------------------------------------ + +static void DitherCombine8x8_C(const uint8_t* dither, uint8_t* dst, + int dst_stride) { + int i, j; + for (j = 0; j < 8; ++j) { + for (i = 0; i < 8; ++i) { + const int delta0 = dither[i] - VP8_DITHER_AMP_CENTER; + const int delta1 = + (delta0 + VP8_DITHER_DESCALE_ROUNDER) >> VP8_DITHER_DESCALE; + dst[i] = clip_8b((int)dst[i] + delta1); + } + dst += dst_stride; + dither += 8; + } +} + +//------------------------------------------------------------------------------ + +VP8DecIdct2 VP8Transform; +VP8DecIdct VP8TransformAC3; +VP8DecIdct VP8TransformUV; +VP8DecIdct VP8TransformDC; +VP8DecIdct VP8TransformDCUV; + +VP8LumaFilterFunc VP8VFilter16; +VP8LumaFilterFunc VP8HFilter16; +VP8ChromaFilterFunc VP8VFilter8; +VP8ChromaFilterFunc VP8HFilter8; +VP8LumaFilterFunc VP8VFilter16i; +VP8LumaFilterFunc VP8HFilter16i; +VP8ChromaFilterFunc VP8VFilter8i; +VP8ChromaFilterFunc VP8HFilter8i; +VP8SimpleFilterFunc VP8SimpleVFilter16; +VP8SimpleFilterFunc VP8SimpleHFilter16; +VP8SimpleFilterFunc VP8SimpleVFilter16i; +VP8SimpleFilterFunc VP8SimpleHFilter16i; + +void (*VP8DitherCombine8x8)(const uint8_t* dither, uint8_t* dst, + int dst_stride); + +extern VP8CPUInfo VP8GetCPUInfo; +extern void VP8DspInitSSE2(void); +extern void VP8DspInitSSE41(void); +extern void VP8DspInitNEON(void); +extern void VP8DspInitMIPS32(void); +extern void VP8DspInitMIPSdspR2(void); +extern void VP8DspInitMSA(void); + +WEBP_DSP_INIT_FUNC(VP8DspInit) { + VP8InitClipTables(); + +#if !WEBP_NEON_OMIT_C_CODE + VP8TransformWHT = TransformWHT_C; + VP8Transform = TransformTwo_C; + VP8TransformDC = TransformDC_C; + VP8TransformAC3 = TransformAC3_C; +#endif + VP8TransformUV = TransformUV_C; + VP8TransformDCUV = TransformDCUV_C; + +#if !WEBP_NEON_OMIT_C_CODE + VP8VFilter16 = VFilter16_C; + VP8VFilter16i = VFilter16i_C; + VP8HFilter16 = HFilter16_C; + VP8VFilter8 = VFilter8_C; + VP8VFilter8i = VFilter8i_C; + VP8SimpleVFilter16 = SimpleVFilter16_C; + VP8SimpleHFilter16 = SimpleHFilter16_C; + VP8SimpleVFilter16i = SimpleVFilter16i_C; + VP8SimpleHFilter16i = SimpleHFilter16i_C; +#endif + +#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC + VP8HFilter16i = HFilter16i_C; + VP8HFilter8 = HFilter8_C; + VP8HFilter8i = HFilter8i_C; +#endif + +#if !WEBP_NEON_OMIT_C_CODE + VP8PredLuma4[0] = DC4_C; + VP8PredLuma4[1] = TM4_C; + VP8PredLuma4[2] = VE4_C; + VP8PredLuma4[4] = RD4_C; + VP8PredLuma4[6] = LD4_C; +#endif + + VP8PredLuma4[3] = HE4_C; + VP8PredLuma4[5] = VR4_C; + VP8PredLuma4[7] = VL4_C; + VP8PredLuma4[8] = HD4_C; + VP8PredLuma4[9] = HU4_C; + +#if !WEBP_NEON_OMIT_C_CODE + VP8PredLuma16[0] = DC16_C; + VP8PredLuma16[1] = TM16_C; + VP8PredLuma16[2] = VE16_C; + VP8PredLuma16[3] = HE16_C; + VP8PredLuma16[4] = DC16NoTop_C; + VP8PredLuma16[5] = DC16NoLeft_C; + VP8PredLuma16[6] = DC16NoTopLeft_C; + + VP8PredChroma8[0] = DC8uv_C; + VP8PredChroma8[1] = TM8uv_C; + VP8PredChroma8[2] = VE8uv_C; + VP8PredChroma8[3] = HE8uv_C; + VP8PredChroma8[4] = DC8uvNoTop_C; + VP8PredChroma8[5] = DC8uvNoLeft_C; + VP8PredChroma8[6] = DC8uvNoTopLeft_C; +#endif + + VP8DitherCombine8x8 = DitherCombine8x8_C; + + // If defined, use CPUInfo() to overwrite some pointers with faster versions. + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_HAVE_SSE2) + if (VP8GetCPUInfo(kSSE2)) { + VP8DspInitSSE2(); +#if defined(WEBP_HAVE_SSE41) + if (VP8GetCPUInfo(kSSE4_1)) { + VP8DspInitSSE41(); + } +#endif + } +#endif +#if defined(WEBP_USE_MIPS32) + if (VP8GetCPUInfo(kMIPS32)) { + VP8DspInitMIPS32(); + } +#endif +#if defined(WEBP_USE_MIPS_DSP_R2) + if (VP8GetCPUInfo(kMIPSdspR2)) { + VP8DspInitMIPSdspR2(); + } +#endif +#if defined(WEBP_USE_MSA) + if (VP8GetCPUInfo(kMSA)) { + VP8DspInitMSA(); + } +#endif + } + +#if defined(WEBP_HAVE_NEON) + if (WEBP_NEON_OMIT_C_CODE || + (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) { + VP8DspInitNEON(); + } +#endif + + assert(VP8TransformWHT != NULL); + assert(VP8Transform != NULL); + assert(VP8TransformDC != NULL); + assert(VP8TransformAC3 != NULL); + assert(VP8TransformUV != NULL); + assert(VP8TransformDCUV != NULL); + assert(VP8VFilter16 != NULL); + assert(VP8HFilter16 != NULL); + assert(VP8VFilter8 != NULL); + assert(VP8HFilter8 != NULL); + assert(VP8VFilter16i != NULL); + assert(VP8HFilter16i != NULL); + assert(VP8VFilter8i != NULL); + assert(VP8HFilter8i != NULL); + assert(VP8SimpleVFilter16 != NULL); + assert(VP8SimpleHFilter16 != NULL); + assert(VP8SimpleVFilter16i != NULL); + assert(VP8SimpleHFilter16i != NULL); + assert(VP8PredLuma4[0] != NULL); + assert(VP8PredLuma4[1] != NULL); + assert(VP8PredLuma4[2] != NULL); + assert(VP8PredLuma4[3] != NULL); + assert(VP8PredLuma4[4] != NULL); + assert(VP8PredLuma4[5] != NULL); + assert(VP8PredLuma4[6] != NULL); + assert(VP8PredLuma4[7] != NULL); + assert(VP8PredLuma4[8] != NULL); + assert(VP8PredLuma4[9] != NULL); + assert(VP8PredLuma16[0] != NULL); + assert(VP8PredLuma16[1] != NULL); + assert(VP8PredLuma16[2] != NULL); + assert(VP8PredLuma16[3] != NULL); + assert(VP8PredLuma16[4] != NULL); + assert(VP8PredLuma16[5] != NULL); + assert(VP8PredLuma16[6] != NULL); + assert(VP8PredChroma8[0] != NULL); + assert(VP8PredChroma8[1] != NULL); + assert(VP8PredChroma8[2] != NULL); + assert(VP8PredChroma8[3] != NULL); + assert(VP8PredChroma8[4] != NULL); + assert(VP8PredChroma8[5] != NULL); + assert(VP8PredChroma8[6] != NULL); + assert(VP8DitherCombine8x8 != NULL); +} diff --git a/third-party/webp/libwebp/src/dsp/dec_clip_tables.c b/third-party/webp/libwebp/src/dsp/dec_clip_tables.c new file mode 100644 index 0000000000..427b74f776 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/dec_clip_tables.c @@ -0,0 +1,369 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Clipping tables for filtering +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +// define to 0 to have run-time table initialization +#if !defined(USE_STATIC_TABLES) +#define USE_STATIC_TABLES 1 // ALTERNATE_CODE +#endif + +#if (USE_STATIC_TABLES == 1) + +static const uint8_t abs0[255 + 255 + 1] = { + 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, + 0xf3, 0xf2, 0xf1, 0xf0, 0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, 0xe8, + 0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0, 0xdf, 0xde, 0xdd, 0xdc, + 0xdb, 0xda, 0xd9, 0xd8, 0xd7, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xd0, + 0xcf, 0xce, 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8, 0xc7, 0xc6, 0xc5, 0xc4, + 0xc3, 0xc2, 0xc1, 0xc0, 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8, + 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0, 0xaf, 0xae, 0xad, 0xac, + 0xab, 0xaa, 0xa9, 0xa8, 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, 0xa0, + 0x9f, 0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94, + 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, + 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x7f, 0x7e, 0x7d, 0x7c, + 0x7b, 0x7a, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70, + 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, + 0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58, + 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x4e, 0x4d, 0x4c, + 0x4b, 0x4a, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, + 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, + 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, + 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x1d, 0x1c, + 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, + 0x03, 0x02, 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, + 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, + 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, + 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, + 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, + 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, + 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, + 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, + 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, + 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, + 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, + 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, + 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, + 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, + 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff +}; + +static const uint8_t sclip1[1020 + 1020 + 1] = { + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, + 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, + 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, + 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, + 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, + 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, + 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, + 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f +}; + +static const uint8_t sclip2[112 + 112 + 1] = { + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, + 0xfc, 0xfd, 0xfe, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f +}; + +static const uint8_t clip1[255 + 511 + 1] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, + 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, + 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, + 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, + 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, + 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, + 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, + 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, + 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, + 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, + 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, + 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, + 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, + 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, + 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +#else + +// uninitialized tables +static uint8_t abs0[255 + 255 + 1]; +static int8_t sclip1[1020 + 1020 + 1]; +static int8_t sclip2[112 + 112 + 1]; +static uint8_t clip1[255 + 511 + 1]; + +// We declare this variable 'volatile' to prevent instruction reordering +// and make sure it's set to true _last_ (so as to be thread-safe) +static volatile int tables_ok = 0; + +#endif // USE_STATIC_TABLES + +const int8_t* const VP8ksclip1 = (const int8_t*)&sclip1[1020]; +const int8_t* const VP8ksclip2 = (const int8_t*)&sclip2[112]; +const uint8_t* const VP8kclip1 = &clip1[255]; +const uint8_t* const VP8kabs0 = &abs0[255]; + +WEBP_TSAN_IGNORE_FUNCTION void VP8InitClipTables(void) { +#if (USE_STATIC_TABLES == 0) + int i; + if (!tables_ok) { + for (i = -255; i <= 255; ++i) { + abs0[255 + i] = (i < 0) ? -i : i; + } + for (i = -1020; i <= 1020; ++i) { + sclip1[1020 + i] = (i < -128) ? -128 : (i > 127) ? 127 : i; + } + for (i = -112; i <= 112; ++i) { + sclip2[112 + i] = (i < -16) ? -16 : (i > 15) ? 15 : i; + } + for (i = -255; i <= 255 + 255; ++i) { + clip1[255 + i] = (i < 0) ? 0 : (i > 255) ? 255 : i; + } + tables_ok = 1; + } +#endif // USE_STATIC_TABLES +} diff --git a/third-party/webp/libwebp/src/dsp/dec_mips32.c b/third-party/webp/libwebp/src/dsp/dec_mips32.c new file mode 100644 index 0000000000..e4e70966d2 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/dec_mips32.c @@ -0,0 +1,587 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MIPS version of dsp functions +// +// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) +// Jovan Zelincevic (jovan.zelincevic@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MIPS32) + +#include "src/dsp/mips_macro.h" + +static const int kC1 = 20091 + (1 << 16); +static const int kC2 = 35468; + +static WEBP_INLINE int abs_mips32(int x) { + const int sign = x >> 31; + return (x ^ sign) - sign; +} + +// 4 pixels in, 2 pixels out +static WEBP_INLINE void do_filter2(uint8_t* p, int step) { + const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step]; + const int a = 3 * (q0 - p0) + VP8ksclip1[p1 - q1]; + const int a1 = VP8ksclip2[(a + 4) >> 3]; + const int a2 = VP8ksclip2[(a + 3) >> 3]; + p[-step] = VP8kclip1[p0 + a2]; + p[ 0] = VP8kclip1[q0 - a1]; +} + +// 4 pixels in, 4 pixels out +static WEBP_INLINE void do_filter4(uint8_t* p, int step) { + const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step]; + const int a = 3 * (q0 - p0); + const int a1 = VP8ksclip2[(a + 4) >> 3]; + const int a2 = VP8ksclip2[(a + 3) >> 3]; + const int a3 = (a1 + 1) >> 1; + p[-2 * step] = VP8kclip1[p1 + a3]; + p[- step] = VP8kclip1[p0 + a2]; + p[ 0] = VP8kclip1[q0 - a1]; + p[ step] = VP8kclip1[q1 - a3]; +} + +// 6 pixels in, 6 pixels out +static WEBP_INLINE void do_filter6(uint8_t* p, int step) { + const int p2 = p[-3 * step], p1 = p[-2 * step], p0 = p[-step]; + const int q0 = p[0], q1 = p[step], q2 = p[2 * step]; + const int a = VP8ksclip1[3 * (q0 - p0) + VP8ksclip1[p1 - q1]]; + // a is in [-128,127], a1 in [-27,27], a2 in [-18,18] and a3 in [-9,9] + const int a1 = (27 * a + 63) >> 7; // eq. to ((3 * a + 7) * 9) >> 7 + const int a2 = (18 * a + 63) >> 7; // eq. to ((2 * a + 7) * 9) >> 7 + const int a3 = (9 * a + 63) >> 7; // eq. to ((1 * a + 7) * 9) >> 7 + p[-3 * step] = VP8kclip1[p2 + a3]; + p[-2 * step] = VP8kclip1[p1 + a2]; + p[- step] = VP8kclip1[p0 + a1]; + p[ 0] = VP8kclip1[q0 - a1]; + p[ step] = VP8kclip1[q1 - a2]; + p[ 2 * step] = VP8kclip1[q2 - a3]; +} + +static WEBP_INLINE int hev(const uint8_t* p, int step, int thresh) { + const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step]; + return (abs_mips32(p1 - p0) > thresh) || (abs_mips32(q1 - q0) > thresh); +} + +static WEBP_INLINE int needs_filter(const uint8_t* p, int step, int t) { + const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step]; + return ((4 * abs_mips32(p0 - q0) + abs_mips32(p1 - q1)) <= t); +} + +static WEBP_INLINE int needs_filter2(const uint8_t* p, + int step, int t, int it) { + const int p3 = p[-4 * step], p2 = p[-3 * step]; + const int p1 = p[-2 * step], p0 = p[-step]; + const int q0 = p[0], q1 = p[step], q2 = p[2 * step], q3 = p[3 * step]; + if ((4 * abs_mips32(p0 - q0) + abs_mips32(p1 - q1)) > t) { + return 0; + } + return abs_mips32(p3 - p2) <= it && abs_mips32(p2 - p1) <= it && + abs_mips32(p1 - p0) <= it && abs_mips32(q3 - q2) <= it && + abs_mips32(q2 - q1) <= it && abs_mips32(q1 - q0) <= it; +} + +static WEBP_INLINE void FilterLoop26(uint8_t* p, + int hstride, int vstride, int size, + int thresh, int ithresh, int hev_thresh) { + const int thresh2 = 2 * thresh + 1; + while (size-- > 0) { + if (needs_filter2(p, hstride, thresh2, ithresh)) { + if (hev(p, hstride, hev_thresh)) { + do_filter2(p, hstride); + } else { + do_filter6(p, hstride); + } + } + p += vstride; + } +} + +static WEBP_INLINE void FilterLoop24(uint8_t* p, + int hstride, int vstride, int size, + int thresh, int ithresh, int hev_thresh) { + const int thresh2 = 2 * thresh + 1; + while (size-- > 0) { + if (needs_filter2(p, hstride, thresh2, ithresh)) { + if (hev(p, hstride, hev_thresh)) { + do_filter2(p, hstride); + } else { + do_filter4(p, hstride); + } + } + p += vstride; + } +} + +// on macroblock edges +static void VFilter16(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop26(p, stride, 1, 16, thresh, ithresh, hev_thresh); +} + +static void HFilter16(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop26(p, 1, stride, 16, thresh, ithresh, hev_thresh); +} + +// 8-pixels wide variant, for chroma filtering +static void VFilter8(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop26(u, stride, 1, 8, thresh, ithresh, hev_thresh); + FilterLoop26(v, stride, 1, 8, thresh, ithresh, hev_thresh); +} + +static void HFilter8(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop26(u, 1, stride, 8, thresh, ithresh, hev_thresh); + FilterLoop26(v, 1, stride, 8, thresh, ithresh, hev_thresh); +} + +static void VFilter8i(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop24(u + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh); + FilterLoop24(v + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh); +} + +static void HFilter8i(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop24(u + 4, 1, stride, 8, thresh, ithresh, hev_thresh); + FilterLoop24(v + 4, 1, stride, 8, thresh, ithresh, hev_thresh); +} + +// on three inner edges +static void VFilter16i(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + int k; + for (k = 3; k > 0; --k) { + p += 4 * stride; + FilterLoop24(p, stride, 1, 16, thresh, ithresh, hev_thresh); + } +} + +static void HFilter16i(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + int k; + for (k = 3; k > 0; --k) { + p += 4; + FilterLoop24(p, 1, stride, 16, thresh, ithresh, hev_thresh); + } +} + +//------------------------------------------------------------------------------ +// Simple In-loop filtering (Paragraph 15.2) + +static void SimpleVFilter16(uint8_t* p, int stride, int thresh) { + int i; + const int thresh2 = 2 * thresh + 1; + for (i = 0; i < 16; ++i) { + if (needs_filter(p + i, stride, thresh2)) { + do_filter2(p + i, stride); + } + } +} + +static void SimpleHFilter16(uint8_t* p, int stride, int thresh) { + int i; + const int thresh2 = 2 * thresh + 1; + for (i = 0; i < 16; ++i) { + if (needs_filter(p + i * stride, 1, thresh2)) { + do_filter2(p + i * stride, 1); + } + } +} + +static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) { + int k; + for (k = 3; k > 0; --k) { + p += 4 * stride; + SimpleVFilter16(p, stride, thresh); + } +} + +static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) { + int k; + for (k = 3; k > 0; --k) { + p += 4; + SimpleHFilter16(p, stride, thresh); + } +} + +static void TransformOne(const int16_t* in, uint8_t* dst) { + int temp0, temp1, temp2, temp3, temp4; + int temp5, temp6, temp7, temp8, temp9; + int temp10, temp11, temp12, temp13, temp14; + int temp15, temp16, temp17, temp18; + int16_t* p_in = (int16_t*)in; + + // loops unrolled and merged to avoid usage of tmp buffer + // and to reduce number of stalls. MUL macro is written + // in assembler and inlined + __asm__ volatile( + "lh %[temp0], 0(%[in]) \n\t" + "lh %[temp8], 16(%[in]) \n\t" + "lh %[temp4], 8(%[in]) \n\t" + "lh %[temp12], 24(%[in]) \n\t" + "addu %[temp16], %[temp0], %[temp8] \n\t" + "subu %[temp0], %[temp0], %[temp8] \n\t" + "mul %[temp8], %[temp4], %[kC2] \n\t" + "mul %[temp17], %[temp12], %[kC1] \n\t" + "mul %[temp4], %[temp4], %[kC1] \n\t" + "mul %[temp12], %[temp12], %[kC2] \n\t" + "lh %[temp1], 2(%[in]) \n\t" + "lh %[temp5], 10(%[in]) \n\t" + "lh %[temp9], 18(%[in]) \n\t" + "lh %[temp13], 26(%[in]) \n\t" + "sra %[temp8], %[temp8], 16 \n\t" + "sra %[temp17], %[temp17], 16 \n\t" + "sra %[temp4], %[temp4], 16 \n\t" + "sra %[temp12], %[temp12], 16 \n\t" + "lh %[temp2], 4(%[in]) \n\t" + "lh %[temp6], 12(%[in]) \n\t" + "lh %[temp10], 20(%[in]) \n\t" + "lh %[temp14], 28(%[in]) \n\t" + "subu %[temp17], %[temp8], %[temp17] \n\t" + "addu %[temp4], %[temp4], %[temp12] \n\t" + "addu %[temp8], %[temp16], %[temp4] \n\t" + "subu %[temp4], %[temp16], %[temp4] \n\t" + "addu %[temp16], %[temp1], %[temp9] \n\t" + "subu %[temp1], %[temp1], %[temp9] \n\t" + "lh %[temp3], 6(%[in]) \n\t" + "lh %[temp7], 14(%[in]) \n\t" + "lh %[temp11], 22(%[in]) \n\t" + "lh %[temp15], 30(%[in]) \n\t" + "addu %[temp12], %[temp0], %[temp17] \n\t" + "subu %[temp0], %[temp0], %[temp17] \n\t" + "mul %[temp9], %[temp5], %[kC2] \n\t" + "mul %[temp17], %[temp13], %[kC1] \n\t" + "mul %[temp5], %[temp5], %[kC1] \n\t" + "mul %[temp13], %[temp13], %[kC2] \n\t" + "sra %[temp9], %[temp9], 16 \n\t" + "sra %[temp17], %[temp17], 16 \n\t" + "subu %[temp17], %[temp9], %[temp17] \n\t" + "sra %[temp5], %[temp5], 16 \n\t" + "sra %[temp13], %[temp13], 16 \n\t" + "addu %[temp5], %[temp5], %[temp13] \n\t" + "addu %[temp13], %[temp1], %[temp17] \n\t" + "subu %[temp1], %[temp1], %[temp17] \n\t" + "mul %[temp17], %[temp14], %[kC1] \n\t" + "mul %[temp14], %[temp14], %[kC2] \n\t" + "addu %[temp9], %[temp16], %[temp5] \n\t" + "subu %[temp5], %[temp16], %[temp5] \n\t" + "addu %[temp16], %[temp2], %[temp10] \n\t" + "subu %[temp2], %[temp2], %[temp10] \n\t" + "mul %[temp10], %[temp6], %[kC2] \n\t" + "mul %[temp6], %[temp6], %[kC1] \n\t" + "sra %[temp17], %[temp17], 16 \n\t" + "sra %[temp14], %[temp14], 16 \n\t" + "sra %[temp10], %[temp10], 16 \n\t" + "sra %[temp6], %[temp6], 16 \n\t" + "subu %[temp17], %[temp10], %[temp17] \n\t" + "addu %[temp6], %[temp6], %[temp14] \n\t" + "addu %[temp10], %[temp16], %[temp6] \n\t" + "subu %[temp6], %[temp16], %[temp6] \n\t" + "addu %[temp14], %[temp2], %[temp17] \n\t" + "subu %[temp2], %[temp2], %[temp17] \n\t" + "mul %[temp17], %[temp15], %[kC1] \n\t" + "mul %[temp15], %[temp15], %[kC2] \n\t" + "addu %[temp16], %[temp3], %[temp11] \n\t" + "subu %[temp3], %[temp3], %[temp11] \n\t" + "mul %[temp11], %[temp7], %[kC2] \n\t" + "mul %[temp7], %[temp7], %[kC1] \n\t" + "addiu %[temp8], %[temp8], 4 \n\t" + "addiu %[temp12], %[temp12], 4 \n\t" + "addiu %[temp0], %[temp0], 4 \n\t" + "addiu %[temp4], %[temp4], 4 \n\t" + "sra %[temp17], %[temp17], 16 \n\t" + "sra %[temp15], %[temp15], 16 \n\t" + "sra %[temp11], %[temp11], 16 \n\t" + "sra %[temp7], %[temp7], 16 \n\t" + "subu %[temp17], %[temp11], %[temp17] \n\t" + "addu %[temp7], %[temp7], %[temp15] \n\t" + "addu %[temp15], %[temp3], %[temp17] \n\t" + "subu %[temp3], %[temp3], %[temp17] \n\t" + "addu %[temp11], %[temp16], %[temp7] \n\t" + "subu %[temp7], %[temp16], %[temp7] \n\t" + "addu %[temp16], %[temp8], %[temp10] \n\t" + "subu %[temp8], %[temp8], %[temp10] \n\t" + "mul %[temp10], %[temp9], %[kC2] \n\t" + "mul %[temp17], %[temp11], %[kC1] \n\t" + "mul %[temp9], %[temp9], %[kC1] \n\t" + "mul %[temp11], %[temp11], %[kC2] \n\t" + "sra %[temp10], %[temp10], 16 \n\t" + "sra %[temp17], %[temp17], 16 \n\t" + "sra %[temp9], %[temp9], 16 \n\t" + "sra %[temp11], %[temp11], 16 \n\t" + "subu %[temp17], %[temp10], %[temp17] \n\t" + "addu %[temp11], %[temp9], %[temp11] \n\t" + "addu %[temp10], %[temp12], %[temp14] \n\t" + "subu %[temp12], %[temp12], %[temp14] \n\t" + "mul %[temp14], %[temp13], %[kC2] \n\t" + "mul %[temp9], %[temp15], %[kC1] \n\t" + "mul %[temp13], %[temp13], %[kC1] \n\t" + "mul %[temp15], %[temp15], %[kC2] \n\t" + "sra %[temp14], %[temp14], 16 \n\t" + "sra %[temp9], %[temp9], 16 \n\t" + "sra %[temp13], %[temp13], 16 \n\t" + "sra %[temp15], %[temp15], 16 \n\t" + "subu %[temp9], %[temp14], %[temp9] \n\t" + "addu %[temp15], %[temp13], %[temp15] \n\t" + "addu %[temp14], %[temp0], %[temp2] \n\t" + "subu %[temp0], %[temp0], %[temp2] \n\t" + "mul %[temp2], %[temp1], %[kC2] \n\t" + "mul %[temp13], %[temp3], %[kC1] \n\t" + "mul %[temp1], %[temp1], %[kC1] \n\t" + "mul %[temp3], %[temp3], %[kC2] \n\t" + "sra %[temp2], %[temp2], 16 \n\t" + "sra %[temp13], %[temp13], 16 \n\t" + "sra %[temp1], %[temp1], 16 \n\t" + "sra %[temp3], %[temp3], 16 \n\t" + "subu %[temp13], %[temp2], %[temp13] \n\t" + "addu %[temp3], %[temp1], %[temp3] \n\t" + "addu %[temp2], %[temp4], %[temp6] \n\t" + "subu %[temp4], %[temp4], %[temp6] \n\t" + "mul %[temp6], %[temp5], %[kC2] \n\t" + "mul %[temp1], %[temp7], %[kC1] \n\t" + "mul %[temp5], %[temp5], %[kC1] \n\t" + "mul %[temp7], %[temp7], %[kC2] \n\t" + "sra %[temp6], %[temp6], 16 \n\t" + "sra %[temp1], %[temp1], 16 \n\t" + "sra %[temp5], %[temp5], 16 \n\t" + "sra %[temp7], %[temp7], 16 \n\t" + "subu %[temp1], %[temp6], %[temp1] \n\t" + "addu %[temp7], %[temp5], %[temp7] \n\t" + "addu %[temp5], %[temp16], %[temp11] \n\t" + "subu %[temp16], %[temp16], %[temp11] \n\t" + "addu %[temp11], %[temp8], %[temp17] \n\t" + "subu %[temp8], %[temp8], %[temp17] \n\t" + "sra %[temp5], %[temp5], 3 \n\t" + "sra %[temp16], %[temp16], 3 \n\t" + "sra %[temp11], %[temp11], 3 \n\t" + "sra %[temp8], %[temp8], 3 \n\t" + "addu %[temp17], %[temp10], %[temp15] \n\t" + "subu %[temp10], %[temp10], %[temp15] \n\t" + "addu %[temp15], %[temp12], %[temp9] \n\t" + "subu %[temp12], %[temp12], %[temp9] \n\t" + "sra %[temp17], %[temp17], 3 \n\t" + "sra %[temp10], %[temp10], 3 \n\t" + "sra %[temp15], %[temp15], 3 \n\t" + "sra %[temp12], %[temp12], 3 \n\t" + "addu %[temp9], %[temp14], %[temp3] \n\t" + "subu %[temp14], %[temp14], %[temp3] \n\t" + "addu %[temp3], %[temp0], %[temp13] \n\t" + "subu %[temp0], %[temp0], %[temp13] \n\t" + "sra %[temp9], %[temp9], 3 \n\t" + "sra %[temp14], %[temp14], 3 \n\t" + "sra %[temp3], %[temp3], 3 \n\t" + "sra %[temp0], %[temp0], 3 \n\t" + "addu %[temp13], %[temp2], %[temp7] \n\t" + "subu %[temp2], %[temp2], %[temp7] \n\t" + "addu %[temp7], %[temp4], %[temp1] \n\t" + "subu %[temp4], %[temp4], %[temp1] \n\t" + "sra %[temp13], %[temp13], 3 \n\t" + "sra %[temp2], %[temp2], 3 \n\t" + "sra %[temp7], %[temp7], 3 \n\t" + "sra %[temp4], %[temp4], 3 \n\t" + "addiu %[temp6], $zero, 255 \n\t" + "lbu %[temp1], 0+0*" XSTR(BPS) "(%[dst]) \n\t" + "addu %[temp1], %[temp1], %[temp5] \n\t" + "sra %[temp5], %[temp1], 8 \n\t" + "sra %[temp18], %[temp1], 31 \n\t" + "beqz %[temp5], 1f \n\t" + "xor %[temp1], %[temp1], %[temp1] \n\t" + "movz %[temp1], %[temp6], %[temp18] \n\t" + "1: \n\t" + "lbu %[temp18], 1+0*" XSTR(BPS) "(%[dst]) \n\t" + "sb %[temp1], 0+0*" XSTR(BPS) "(%[dst]) \n\t" + "addu %[temp18], %[temp18], %[temp11] \n\t" + "sra %[temp11], %[temp18], 8 \n\t" + "sra %[temp1], %[temp18], 31 \n\t" + "beqz %[temp11], 2f \n\t" + "xor %[temp18], %[temp18], %[temp18] \n\t" + "movz %[temp18], %[temp6], %[temp1] \n\t" + "2: \n\t" + "lbu %[temp1], 2+0*" XSTR(BPS) "(%[dst]) \n\t" + "sb %[temp18], 1+0*" XSTR(BPS) "(%[dst]) \n\t" + "addu %[temp1], %[temp1], %[temp8] \n\t" + "sra %[temp8], %[temp1], 8 \n\t" + "sra %[temp18], %[temp1], 31 \n\t" + "beqz %[temp8], 3f \n\t" + "xor %[temp1], %[temp1], %[temp1] \n\t" + "movz %[temp1], %[temp6], %[temp18] \n\t" + "3: \n\t" + "lbu %[temp18], 3+0*" XSTR(BPS) "(%[dst]) \n\t" + "sb %[temp1], 2+0*" XSTR(BPS) "(%[dst]) \n\t" + "addu %[temp18], %[temp18], %[temp16] \n\t" + "sra %[temp16], %[temp18], 8 \n\t" + "sra %[temp1], %[temp18], 31 \n\t" + "beqz %[temp16], 4f \n\t" + "xor %[temp18], %[temp18], %[temp18] \n\t" + "movz %[temp18], %[temp6], %[temp1] \n\t" + "4: \n\t" + "sb %[temp18], 3+0*" XSTR(BPS) "(%[dst]) \n\t" + "lbu %[temp5], 0+1*" XSTR(BPS) "(%[dst]) \n\t" + "lbu %[temp8], 1+1*" XSTR(BPS) "(%[dst]) \n\t" + "lbu %[temp11], 2+1*" XSTR(BPS) "(%[dst]) \n\t" + "lbu %[temp16], 3+1*" XSTR(BPS) "(%[dst]) \n\t" + "addu %[temp5], %[temp5], %[temp17] \n\t" + "addu %[temp8], %[temp8], %[temp15] \n\t" + "addu %[temp11], %[temp11], %[temp12] \n\t" + "addu %[temp16], %[temp16], %[temp10] \n\t" + "sra %[temp18], %[temp5], 8 \n\t" + "sra %[temp1], %[temp5], 31 \n\t" + "beqz %[temp18], 5f \n\t" + "xor %[temp5], %[temp5], %[temp5] \n\t" + "movz %[temp5], %[temp6], %[temp1] \n\t" + "5: \n\t" + "sra %[temp18], %[temp8], 8 \n\t" + "sra %[temp1], %[temp8], 31 \n\t" + "beqz %[temp18], 6f \n\t" + "xor %[temp8], %[temp8], %[temp8] \n\t" + "movz %[temp8], %[temp6], %[temp1] \n\t" + "6: \n\t" + "sra %[temp18], %[temp11], 8 \n\t" + "sra %[temp1], %[temp11], 31 \n\t" + "sra %[temp17], %[temp16], 8 \n\t" + "sra %[temp15], %[temp16], 31 \n\t" + "beqz %[temp18], 7f \n\t" + "xor %[temp11], %[temp11], %[temp11] \n\t" + "movz %[temp11], %[temp6], %[temp1] \n\t" + "7: \n\t" + "beqz %[temp17], 8f \n\t" + "xor %[temp16], %[temp16], %[temp16] \n\t" + "movz %[temp16], %[temp6], %[temp15] \n\t" + "8: \n\t" + "sb %[temp5], 0+1*" XSTR(BPS) "(%[dst]) \n\t" + "sb %[temp8], 1+1*" XSTR(BPS) "(%[dst]) \n\t" + "sb %[temp11], 2+1*" XSTR(BPS) "(%[dst]) \n\t" + "sb %[temp16], 3+1*" XSTR(BPS) "(%[dst]) \n\t" + "lbu %[temp5], 0+2*" XSTR(BPS) "(%[dst]) \n\t" + "lbu %[temp8], 1+2*" XSTR(BPS) "(%[dst]) \n\t" + "lbu %[temp11], 2+2*" XSTR(BPS) "(%[dst]) \n\t" + "lbu %[temp16], 3+2*" XSTR(BPS) "(%[dst]) \n\t" + "addu %[temp5], %[temp5], %[temp9] \n\t" + "addu %[temp8], %[temp8], %[temp3] \n\t" + "addu %[temp11], %[temp11], %[temp0] \n\t" + "addu %[temp16], %[temp16], %[temp14] \n\t" + "sra %[temp18], %[temp5], 8 \n\t" + "sra %[temp1], %[temp5], 31 \n\t" + "sra %[temp17], %[temp8], 8 \n\t" + "sra %[temp15], %[temp8], 31 \n\t" + "sra %[temp12], %[temp11], 8 \n\t" + "sra %[temp10], %[temp11], 31 \n\t" + "sra %[temp9], %[temp16], 8 \n\t" + "sra %[temp3], %[temp16], 31 \n\t" + "beqz %[temp18], 9f \n\t" + "xor %[temp5], %[temp5], %[temp5] \n\t" + "movz %[temp5], %[temp6], %[temp1] \n\t" + "9: \n\t" + "beqz %[temp17], 10f \n\t" + "xor %[temp8], %[temp8], %[temp8] \n\t" + "movz %[temp8], %[temp6], %[temp15] \n\t" + "10: \n\t" + "beqz %[temp12], 11f \n\t" + "xor %[temp11], %[temp11], %[temp11] \n\t" + "movz %[temp11], %[temp6], %[temp10] \n\t" + "11: \n\t" + "beqz %[temp9], 12f \n\t" + "xor %[temp16], %[temp16], %[temp16] \n\t" + "movz %[temp16], %[temp6], %[temp3] \n\t" + "12: \n\t" + "sb %[temp5], 0+2*" XSTR(BPS) "(%[dst]) \n\t" + "sb %[temp8], 1+2*" XSTR(BPS) "(%[dst]) \n\t" + "sb %[temp11], 2+2*" XSTR(BPS) "(%[dst]) \n\t" + "sb %[temp16], 3+2*" XSTR(BPS) "(%[dst]) \n\t" + "lbu %[temp5], 0+3*" XSTR(BPS) "(%[dst]) \n\t" + "lbu %[temp8], 1+3*" XSTR(BPS) "(%[dst]) \n\t" + "lbu %[temp11], 2+3*" XSTR(BPS) "(%[dst]) \n\t" + "lbu %[temp16], 3+3*" XSTR(BPS) "(%[dst]) \n\t" + "addu %[temp5], %[temp5], %[temp13] \n\t" + "addu %[temp8], %[temp8], %[temp7] \n\t" + "addu %[temp11], %[temp11], %[temp4] \n\t" + "addu %[temp16], %[temp16], %[temp2] \n\t" + "sra %[temp18], %[temp5], 8 \n\t" + "sra %[temp1], %[temp5], 31 \n\t" + "sra %[temp17], %[temp8], 8 \n\t" + "sra %[temp15], %[temp8], 31 \n\t" + "sra %[temp12], %[temp11], 8 \n\t" + "sra %[temp10], %[temp11], 31 \n\t" + "sra %[temp9], %[temp16], 8 \n\t" + "sra %[temp3], %[temp16], 31 \n\t" + "beqz %[temp18], 13f \n\t" + "xor %[temp5], %[temp5], %[temp5] \n\t" + "movz %[temp5], %[temp6], %[temp1] \n\t" + "13: \n\t" + "beqz %[temp17], 14f \n\t" + "xor %[temp8], %[temp8], %[temp8] \n\t" + "movz %[temp8], %[temp6], %[temp15] \n\t" + "14: \n\t" + "beqz %[temp12], 15f \n\t" + "xor %[temp11], %[temp11], %[temp11] \n\t" + "movz %[temp11], %[temp6], %[temp10] \n\t" + "15: \n\t" + "beqz %[temp9], 16f \n\t" + "xor %[temp16], %[temp16], %[temp16] \n\t" + "movz %[temp16], %[temp6], %[temp3] \n\t" + "16: \n\t" + "sb %[temp5], 0+3*" XSTR(BPS) "(%[dst]) \n\t" + "sb %[temp8], 1+3*" XSTR(BPS) "(%[dst]) \n\t" + "sb %[temp11], 2+3*" XSTR(BPS) "(%[dst]) \n\t" + "sb %[temp16], 3+3*" XSTR(BPS) "(%[dst]) \n\t" + + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), + [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11), + [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), [temp14]"=&r"(temp14), + [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), [temp17]"=&r"(temp17), + [temp18]"=&r"(temp18) + : [in]"r"(p_in), [kC1]"r"(kC1), [kC2]"r"(kC2), [dst]"r"(dst) + : "memory", "hi", "lo" + ); +} + +static void TransformTwo(const int16_t* in, uint8_t* dst, int do_two) { + TransformOne(in, dst); + if (do_two) { + TransformOne(in + 16, dst + 4); + } +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8DspInitMIPS32(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitMIPS32(void) { + VP8InitClipTables(); + + VP8Transform = TransformTwo; + + VP8VFilter16 = VFilter16; + VP8HFilter16 = HFilter16; + VP8VFilter8 = VFilter8; + VP8HFilter8 = HFilter8; + VP8VFilter16i = VFilter16i; + VP8HFilter16i = HFilter16i; + VP8VFilter8i = VFilter8i; + VP8HFilter8i = HFilter8i; + + VP8SimpleVFilter16 = SimpleVFilter16; + VP8SimpleHFilter16 = SimpleHFilter16; + VP8SimpleVFilter16i = SimpleVFilter16i; + VP8SimpleHFilter16i = SimpleHFilter16i; +} + +#else // !WEBP_USE_MIPS32 + +WEBP_DSP_INIT_STUB(VP8DspInitMIPS32) + +#endif // WEBP_USE_MIPS32 diff --git a/third-party/webp/libwebp/src/dsp/dec_mips_dsp_r2.c b/third-party/webp/libwebp/src/dsp/dec_mips_dsp_r2.c new file mode 100644 index 0000000000..b0936bc46e --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/dec_mips_dsp_r2.c @@ -0,0 +1,994 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MIPS version of dsp functions +// +// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) +// Jovan Zelincevic (jovan.zelincevic@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MIPS_DSP_R2) + +#include "src/dsp/mips_macro.h" + +static const int kC1 = 20091 + (1 << 16); +static const int kC2 = 35468; + +#define MUL(a, b) (((a) * (b)) >> 16) + +static void TransformDC(const int16_t* in, uint8_t* dst) { + int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9, temp10; + + __asm__ volatile ( + LOAD_WITH_OFFSET_X4(temp1, temp2, temp3, temp4, dst, + 0, 0, 0, 0, + 0, 1, 2, 3, + BPS) + "lh %[temp5], 0(%[in]) \n\t" + "addiu %[temp5], %[temp5], 4 \n\t" + "ins %[temp5], %[temp5], 16, 16 \n\t" + "shra.ph %[temp5], %[temp5], 3 \n\t" + CONVERT_2_BYTES_TO_HALF(temp6, temp7, temp8, temp9, temp10, temp1, temp2, + temp3, temp1, temp2, temp3, temp4) + STORE_SAT_SUM_X2(temp6, temp7, temp8, temp9, temp10, temp1, temp2, temp3, + temp5, temp5, temp5, temp5, temp5, temp5, temp5, temp5, + dst, 0, 1, 2, 3, BPS) + + OUTPUT_EARLY_CLOBBER_REGS_10() + : [in]"r"(in), [dst]"r"(dst) + : "memory" + ); +} + +static void TransformAC3(const int16_t* in, uint8_t* dst) { + const int a = in[0] + 4; + int c4 = MUL(in[4], kC2); + const int d4 = MUL(in[4], kC1); + const int c1 = MUL(in[1], kC2); + const int d1 = MUL(in[1], kC1); + int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9; + int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17, temp18; + + __asm__ volatile ( + "ins %[c4], %[d4], 16, 16 \n\t" + "replv.ph %[temp1], %[a] \n\t" + "replv.ph %[temp4], %[d1] \n\t" + ADD_SUB_HALVES(temp2, temp3, temp1, c4) + "replv.ph %[temp5], %[c1] \n\t" + SHIFT_R_SUM_X2(temp1, temp6, temp7, temp8, temp2, temp9, temp10, temp4, + temp2, temp2, temp3, temp3, temp4, temp5, temp4, temp5) + LOAD_WITH_OFFSET_X4(temp3, temp5, temp11, temp12, dst, + 0, 0, 0, 0, + 0, 1, 2, 3, + BPS) + CONVERT_2_BYTES_TO_HALF(temp13, temp14, temp3, temp15, temp5, temp16, + temp11, temp17, temp3, temp5, temp11, temp12) + PACK_2_HALVES_TO_WORD(temp12, temp18, temp7, temp6, temp1, temp8, temp2, + temp4, temp7, temp6, temp10, temp9) + STORE_SAT_SUM_X2(temp13, temp14, temp3, temp15, temp5, temp16, temp11, + temp17, temp12, temp18, temp1, temp8, temp2, temp4, + temp7, temp6, dst, 0, 1, 2, 3, BPS) + + OUTPUT_EARLY_CLOBBER_REGS_18(), + [c4]"+&r"(c4) + : [dst]"r"(dst), [a]"r"(a), [d1]"r"(d1), [d4]"r"(d4), [c1]"r"(c1) + : "memory" + ); +} + +static void TransformOne(const int16_t* in, uint8_t* dst) { + int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9; + int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17, temp18; + + __asm__ volatile ( + "ulw %[temp1], 0(%[in]) \n\t" + "ulw %[temp2], 16(%[in]) \n\t" + LOAD_IN_X2(temp5, temp6, 24, 26) + ADD_SUB_HALVES(temp3, temp4, temp1, temp2) + LOAD_IN_X2(temp1, temp2, 8, 10) + MUL_SHIFT_SUM(temp7, temp8, temp9, temp10, temp11, temp12, temp13, temp14, + temp10, temp8, temp9, temp7, temp1, temp2, temp5, temp6, + temp13, temp11, temp14, temp12) + INSERT_HALF_X2(temp8, temp7, temp10, temp9) + "ulw %[temp17], 4(%[in]) \n\t" + "ulw %[temp18], 20(%[in]) \n\t" + ADD_SUB_HALVES(temp1, temp2, temp3, temp8) + ADD_SUB_HALVES(temp5, temp6, temp4, temp7) + ADD_SUB_HALVES(temp7, temp8, temp17, temp18) + LOAD_IN_X2(temp17, temp18, 12, 14) + LOAD_IN_X2(temp9, temp10, 28, 30) + MUL_SHIFT_SUM(temp11, temp12, temp13, temp14, temp15, temp16, temp4, temp17, + temp12, temp14, temp11, temp13, temp17, temp18, temp9, temp10, + temp15, temp4, temp16, temp17) + INSERT_HALF_X2(temp11, temp12, temp13, temp14) + ADD_SUB_HALVES(temp17, temp8, temp8, temp11) + ADD_SUB_HALVES(temp3, temp4, temp7, temp12) + + // horizontal + SRA_16(temp9, temp10, temp11, temp12, temp1, temp2, temp5, temp6) + INSERT_HALF_X2(temp1, temp6, temp5, temp2) + SRA_16(temp13, temp14, temp15, temp16, temp3, temp4, temp17, temp8) + "repl.ph %[temp2], 0x4 \n\t" + INSERT_HALF_X2(temp3, temp8, temp17, temp4) + "addq.ph %[temp1], %[temp1], %[temp2] \n\t" + "addq.ph %[temp6], %[temp6], %[temp2] \n\t" + ADD_SUB_HALVES(temp2, temp4, temp1, temp3) + ADD_SUB_HALVES(temp5, temp7, temp6, temp8) + MUL_SHIFT_SUM(temp1, temp3, temp6, temp8, temp9, temp13, temp17, temp18, + temp3, temp13, temp1, temp9, temp9, temp13, temp11, temp15, + temp6, temp17, temp8, temp18) + MUL_SHIFT_SUM(temp6, temp8, temp18, temp17, temp11, temp15, temp12, temp16, + temp8, temp15, temp6, temp11, temp12, temp16, temp10, temp14, + temp18, temp12, temp17, temp16) + INSERT_HALF_X2(temp1, temp3, temp9, temp13) + INSERT_HALF_X2(temp6, temp8, temp11, temp15) + SHIFT_R_SUM_X2(temp9, temp10, temp11, temp12, temp13, temp14, temp15, + temp16, temp2, temp4, temp5, temp7, temp3, temp1, temp8, + temp6) + PACK_2_HALVES_TO_WORD(temp1, temp2, temp3, temp4, temp9, temp12, temp13, + temp16, temp11, temp10, temp15, temp14) + LOAD_WITH_OFFSET_X4(temp10, temp11, temp14, temp15, dst, + 0, 0, 0, 0, + 0, 1, 2, 3, + BPS) + CONVERT_2_BYTES_TO_HALF(temp5, temp6, temp7, temp8, temp17, temp18, temp10, + temp11, temp10, temp11, temp14, temp15) + STORE_SAT_SUM_X2(temp5, temp6, temp7, temp8, temp17, temp18, temp10, temp11, + temp9, temp12, temp1, temp2, temp13, temp16, temp3, temp4, + dst, 0, 1, 2, 3, BPS) + + OUTPUT_EARLY_CLOBBER_REGS_18() + : [dst]"r"(dst), [in]"r"(in), [kC1]"r"(kC1), [kC2]"r"(kC2) + : "memory", "hi", "lo" + ); +} + +static void TransformTwo(const int16_t* in, uint8_t* dst, int do_two) { + TransformOne(in, dst); + if (do_two) { + TransformOne(in + 16, dst + 4); + } +} + +static WEBP_INLINE void FilterLoop26(uint8_t* p, + int hstride, int vstride, int size, + int thresh, int ithresh, int hev_thresh) { + const int thresh2 = 2 * thresh + 1; + int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9; + int temp10, temp11, temp12, temp13, temp14, temp15; + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "1: \n\t" + "negu %[temp1], %[hstride] \n\t" + "addiu %[size], %[size], -1 \n\t" + "sll %[temp2], %[hstride], 1 \n\t" + "sll %[temp3], %[temp1], 1 \n\t" + "addu %[temp4], %[temp2], %[hstride] \n\t" + "addu %[temp5], %[temp3], %[temp1] \n\t" + "lbu %[temp7], 0(%[p]) \n\t" + "sll %[temp6], %[temp3], 1 \n\t" + "lbux %[temp8], %[temp5](%[p]) \n\t" + "lbux %[temp9], %[temp3](%[p]) \n\t" + "lbux %[temp10], %[temp1](%[p]) \n\t" + "lbux %[temp11], %[temp6](%[p]) \n\t" + "lbux %[temp12], %[hstride](%[p]) \n\t" + "lbux %[temp13], %[temp2](%[p]) \n\t" + "lbux %[temp14], %[temp4](%[p]) \n\t" + "subu %[temp1], %[temp10], %[temp7] \n\t" + "subu %[temp2], %[temp9], %[temp12] \n\t" + "absq_s.w %[temp3], %[temp1] \n\t" + "absq_s.w %[temp4], %[temp2] \n\t" + "negu %[temp1], %[temp1] \n\t" + "sll %[temp3], %[temp3], 2 \n\t" + "addu %[temp15], %[temp3], %[temp4] \n\t" + "subu %[temp3], %[temp15], %[thresh2] \n\t" + "sll %[temp6], %[temp1], 1 \n\t" + "bgtz %[temp3], 3f \n\t" + " subu %[temp4], %[temp11], %[temp8] \n\t" + "absq_s.w %[temp4], %[temp4] \n\t" + "shll_s.w %[temp2], %[temp2], 24 \n\t" + "subu %[temp4], %[temp4], %[ithresh] \n\t" + "bgtz %[temp4], 3f \n\t" + " subu %[temp3], %[temp8], %[temp9] \n\t" + "absq_s.w %[temp3], %[temp3] \n\t" + "subu %[temp3], %[temp3], %[ithresh] \n\t" + "bgtz %[temp3], 3f \n\t" + " subu %[temp5], %[temp9], %[temp10] \n\t" + "absq_s.w %[temp3], %[temp5] \n\t" + "absq_s.w %[temp5], %[temp5] \n\t" + "subu %[temp3], %[temp3], %[ithresh] \n\t" + "bgtz %[temp3], 3f \n\t" + " subu %[temp3], %[temp14], %[temp13] \n\t" + "absq_s.w %[temp3], %[temp3] \n\t" + "slt %[temp5], %[hev_thresh], %[temp5] \n\t" + "subu %[temp3], %[temp3], %[ithresh] \n\t" + "bgtz %[temp3], 3f \n\t" + " subu %[temp3], %[temp13], %[temp12] \n\t" + "absq_s.w %[temp3], %[temp3] \n\t" + "sra %[temp4], %[temp2], 24 \n\t" + "subu %[temp3], %[temp3], %[ithresh] \n\t" + "bgtz %[temp3], 3f \n\t" + " subu %[temp15], %[temp12], %[temp7] \n\t" + "absq_s.w %[temp3], %[temp15] \n\t" + "absq_s.w %[temp15], %[temp15] \n\t" + "subu %[temp3], %[temp3], %[ithresh] \n\t" + "bgtz %[temp3], 3f \n\t" + " slt %[temp15], %[hev_thresh], %[temp15] \n\t" + "addu %[temp3], %[temp6], %[temp1] \n\t" + "or %[temp2], %[temp5], %[temp15] \n\t" + "addu %[temp5], %[temp4], %[temp3] \n\t" + "beqz %[temp2], 4f \n\t" + " shra_r.w %[temp1], %[temp5], 3 \n\t" + "addiu %[temp2], %[temp5], 3 \n\t" + "sra %[temp2], %[temp2], 3 \n\t" + "shll_s.w %[temp1], %[temp1], 27 \n\t" + "shll_s.w %[temp2], %[temp2], 27 \n\t" + "subu %[temp3], %[p], %[hstride] \n\t" + "sra %[temp1], %[temp1], 27 \n\t" + "sra %[temp2], %[temp2], 27 \n\t" + "subu %[temp1], %[temp7], %[temp1] \n\t" + "addu %[temp2], %[temp10], %[temp2] \n\t" + "lbux %[temp2], %[temp2](%[VP8kclip1]) \n\t" + "lbux %[temp1], %[temp1](%[VP8kclip1]) \n\t" + "sb %[temp2], 0(%[temp3]) \n\t" + "j 3f \n\t" + " sb %[temp1], 0(%[p]) \n\t" + "4: \n\t" + "shll_s.w %[temp5], %[temp5], 24 \n\t" + "subu %[temp14], %[p], %[hstride] \n\t" + "subu %[temp11], %[temp14], %[hstride] \n\t" + "sra %[temp6], %[temp5], 24 \n\t" + "sll %[temp1], %[temp6], 3 \n\t" + "subu %[temp15], %[temp11], %[hstride] \n\t" + "addu %[temp2], %[temp6], %[temp1] \n\t" + "sll %[temp3], %[temp2], 1 \n\t" + "addu %[temp4], %[temp3], %[temp2] \n\t" + "addiu %[temp2], %[temp2], 63 \n\t" + "addiu %[temp3], %[temp3], 63 \n\t" + "addiu %[temp4], %[temp4], 63 \n\t" + "sra %[temp2], %[temp2], 7 \n\t" + "sra %[temp3], %[temp3], 7 \n\t" + "sra %[temp4], %[temp4], 7 \n\t" + "addu %[temp1], %[temp8], %[temp2] \n\t" + "addu %[temp5], %[temp9], %[temp3] \n\t" + "addu %[temp6], %[temp10], %[temp4] \n\t" + "subu %[temp8], %[temp7], %[temp4] \n\t" + "subu %[temp7], %[temp12], %[temp3] \n\t" + "addu %[temp10], %[p], %[hstride] \n\t" + "subu %[temp9], %[temp13], %[temp2] \n\t" + "addu %[temp12], %[temp10], %[hstride] \n\t" + "lbux %[temp2], %[temp1](%[VP8kclip1]) \n\t" + "lbux %[temp3], %[temp5](%[VP8kclip1]) \n\t" + "lbux %[temp4], %[temp6](%[VP8kclip1]) \n\t" + "lbux %[temp5], %[temp8](%[VP8kclip1]) \n\t" + "lbux %[temp6], %[temp7](%[VP8kclip1]) \n\t" + "lbux %[temp8], %[temp9](%[VP8kclip1]) \n\t" + "sb %[temp2], 0(%[temp15]) \n\t" + "sb %[temp3], 0(%[temp11]) \n\t" + "sb %[temp4], 0(%[temp14]) \n\t" + "sb %[temp5], 0(%[p]) \n\t" + "sb %[temp6], 0(%[temp10]) \n\t" + "sb %[temp8], 0(%[temp12]) \n\t" + "3: \n\t" + "bgtz %[size], 1b \n\t" + " addu %[p], %[p], %[vstride] \n\t" + ".set pop \n\t" + : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),[temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [temp6]"=&r"(temp6), + [temp7]"=&r"(temp7),[temp8]"=&r"(temp8),[temp9]"=&r"(temp9), + [temp10]"=&r"(temp10),[temp11]"=&r"(temp11),[temp12]"=&r"(temp12), + [temp13]"=&r"(temp13),[temp14]"=&r"(temp14),[temp15]"=&r"(temp15), + [size]"+&r"(size), [p]"+&r"(p) + : [hstride]"r"(hstride), [thresh2]"r"(thresh2), + [ithresh]"r"(ithresh),[vstride]"r"(vstride), [hev_thresh]"r"(hev_thresh), + [VP8kclip1]"r"(VP8kclip1) + : "memory" + ); +} + +static WEBP_INLINE void FilterLoop24(uint8_t* p, + int hstride, int vstride, int size, + int thresh, int ithresh, int hev_thresh) { + int p0, q0, p1, q1, p2, q2, p3, q3; + int step1, step2, temp1, temp2, temp3, temp4; + uint8_t* pTemp0; + uint8_t* pTemp1; + const int thresh2 = 2 * thresh + 1; + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "bltz %[size], 3f \n\t" + " nop \n\t" + "2: \n\t" + "negu %[step1], %[hstride] \n\t" + "lbu %[q0], 0(%[p]) \n\t" + "lbux %[p0], %[step1](%[p]) \n\t" + "subu %[step1], %[step1], %[hstride] \n\t" + "lbux %[q1], %[hstride](%[p]) \n\t" + "subu %[temp1], %[p0], %[q0] \n\t" + "lbux %[p1], %[step1](%[p]) \n\t" + "addu %[step2], %[hstride], %[hstride] \n\t" + "absq_s.w %[temp2], %[temp1] \n\t" + "subu %[temp3], %[p1], %[q1] \n\t" + "absq_s.w %[temp4], %[temp3] \n\t" + "sll %[temp2], %[temp2], 2 \n\t" + "addu %[temp2], %[temp2], %[temp4] \n\t" + "subu %[temp4], %[temp2], %[thresh2] \n\t" + "subu %[step1], %[step1], %[hstride] \n\t" + "bgtz %[temp4], 0f \n\t" + " lbux %[p2], %[step1](%[p]) \n\t" + "subu %[step1], %[step1], %[hstride] \n\t" + "lbux %[q2], %[step2](%[p]) \n\t" + "lbux %[p3], %[step1](%[p]) \n\t" + "subu %[temp4], %[p2], %[p1] \n\t" + "addu %[step2], %[step2], %[hstride] \n\t" + "subu %[temp2], %[p3], %[p2] \n\t" + "absq_s.w %[temp4], %[temp4] \n\t" + "absq_s.w %[temp2], %[temp2] \n\t" + "lbux %[q3], %[step2](%[p]) \n\t" + "subu %[temp4], %[temp4], %[ithresh] \n\t" + "negu %[temp1], %[temp1] \n\t" + "bgtz %[temp4], 0f \n\t" + " subu %[temp2], %[temp2], %[ithresh] \n\t" + "subu %[p3], %[p1], %[p0] \n\t" + "bgtz %[temp2], 0f \n\t" + " absq_s.w %[p3], %[p3] \n\t" + "subu %[temp4], %[q3], %[q2] \n\t" + "subu %[pTemp0], %[p], %[hstride] \n\t" + "absq_s.w %[temp4], %[temp4] \n\t" + "subu %[temp2], %[p3], %[ithresh] \n\t" + "sll %[step1], %[temp1], 1 \n\t" + "bgtz %[temp2], 0f \n\t" + " subu %[temp4], %[temp4], %[ithresh] \n\t" + "subu %[temp2], %[q2], %[q1] \n\t" + "bgtz %[temp4], 0f \n\t" + " absq_s.w %[temp2], %[temp2] \n\t" + "subu %[q3], %[q1], %[q0] \n\t" + "absq_s.w %[q3], %[q3] \n\t" + "subu %[temp2], %[temp2], %[ithresh] \n\t" + "addu %[temp1], %[temp1], %[step1] \n\t" + "bgtz %[temp2], 0f \n\t" + " subu %[temp4], %[q3], %[ithresh] \n\t" + "slt %[p3], %[hev_thresh], %[p3] \n\t" + "bgtz %[temp4], 0f \n\t" + " slt %[q3], %[hev_thresh], %[q3] \n\t" + "or %[q3], %[q3], %[p3] \n\t" + "bgtz %[q3], 1f \n\t" + " shra_r.w %[temp2], %[temp1], 3 \n\t" + "addiu %[temp1], %[temp1], 3 \n\t" + "sra %[temp1], %[temp1], 3 \n\t" + "shll_s.w %[temp2], %[temp2], 27 \n\t" + "shll_s.w %[temp1], %[temp1], 27 \n\t" + "addu %[pTemp1], %[p], %[hstride] \n\t" + "sra %[temp2], %[temp2], 27 \n\t" + "sra %[temp1], %[temp1], 27 \n\t" + "addiu %[step1], %[temp2], 1 \n\t" + "sra %[step1], %[step1], 1 \n\t" + "addu %[p0], %[p0], %[temp1] \n\t" + "addu %[p1], %[p1], %[step1] \n\t" + "subu %[q0], %[q0], %[temp2] \n\t" + "subu %[q1], %[q1], %[step1] \n\t" + "lbux %[temp2], %[p0](%[VP8kclip1]) \n\t" + "lbux %[temp3], %[q0](%[VP8kclip1]) \n\t" + "lbux %[temp4], %[q1](%[VP8kclip1]) \n\t" + "sb %[temp2], 0(%[pTemp0]) \n\t" + "lbux %[temp1], %[p1](%[VP8kclip1]) \n\t" + "subu %[pTemp0], %[pTemp0], %[hstride] \n\t" + "sb %[temp3], 0(%[p]) \n\t" + "sb %[temp4], 0(%[pTemp1]) \n\t" + "j 0f \n\t" + " sb %[temp1], 0(%[pTemp0]) \n\t" + "1: \n\t" + "shll_s.w %[temp3], %[temp3], 24 \n\t" + "sra %[temp3], %[temp3], 24 \n\t" + "addu %[temp1], %[temp1], %[temp3] \n\t" + "shra_r.w %[temp2], %[temp1], 3 \n\t" + "addiu %[temp1], %[temp1], 3 \n\t" + "shll_s.w %[temp2], %[temp2], 27 \n\t" + "sra %[temp1], %[temp1], 3 \n\t" + "shll_s.w %[temp1], %[temp1], 27 \n\t" + "sra %[temp2], %[temp2], 27 \n\t" + "sra %[temp1], %[temp1], 27 \n\t" + "addu %[p0], %[p0], %[temp1] \n\t" + "subu %[q0], %[q0], %[temp2] \n\t" + "lbux %[temp1], %[p0](%[VP8kclip1]) \n\t" + "lbux %[temp2], %[q0](%[VP8kclip1]) \n\t" + "sb %[temp2], 0(%[p]) \n\t" + "sb %[temp1], 0(%[pTemp0]) \n\t" + "0: \n\t" + "subu %[size], %[size], 1 \n\t" + "bgtz %[size], 2b \n\t" + " addu %[p], %[p], %[vstride] \n\t" + "3: \n\t" + ".set pop \n\t" + : [p0]"=&r"(p0), [q0]"=&r"(q0), [p1]"=&r"(p1), [q1]"=&r"(q1), + [p2]"=&r"(p2), [q2]"=&r"(q2), [p3]"=&r"(p3), [q3]"=&r"(q3), + [step2]"=&r"(step2), [step1]"=&r"(step1), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), + [pTemp0]"=&r"(pTemp0), [pTemp1]"=&r"(pTemp1), [p]"+&r"(p), + [size]"+&r"(size) + : [vstride]"r"(vstride), [ithresh]"r"(ithresh), + [hev_thresh]"r"(hev_thresh), [hstride]"r"(hstride), + [VP8kclip1]"r"(VP8kclip1), [thresh2]"r"(thresh2) + : "memory" + ); +} + +// on macroblock edges +static void VFilter16(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop26(p, stride, 1, 16, thresh, ithresh, hev_thresh); +} + +static void HFilter16(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop26(p, 1, stride, 16, thresh, ithresh, hev_thresh); +} + +// 8-pixels wide variant, for chroma filtering +static void VFilter8(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop26(u, stride, 1, 8, thresh, ithresh, hev_thresh); + FilterLoop26(v, stride, 1, 8, thresh, ithresh, hev_thresh); +} + +static void HFilter8(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop26(u, 1, stride, 8, thresh, ithresh, hev_thresh); + FilterLoop26(v, 1, stride, 8, thresh, ithresh, hev_thresh); +} + +// on three inner edges +static void VFilter16i(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + int k; + for (k = 3; k > 0; --k) { + p += 4 * stride; + FilterLoop24(p, stride, 1, 16, thresh, ithresh, hev_thresh); + } +} + +static void HFilter16i(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + int k; + for (k = 3; k > 0; --k) { + p += 4; + FilterLoop24(p, 1, stride, 16, thresh, ithresh, hev_thresh); + } +} + +static void VFilter8i(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop24(u + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh); + FilterLoop24(v + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh); +} + +static void HFilter8i(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop24(u + 4, 1, stride, 8, thresh, ithresh, hev_thresh); + FilterLoop24(v + 4, 1, stride, 8, thresh, ithresh, hev_thresh); +} + +#undef MUL + +//------------------------------------------------------------------------------ +// Simple In-loop filtering (Paragraph 15.2) + +static void SimpleVFilter16(uint8_t* p, int stride, int thresh) { + int i; + const int thresh2 = 2 * thresh + 1; + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8; + uint8_t* p1 = p - stride; + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "li %[i], 16 \n\t" + "0: \n\t" + "negu %[temp4], %[stride] \n\t" + "sll %[temp5], %[temp4], 1 \n\t" + "lbu %[temp2], 0(%[p]) \n\t" + "lbux %[temp3], %[stride](%[p]) \n\t" + "lbux %[temp1], %[temp4](%[p]) \n\t" + "lbux %[temp0], %[temp5](%[p]) \n\t" + "subu %[temp7], %[temp1], %[temp2] \n\t" + "subu %[temp6], %[temp0], %[temp3] \n\t" + "absq_s.w %[temp4], %[temp7] \n\t" + "absq_s.w %[temp5], %[temp6] \n\t" + "sll %[temp4], %[temp4], 2 \n\t" + "subu %[temp5], %[temp5], %[thresh2] \n\t" + "addu %[temp5], %[temp4], %[temp5] \n\t" + "negu %[temp8], %[temp7] \n\t" + "bgtz %[temp5], 1f \n\t" + " addiu %[i], %[i], -1 \n\t" + "sll %[temp4], %[temp8], 1 \n\t" + "shll_s.w %[temp5], %[temp6], 24 \n\t" + "addu %[temp3], %[temp4], %[temp8] \n\t" + "sra %[temp5], %[temp5], 24 \n\t" + "addu %[temp3], %[temp3], %[temp5] \n\t" + "addiu %[temp7], %[temp3], 3 \n\t" + "sra %[temp7], %[temp7], 3 \n\t" + "shra_r.w %[temp8], %[temp3], 3 \n\t" + "shll_s.w %[temp0], %[temp7], 27 \n\t" + "shll_s.w %[temp4], %[temp8], 27 \n\t" + "sra %[temp0], %[temp0], 27 \n\t" + "sra %[temp4], %[temp4], 27 \n\t" + "addu %[temp7], %[temp1], %[temp0] \n\t" + "subu %[temp2], %[temp2], %[temp4] \n\t" + "lbux %[temp3], %[temp7](%[VP8kclip1]) \n\t" + "lbux %[temp4], %[temp2](%[VP8kclip1]) \n\t" + "sb %[temp3], 0(%[p1]) \n\t" + "sb %[temp4], 0(%[p]) \n\t" + "1: \n\t" + "addiu %[p1], %[p1], 1 \n\t" + "bgtz %[i], 0b \n\t" + " addiu %[p], %[p], 1 \n\t" + " .set pop \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), + [p]"+&r"(p), [i]"=&r"(i), [p1]"+&r"(p1) + : [stride]"r"(stride), [VP8kclip1]"r"(VP8kclip1), [thresh2]"r"(thresh2) + : "memory" + ); +} + +// TEMP0 = SRC[A + A1 * BPS] +// TEMP1 = SRC[B + B1 * BPS] +// TEMP2 = SRC[C + C1 * BPS] +// TEMP3 = SRC[D + D1 * BPS] +#define LOAD_4_BYTES(TEMP0, TEMP1, TEMP2, TEMP3, \ + A, A1, B, B1, C, C1, D, D1, SRC) \ + "lbu %[" #TEMP0 "], " #A "+" #A1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \ + "lbu %[" #TEMP1 "], " #B "+" #B1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \ + "lbu %[" #TEMP2 "], " #C "+" #C1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \ + "lbu %[" #TEMP3 "], " #D "+" #D1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \ + +static void SimpleHFilter16(uint8_t* p, int stride, int thresh) { + int i; + const int thresh2 = 2 * thresh + 1; + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8; + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "li %[i], 16 \n\t" + "0: \n\t" + LOAD_4_BYTES(temp0, temp1, temp2, temp3, -2, 0, -1, 0, 0, 0, 1, 0, p) + "subu %[temp7], %[temp1], %[temp2] \n\t" + "subu %[temp6], %[temp0], %[temp3] \n\t" + "absq_s.w %[temp4], %[temp7] \n\t" + "absq_s.w %[temp5], %[temp6] \n\t" + "sll %[temp4], %[temp4], 2 \n\t" + "addu %[temp5], %[temp4], %[temp5] \n\t" + "subu %[temp5], %[temp5], %[thresh2] \n\t" + "negu %[temp8], %[temp7] \n\t" + "bgtz %[temp5], 1f \n\t" + " addiu %[i], %[i], -1 \n\t" + "sll %[temp4], %[temp8], 1 \n\t" + "shll_s.w %[temp5], %[temp6], 24 \n\t" + "addu %[temp3], %[temp4], %[temp8] \n\t" + "sra %[temp5], %[temp5], 24 \n\t" + "addu %[temp3], %[temp3], %[temp5] \n\t" + "addiu %[temp7], %[temp3], 3 \n\t" + "sra %[temp7], %[temp7], 3 \n\t" + "shra_r.w %[temp8], %[temp3], 3 \n\t" + "shll_s.w %[temp0], %[temp7], 27 \n\t" + "shll_s.w %[temp4], %[temp8], 27 \n\t" + "sra %[temp0], %[temp0], 27 \n\t" + "sra %[temp4], %[temp4], 27 \n\t" + "addu %[temp7], %[temp1], %[temp0] \n\t" + "subu %[temp2], %[temp2], %[temp4] \n\t" + "lbux %[temp3], %[temp7](%[VP8kclip1]) \n\t" + "lbux %[temp4], %[temp2](%[VP8kclip1]) \n\t" + "sb %[temp3], -1(%[p]) \n\t" + "sb %[temp4], 0(%[p]) \n\t" + "1: \n\t" + "bgtz %[i], 0b \n\t" + " addu %[p], %[p], %[stride] \n\t" + ".set pop \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), + [p]"+&r"(p), [i]"=&r"(i) + : [stride]"r"(stride), [VP8kclip1]"r"(VP8kclip1), [thresh2]"r"(thresh2) + : "memory" + ); +} + +static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) { + int k; + for (k = 3; k > 0; --k) { + p += 4 * stride; + SimpleVFilter16(p, stride, thresh); + } +} + +static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) { + int k; + for (k = 3; k > 0; --k) { + p += 4; + SimpleHFilter16(p, stride, thresh); + } +} + +// DST[A * BPS] = TEMP0 +// DST[B + C * BPS] = TEMP1 +#define STORE_8_BYTES(TEMP0, TEMP1, A, B, C, DST) \ + "usw %[" #TEMP0 "], " #A "*" XSTR(BPS) "(%[" #DST "]) \n\t" \ + "usw %[" #TEMP1 "], " #B "+" #C "*" XSTR(BPS) "(%[" #DST "]) \n\t" + +static void VE4(uint8_t* dst) { // vertical + const uint8_t* top = dst - BPS; + int temp0, temp1, temp2, temp3, temp4, temp5, temp6; + __asm__ volatile ( + "ulw %[temp0], -1(%[top]) \n\t" + "ulh %[temp1], 3(%[top]) \n\t" + "preceu.ph.qbr %[temp2], %[temp0] \n\t" + "preceu.ph.qbl %[temp3], %[temp0] \n\t" + "preceu.ph.qbr %[temp4], %[temp1] \n\t" + "packrl.ph %[temp5], %[temp3], %[temp2] \n\t" + "packrl.ph %[temp6], %[temp4], %[temp3] \n\t" + "shll.ph %[temp5], %[temp5], 1 \n\t" + "shll.ph %[temp6], %[temp6], 1 \n\t" + "addq.ph %[temp2], %[temp5], %[temp2] \n\t" + "addq.ph %[temp6], %[temp6], %[temp4] \n\t" + "addq.ph %[temp2], %[temp2], %[temp3] \n\t" + "addq.ph %[temp6], %[temp6], %[temp3] \n\t" + "shra_r.ph %[temp2], %[temp2], 2 \n\t" + "shra_r.ph %[temp6], %[temp6], 2 \n\t" + "precr.qb.ph %[temp4], %[temp6], %[temp2] \n\t" + STORE_8_BYTES(temp4, temp4, 0, 0, 1, dst) + STORE_8_BYTES(temp4, temp4, 2, 0, 3, dst) + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6) + : [top]"r"(top), [dst]"r"(dst) + : "memory" + ); +} + +static void DC4(uint8_t* dst) { // DC + int temp0, temp1, temp2, temp3, temp4; + __asm__ volatile ( + "ulw %[temp0], -1*" XSTR(BPS) "(%[dst]) \n\t" + LOAD_4_BYTES(temp1, temp2, temp3, temp4, -1, 0, -1, 1, -1, 2, -1, 3, dst) + "ins %[temp1], %[temp2], 8, 8 \n\t" + "ins %[temp1], %[temp3], 16, 8 \n\t" + "ins %[temp1], %[temp4], 24, 8 \n\t" + "raddu.w.qb %[temp0], %[temp0] \n\t" + "raddu.w.qb %[temp1], %[temp1] \n\t" + "addu %[temp0], %[temp0], %[temp1] \n\t" + "shra_r.w %[temp0], %[temp0], 3 \n\t" + "replv.qb %[temp0], %[temp0] \n\t" + STORE_8_BYTES(temp0, temp0, 0, 0, 1, dst) + STORE_8_BYTES(temp0, temp0, 2, 0, 3, dst) + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4) + : [dst]"r"(dst) + : "memory" + ); +} + +static void RD4(uint8_t* dst) { // Down-right + int temp0, temp1, temp2, temp3, temp4; + int temp5, temp6, temp7, temp8; + __asm__ volatile ( + LOAD_4_BYTES(temp0, temp1, temp2, temp3, -1, 0, -1, 1, -1, 2, -1, 3, dst) + "ulw %[temp7], -1-" XSTR(BPS) "(%[dst]) \n\t" + "ins %[temp1], %[temp0], 16, 16 \n\t" + "preceu.ph.qbr %[temp5], %[temp7] \n\t" + "ins %[temp2], %[temp1], 16, 16 \n\t" + "preceu.ph.qbl %[temp4], %[temp7] \n\t" + "ins %[temp3], %[temp2], 16, 16 \n\t" + "shll.ph %[temp2], %[temp2], 1 \n\t" + "addq.ph %[temp3], %[temp3], %[temp1] \n\t" + "packrl.ph %[temp6], %[temp5], %[temp1] \n\t" + "addq.ph %[temp3], %[temp3], %[temp2] \n\t" + "addq.ph %[temp1], %[temp1], %[temp5] \n\t" + "shll.ph %[temp6], %[temp6], 1 \n\t" + "addq.ph %[temp1], %[temp1], %[temp6] \n\t" + "packrl.ph %[temp0], %[temp4], %[temp5] \n\t" + "addq.ph %[temp8], %[temp5], %[temp4] \n\t" + "shra_r.ph %[temp3], %[temp3], 2 \n\t" + "shll.ph %[temp0], %[temp0], 1 \n\t" + "shra_r.ph %[temp1], %[temp1], 2 \n\t" + "addq.ph %[temp8], %[temp0], %[temp8] \n\t" + "lbu %[temp5], 3-" XSTR(BPS) "(%[dst]) \n\t" + "precrq.ph.w %[temp7], %[temp7], %[temp7] \n\t" + "shra_r.ph %[temp8], %[temp8], 2 \n\t" + "ins %[temp7], %[temp5], 0, 8 \n\t" + "precr.qb.ph %[temp2], %[temp1], %[temp3] \n\t" + "raddu.w.qb %[temp4], %[temp7] \n\t" + "precr.qb.ph %[temp6], %[temp8], %[temp1] \n\t" + "shra_r.w %[temp4], %[temp4], 2 \n\t" + STORE_8_BYTES(temp2, temp6, 3, 0, 1, dst) + "prepend %[temp2], %[temp8], 8 \n\t" + "prepend %[temp6], %[temp4], 8 \n\t" + STORE_8_BYTES(temp2, temp6, 2, 0, 0, dst) + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8) + : [dst]"r"(dst) + : "memory" + ); +} + +// TEMP0 = SRC[A * BPS] +// TEMP1 = SRC[B + C * BPS] +#define LOAD_8_BYTES(TEMP0, TEMP1, A, B, C, SRC) \ + "ulw %[" #TEMP0 "], " #A "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \ + "ulw %[" #TEMP1 "], " #B "+" #C "*" XSTR(BPS) "(%[" #SRC "]) \n\t" + +static void LD4(uint8_t* dst) { // Down-Left + int temp0, temp1, temp2, temp3, temp4; + int temp5, temp6, temp7, temp8, temp9; + __asm__ volatile ( + LOAD_8_BYTES(temp0, temp1, -1, 4, -1, dst) + "preceu.ph.qbl %[temp2], %[temp0] \n\t" + "preceu.ph.qbr %[temp3], %[temp0] \n\t" + "preceu.ph.qbr %[temp4], %[temp1] \n\t" + "preceu.ph.qbl %[temp5], %[temp1] \n\t" + "packrl.ph %[temp6], %[temp2], %[temp3] \n\t" + "packrl.ph %[temp7], %[temp4], %[temp2] \n\t" + "packrl.ph %[temp8], %[temp5], %[temp4] \n\t" + "shll.ph %[temp6], %[temp6], 1 \n\t" + "addq.ph %[temp9], %[temp2], %[temp6] \n\t" + "shll.ph %[temp7], %[temp7], 1 \n\t" + "addq.ph %[temp9], %[temp9], %[temp3] \n\t" + "shll.ph %[temp8], %[temp8], 1 \n\t" + "shra_r.ph %[temp9], %[temp9], 2 \n\t" + "addq.ph %[temp3], %[temp4], %[temp7] \n\t" + "addq.ph %[temp0], %[temp5], %[temp8] \n\t" + "addq.ph %[temp3], %[temp3], %[temp2] \n\t" + "addq.ph %[temp0], %[temp0], %[temp4] \n\t" + "shra_r.ph %[temp3], %[temp3], 2 \n\t" + "shra_r.ph %[temp0], %[temp0], 2 \n\t" + "srl %[temp1], %[temp1], 24 \n\t" + "sll %[temp1], %[temp1], 1 \n\t" + "raddu.w.qb %[temp5], %[temp5] \n\t" + "precr.qb.ph %[temp9], %[temp3], %[temp9] \n\t" + "precr.qb.ph %[temp3], %[temp0], %[temp3] \n\t" + "addu %[temp1], %[temp1], %[temp5] \n\t" + "shra_r.w %[temp1], %[temp1], 2 \n\t" + STORE_8_BYTES(temp9, temp3, 0, 0, 2, dst) + "prepend %[temp9], %[temp0], 8 \n\t" + "prepend %[temp3], %[temp1], 8 \n\t" + STORE_8_BYTES(temp9, temp3, 1, 0, 3, dst) + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), + [temp9]"=&r"(temp9) + : [dst]"r"(dst) + : "memory" + ); +} + +//------------------------------------------------------------------------------ +// Chroma + +static void DC8uv(uint8_t* dst) { // DC + int temp0, temp1, temp2, temp3, temp4; + int temp5, temp6, temp7, temp8, temp9; + __asm__ volatile ( + LOAD_8_BYTES(temp0, temp1, -1, 4, -1, dst) + LOAD_4_BYTES(temp2, temp3, temp4, temp5, -1, 0, -1, 1, -1, 2, -1, 3, dst) + LOAD_4_BYTES(temp6, temp7, temp8, temp9, -1, 4, -1, 5, -1, 6, -1, 7, dst) + "raddu.w.qb %[temp0], %[temp0] \n\t" + "raddu.w.qb %[temp1], %[temp1] \n\t" + "addu %[temp2], %[temp2], %[temp3] \n\t" + "addu %[temp4], %[temp4], %[temp5] \n\t" + "addu %[temp6], %[temp6], %[temp7] \n\t" + "addu %[temp8], %[temp8], %[temp9] \n\t" + "addu %[temp0], %[temp0], %[temp1] \n\t" + "addu %[temp2], %[temp2], %[temp4] \n\t" + "addu %[temp6], %[temp6], %[temp8] \n\t" + "addu %[temp0], %[temp0], %[temp2] \n\t" + "addu %[temp0], %[temp0], %[temp6] \n\t" + "shra_r.w %[temp0], %[temp0], 4 \n\t" + "replv.qb %[temp0], %[temp0] \n\t" + STORE_8_BYTES(temp0, temp0, 0, 4, 0, dst) + STORE_8_BYTES(temp0, temp0, 1, 4, 1, dst) + STORE_8_BYTES(temp0, temp0, 2, 4, 2, dst) + STORE_8_BYTES(temp0, temp0, 3, 4, 3, dst) + STORE_8_BYTES(temp0, temp0, 4, 4, 4, dst) + STORE_8_BYTES(temp0, temp0, 5, 4, 5, dst) + STORE_8_BYTES(temp0, temp0, 6, 4, 6, dst) + STORE_8_BYTES(temp0, temp0, 7, 4, 7, dst) + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), + [temp9]"=&r"(temp9) + : [dst]"r"(dst) + : "memory" + ); +} + +static void DC8uvNoLeft(uint8_t* dst) { // DC with no left samples + int temp0, temp1; + __asm__ volatile ( + LOAD_8_BYTES(temp0, temp1, -1, 4, -1, dst) + "raddu.w.qb %[temp0], %[temp0] \n\t" + "raddu.w.qb %[temp1], %[temp1] \n\t" + "addu %[temp0], %[temp0], %[temp1] \n\t" + "shra_r.w %[temp0], %[temp0], 3 \n\t" + "replv.qb %[temp0], %[temp0] \n\t" + STORE_8_BYTES(temp0, temp0, 0, 4, 0, dst) + STORE_8_BYTES(temp0, temp0, 1, 4, 1, dst) + STORE_8_BYTES(temp0, temp0, 2, 4, 2, dst) + STORE_8_BYTES(temp0, temp0, 3, 4, 3, dst) + STORE_8_BYTES(temp0, temp0, 4, 4, 4, dst) + STORE_8_BYTES(temp0, temp0, 5, 4, 5, dst) + STORE_8_BYTES(temp0, temp0, 6, 4, 6, dst) + STORE_8_BYTES(temp0, temp0, 7, 4, 7, dst) + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1) + : [dst]"r"(dst) + : "memory" + ); +} + +static void DC8uvNoTop(uint8_t* dst) { // DC with no top samples + int temp0, temp1, temp2, temp3, temp4; + int temp5, temp6, temp7, temp8; + __asm__ volatile ( + LOAD_4_BYTES(temp2, temp3, temp4, temp5, -1, 0, -1, 1, -1, 2, -1, 3, dst) + LOAD_4_BYTES(temp6, temp7, temp8, temp1, -1, 4, -1, 5, -1, 6, -1, 7, dst) + "addu %[temp2], %[temp2], %[temp3] \n\t" + "addu %[temp4], %[temp4], %[temp5] \n\t" + "addu %[temp6], %[temp6], %[temp7] \n\t" + "addu %[temp8], %[temp8], %[temp1] \n\t" + "addu %[temp2], %[temp2], %[temp4] \n\t" + "addu %[temp6], %[temp6], %[temp8] \n\t" + "addu %[temp0], %[temp6], %[temp2] \n\t" + "shra_r.w %[temp0], %[temp0], 3 \n\t" + "replv.qb %[temp0], %[temp0] \n\t" + STORE_8_BYTES(temp0, temp0, 0, 4, 0, dst) + STORE_8_BYTES(temp0, temp0, 1, 4, 1, dst) + STORE_8_BYTES(temp0, temp0, 2, 4, 2, dst) + STORE_8_BYTES(temp0, temp0, 3, 4, 3, dst) + STORE_8_BYTES(temp0, temp0, 4, 4, 4, dst) + STORE_8_BYTES(temp0, temp0, 5, 4, 5, dst) + STORE_8_BYTES(temp0, temp0, 6, 4, 6, dst) + STORE_8_BYTES(temp0, temp0, 7, 4, 7, dst) + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8) + : [dst]"r"(dst) + : "memory" + ); +} + +#undef LOAD_8_BYTES +#undef STORE_8_BYTES +#undef LOAD_4_BYTES + +#define CLIPPING(SIZE) \ + "preceu.ph.qbl %[temp2], %[temp0] \n\t" \ + "preceu.ph.qbr %[temp0], %[temp0] \n\t" \ +".if " #SIZE " == 8 \n\t" \ + "preceu.ph.qbl %[temp3], %[temp1] \n\t" \ + "preceu.ph.qbr %[temp1], %[temp1] \n\t" \ +".endif \n\t" \ + "addu.ph %[temp2], %[temp2], %[dst_1] \n\t" \ + "addu.ph %[temp0], %[temp0], %[dst_1] \n\t" \ +".if " #SIZE " == 8 \n\t" \ + "addu.ph %[temp3], %[temp3], %[dst_1] \n\t" \ + "addu.ph %[temp1], %[temp1], %[dst_1] \n\t" \ +".endif \n\t" \ + "shll_s.ph %[temp2], %[temp2], 7 \n\t" \ + "shll_s.ph %[temp0], %[temp0], 7 \n\t" \ +".if " #SIZE " == 8 \n\t" \ + "shll_s.ph %[temp3], %[temp3], 7 \n\t" \ + "shll_s.ph %[temp1], %[temp1], 7 \n\t" \ +".endif \n\t" \ + "precrqu_s.qb.ph %[temp0], %[temp2], %[temp0] \n\t" \ +".if " #SIZE " == 8 \n\t" \ + "precrqu_s.qb.ph %[temp1], %[temp3], %[temp1] \n\t" \ +".endif \n\t" + + +#define CLIP_8B_TO_DST(DST, TOP, SIZE) do { \ + int dst_1 = ((int)(DST)[-1] << 16) + (DST)[-1]; \ + int temp0, temp1, temp2, temp3; \ + __asm__ volatile ( \ + ".if " #SIZE " < 8 \n\t" \ + "ulw %[temp0], 0(%[top]) \n\t" \ + "subu.ph %[dst_1], %[dst_1], %[top_1] \n\t" \ + CLIPPING(4) \ + "usw %[temp0], 0(%[dst]) \n\t" \ + ".else \n\t" \ + "ulw %[temp0], 0(%[top]) \n\t" \ + "ulw %[temp1], 4(%[top]) \n\t" \ + "subu.ph %[dst_1], %[dst_1], %[top_1] \n\t" \ + CLIPPING(8) \ + "usw %[temp0], 0(%[dst]) \n\t" \ + "usw %[temp1], 4(%[dst]) \n\t" \ + ".if " #SIZE " == 16 \n\t" \ + "ulw %[temp0], 8(%[top]) \n\t" \ + "ulw %[temp1], 12(%[top]) \n\t" \ + CLIPPING(8) \ + "usw %[temp0], 8(%[dst]) \n\t" \ + "usw %[temp1], 12(%[dst]) \n\t" \ + ".endif \n\t" \ + ".endif \n\t" \ + : [dst_1]"+&r"(dst_1), [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), \ + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3) \ + : [top_1]"r"(top_1), [top]"r"((TOP)), [dst]"r"((DST)) \ + : "memory" \ + ); \ +} while (0) + +#define CLIP_TO_DST(DST, SIZE) do { \ + int y; \ + const uint8_t* top = (DST) - BPS; \ + const int top_1 = ((int)top[-1] << 16) + top[-1]; \ + for (y = 0; y < (SIZE); ++y) { \ + CLIP_8B_TO_DST((DST), top, (SIZE)); \ + (DST) += BPS; \ + } \ +} while (0) + +#define TRUE_MOTION(DST, SIZE) \ +static void TrueMotion##SIZE(uint8_t* (DST)) { \ + CLIP_TO_DST((DST), (SIZE)); \ +} + +TRUE_MOTION(dst, 4) +TRUE_MOTION(dst, 8) +TRUE_MOTION(dst, 16) + +#undef TRUE_MOTION +#undef CLIP_TO_DST +#undef CLIP_8B_TO_DST +#undef CLIPPING + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8DspInitMIPSdspR2(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitMIPSdspR2(void) { + VP8TransformDC = TransformDC; + VP8TransformAC3 = TransformAC3; + VP8Transform = TransformTwo; + + VP8VFilter16 = VFilter16; + VP8HFilter16 = HFilter16; + VP8VFilter8 = VFilter8; + VP8HFilter8 = HFilter8; + VP8VFilter16i = VFilter16i; + VP8HFilter16i = HFilter16i; + VP8VFilter8i = VFilter8i; + VP8HFilter8i = HFilter8i; + VP8SimpleVFilter16 = SimpleVFilter16; + VP8SimpleHFilter16 = SimpleHFilter16; + VP8SimpleVFilter16i = SimpleVFilter16i; + VP8SimpleHFilter16i = SimpleHFilter16i; + + VP8PredLuma4[0] = DC4; + VP8PredLuma4[1] = TrueMotion4; + VP8PredLuma4[2] = VE4; + VP8PredLuma4[4] = RD4; + VP8PredLuma4[6] = LD4; + + VP8PredChroma8[0] = DC8uv; + VP8PredChroma8[1] = TrueMotion8; + VP8PredChroma8[4] = DC8uvNoTop; + VP8PredChroma8[5] = DC8uvNoLeft; + + VP8PredLuma16[1] = TrueMotion16; +} + +#else // !WEBP_USE_MIPS_DSP_R2 + +WEBP_DSP_INIT_STUB(VP8DspInitMIPSdspR2) + +#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/third-party/webp/libwebp/src/dsp/dec_msa.c b/third-party/webp/libwebp/src/dsp/dec_msa.c new file mode 100644 index 0000000000..8090622b7b --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/dec_msa.c @@ -0,0 +1,1020 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MSA version of dsp functions +// +// Author(s): Prashant Patil (prashant.patil@imgtec.com) + + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MSA) + +#include "src/dsp/msa_macro.h" + +//------------------------------------------------------------------------------ +// Transforms + +#define IDCT_1D_W(in0, in1, in2, in3, out0, out1, out2, out3) { \ + v4i32 a1_m, b1_m, c1_m, d1_m; \ + v4i32 c_tmp1_m, c_tmp2_m, d_tmp1_m, d_tmp2_m; \ + const v4i32 cospi8sqrt2minus1 = __msa_fill_w(20091); \ + const v4i32 sinpi8sqrt2 = __msa_fill_w(35468); \ + \ + a1_m = in0 + in2; \ + b1_m = in0 - in2; \ + c_tmp1_m = (in1 * sinpi8sqrt2) >> 16; \ + c_tmp2_m = in3 + ((in3 * cospi8sqrt2minus1) >> 16); \ + c1_m = c_tmp1_m - c_tmp2_m; \ + d_tmp1_m = in1 + ((in1 * cospi8sqrt2minus1) >> 16); \ + d_tmp2_m = (in3 * sinpi8sqrt2) >> 16; \ + d1_m = d_tmp1_m + d_tmp2_m; \ + BUTTERFLY_4(a1_m, b1_m, c1_m, d1_m, out0, out1, out2, out3); \ +} +#define MULT1(a) ((((a) * 20091) >> 16) + (a)) +#define MULT2(a) (((a) * 35468) >> 16) + +static void TransformOne(const int16_t* in, uint8_t* dst) { + v8i16 input0, input1; + v4i32 in0, in1, in2, in3, hz0, hz1, hz2, hz3, vt0, vt1, vt2, vt3; + v4i32 res0, res1, res2, res3; + const v16i8 zero = { 0 }; + v16i8 dest0, dest1, dest2, dest3; + + LD_SH2(in, 8, input0, input1); + UNPCK_SH_SW(input0, in0, in1); + UNPCK_SH_SW(input1, in2, in3); + IDCT_1D_W(in0, in1, in2, in3, hz0, hz1, hz2, hz3); + TRANSPOSE4x4_SW_SW(hz0, hz1, hz2, hz3, hz0, hz1, hz2, hz3); + IDCT_1D_W(hz0, hz1, hz2, hz3, vt0, vt1, vt2, vt3); + SRARI_W4_SW(vt0, vt1, vt2, vt3, 3); + TRANSPOSE4x4_SW_SW(vt0, vt1, vt2, vt3, vt0, vt1, vt2, vt3); + LD_SB4(dst, BPS, dest0, dest1, dest2, dest3); + ILVR_B4_SW(zero, dest0, zero, dest1, zero, dest2, zero, dest3, + res0, res1, res2, res3); + ILVR_H4_SW(zero, res0, zero, res1, zero, res2, zero, res3, + res0, res1, res2, res3); + ADD4(res0, vt0, res1, vt1, res2, vt2, res3, vt3, res0, res1, res2, res3); + CLIP_SW4_0_255(res0, res1, res2, res3); + PCKEV_B2_SW(res0, res1, res2, res3, vt0, vt1); + res0 = (v4i32)__msa_pckev_b((v16i8)vt0, (v16i8)vt1); + ST4x4_UB(res0, res0, 3, 2, 1, 0, dst, BPS); +} + +static void TransformTwo(const int16_t* in, uint8_t* dst, int do_two) { + TransformOne(in, dst); + if (do_two) { + TransformOne(in + 16, dst + 4); + } +} + +static void TransformWHT(const int16_t* in, int16_t* out) { + v8i16 input0, input1; + const v8i16 mask0 = { 0, 1, 2, 3, 8, 9, 10, 11 }; + const v8i16 mask1 = { 4, 5, 6, 7, 12, 13, 14, 15 }; + const v8i16 mask2 = { 0, 4, 8, 12, 1, 5, 9, 13 }; + const v8i16 mask3 = { 3, 7, 11, 15, 2, 6, 10, 14 }; + v8i16 tmp0, tmp1, tmp2, tmp3; + v8i16 out0, out1; + + LD_SH2(in, 8, input0, input1); + input1 = SLDI_SH(input1, input1, 8); + tmp0 = input0 + input1; + tmp1 = input0 - input1; + VSHF_H2_SH(tmp0, tmp1, tmp0, tmp1, mask0, mask1, tmp2, tmp3); + out0 = tmp2 + tmp3; + out1 = tmp2 - tmp3; + VSHF_H2_SH(out0, out1, out0, out1, mask2, mask3, input0, input1); + tmp0 = input0 + input1; + tmp1 = input0 - input1; + VSHF_H2_SH(tmp0, tmp1, tmp0, tmp1, mask0, mask1, tmp2, tmp3); + tmp0 = tmp2 + tmp3; + tmp1 = tmp2 - tmp3; + ADDVI_H2_SH(tmp0, 3, tmp1, 3, out0, out1); + SRAI_H2_SH(out0, out1, 3); + out[0] = __msa_copy_s_h(out0, 0); + out[16] = __msa_copy_s_h(out0, 4); + out[32] = __msa_copy_s_h(out1, 0); + out[48] = __msa_copy_s_h(out1, 4); + out[64] = __msa_copy_s_h(out0, 1); + out[80] = __msa_copy_s_h(out0, 5); + out[96] = __msa_copy_s_h(out1, 1); + out[112] = __msa_copy_s_h(out1, 5); + out[128] = __msa_copy_s_h(out0, 2); + out[144] = __msa_copy_s_h(out0, 6); + out[160] = __msa_copy_s_h(out1, 2); + out[176] = __msa_copy_s_h(out1, 6); + out[192] = __msa_copy_s_h(out0, 3); + out[208] = __msa_copy_s_h(out0, 7); + out[224] = __msa_copy_s_h(out1, 3); + out[240] = __msa_copy_s_h(out1, 7); +} + +static void TransformDC(const int16_t* in, uint8_t* dst) { + const int DC = (in[0] + 4) >> 3; + const v8i16 tmp0 = __msa_fill_h(DC); + ADDBLK_ST4x4_UB(tmp0, tmp0, tmp0, tmp0, dst, BPS); +} + +static void TransformAC3(const int16_t* in, uint8_t* dst) { + const int a = in[0] + 4; + const int c4 = MULT2(in[4]); + const int d4 = MULT1(in[4]); + const int in2 = MULT2(in[1]); + const int in3 = MULT1(in[1]); + v4i32 tmp0 = { 0 }; + v4i32 out0 = __msa_fill_w(a + d4); + v4i32 out1 = __msa_fill_w(a + c4); + v4i32 out2 = __msa_fill_w(a - c4); + v4i32 out3 = __msa_fill_w(a - d4); + v4i32 res0, res1, res2, res3; + const v4i32 zero = { 0 }; + v16u8 dest0, dest1, dest2, dest3; + + INSERT_W4_SW(in3, in2, -in2, -in3, tmp0); + ADD4(out0, tmp0, out1, tmp0, out2, tmp0, out3, tmp0, + out0, out1, out2, out3); + SRAI_W4_SW(out0, out1, out2, out3, 3); + LD_UB4(dst, BPS, dest0, dest1, dest2, dest3); + ILVR_B4_SW(zero, dest0, zero, dest1, zero, dest2, zero, dest3, + res0, res1, res2, res3); + ILVR_H4_SW(zero, res0, zero, res1, zero, res2, zero, res3, + res0, res1, res2, res3); + ADD4(res0, out0, res1, out1, res2, out2, res3, out3, res0, res1, res2, res3); + CLIP_SW4_0_255(res0, res1, res2, res3); + PCKEV_B2_SW(res0, res1, res2, res3, out0, out1); + res0 = (v4i32)__msa_pckev_b((v16i8)out0, (v16i8)out1); + ST4x4_UB(res0, res0, 3, 2, 1, 0, dst, BPS); +} + +//------------------------------------------------------------------------------ +// Edge filtering functions + +#define FLIP_SIGN2(in0, in1, out0, out1) { \ + out0 = (v16i8)__msa_xori_b(in0, 0x80); \ + out1 = (v16i8)__msa_xori_b(in1, 0x80); \ +} + +#define FLIP_SIGN4(in0, in1, in2, in3, out0, out1, out2, out3) { \ + FLIP_SIGN2(in0, in1, out0, out1); \ + FLIP_SIGN2(in2, in3, out2, out3); \ +} + +#define FILT_VAL(q0_m, p0_m, mask, filt) do { \ + v16i8 q0_sub_p0; \ + q0_sub_p0 = __msa_subs_s_b(q0_m, p0_m); \ + filt = __msa_adds_s_b(filt, q0_sub_p0); \ + filt = __msa_adds_s_b(filt, q0_sub_p0); \ + filt = __msa_adds_s_b(filt, q0_sub_p0); \ + filt = filt & mask; \ +} while (0) + +#define FILT2(q_m, p_m, q, p) do { \ + u_r = SRAI_H(temp1, 7); \ + u_r = __msa_sat_s_h(u_r, 7); \ + u_l = SRAI_H(temp3, 7); \ + u_l = __msa_sat_s_h(u_l, 7); \ + u = __msa_pckev_b((v16i8)u_l, (v16i8)u_r); \ + q_m = __msa_subs_s_b(q_m, u); \ + p_m = __msa_adds_s_b(p_m, u); \ + q = __msa_xori_b((v16u8)q_m, 0x80); \ + p = __msa_xori_b((v16u8)p_m, 0x80); \ +} while (0) + +#define LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev) do { \ + v16i8 p1_m, p0_m, q0_m, q1_m; \ + v16i8 filt, t1, t2; \ + const v16i8 cnst4b = __msa_ldi_b(4); \ + const v16i8 cnst3b = __msa_ldi_b(3); \ + \ + FLIP_SIGN4(p1, p0, q0, q1, p1_m, p0_m, q0_m, q1_m); \ + filt = __msa_subs_s_b(p1_m, q1_m); \ + filt = filt & hev; \ + FILT_VAL(q0_m, p0_m, mask, filt); \ + t1 = __msa_adds_s_b(filt, cnst4b); \ + t1 = SRAI_B(t1, 3); \ + t2 = __msa_adds_s_b(filt, cnst3b); \ + t2 = SRAI_B(t2, 3); \ + q0_m = __msa_subs_s_b(q0_m, t1); \ + q0 = __msa_xori_b((v16u8)q0_m, 0x80); \ + p0_m = __msa_adds_s_b(p0_m, t2); \ + p0 = __msa_xori_b((v16u8)p0_m, 0x80); \ + filt = __msa_srari_b(t1, 1); \ + hev = __msa_xori_b(hev, 0xff); \ + filt = filt & hev; \ + q1_m = __msa_subs_s_b(q1_m, filt); \ + q1 = __msa_xori_b((v16u8)q1_m, 0x80); \ + p1_m = __msa_adds_s_b(p1_m, filt); \ + p1 = __msa_xori_b((v16u8)p1_m, 0x80); \ +} while (0) + +#define LPF_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev) do { \ + v16i8 p2_m, p1_m, p0_m, q2_m, q1_m, q0_m; \ + v16i8 u, filt, t1, t2, filt_sign; \ + v8i16 filt_r, filt_l, u_r, u_l; \ + v8i16 temp0, temp1, temp2, temp3; \ + const v16i8 cnst4b = __msa_ldi_b(4); \ + const v16i8 cnst3b = __msa_ldi_b(3); \ + const v8i16 cnst9h = __msa_ldi_h(9); \ + const v8i16 cnst63h = __msa_ldi_h(63); \ + \ + FLIP_SIGN4(p1, p0, q0, q1, p1_m, p0_m, q0_m, q1_m); \ + filt = __msa_subs_s_b(p1_m, q1_m); \ + FILT_VAL(q0_m, p0_m, mask, filt); \ + FLIP_SIGN2(p2, q2, p2_m, q2_m); \ + t2 = filt & hev; \ + /* filt_val &= ~hev */ \ + hev = __msa_xori_b(hev, 0xff); \ + filt = filt & hev; \ + t1 = __msa_adds_s_b(t2, cnst4b); \ + t1 = SRAI_B(t1, 3); \ + t2 = __msa_adds_s_b(t2, cnst3b); \ + t2 = SRAI_B(t2, 3); \ + q0_m = __msa_subs_s_b(q0_m, t1); \ + p0_m = __msa_adds_s_b(p0_m, t2); \ + filt_sign = __msa_clti_s_b(filt, 0); \ + ILVRL_B2_SH(filt_sign, filt, filt_r, filt_l); \ + /* update q2/p2 */ \ + temp0 = filt_r * cnst9h; \ + temp1 = temp0 + cnst63h; \ + temp2 = filt_l * cnst9h; \ + temp3 = temp2 + cnst63h; \ + FILT2(q2_m, p2_m, q2, p2); \ + /* update q1/p1 */ \ + temp1 = temp1 + temp0; \ + temp3 = temp3 + temp2; \ + FILT2(q1_m, p1_m, q1, p1); \ + /* update q0/p0 */ \ + temp1 = temp1 + temp0; \ + temp3 = temp3 + temp2; \ + FILT2(q0_m, p0_m, q0, p0); \ +} while (0) + +#define LPF_MASK_HEV(p3_in, p2_in, p1_in, p0_in, \ + q0_in, q1_in, q2_in, q3_in, \ + limit_in, b_limit_in, thresh_in, \ + hev_out, mask_out) do { \ + v16u8 p3_asub_p2_m, p2_asub_p1_m, p1_asub_p0_m, q1_asub_q0_m; \ + v16u8 p1_asub_q1_m, p0_asub_q0_m, q3_asub_q2_m, q2_asub_q1_m; \ + v16u8 flat_out; \ + \ + /* absolute subtraction of pixel values */ \ + p3_asub_p2_m = __msa_asub_u_b(p3_in, p2_in); \ + p2_asub_p1_m = __msa_asub_u_b(p2_in, p1_in); \ + p1_asub_p0_m = __msa_asub_u_b(p1_in, p0_in); \ + q1_asub_q0_m = __msa_asub_u_b(q1_in, q0_in); \ + q2_asub_q1_m = __msa_asub_u_b(q2_in, q1_in); \ + q3_asub_q2_m = __msa_asub_u_b(q3_in, q2_in); \ + p0_asub_q0_m = __msa_asub_u_b(p0_in, q0_in); \ + p1_asub_q1_m = __msa_asub_u_b(p1_in, q1_in); \ + /* calculation of hev */ \ + flat_out = __msa_max_u_b(p1_asub_p0_m, q1_asub_q0_m); \ + hev_out = (thresh_in < flat_out); \ + /* calculation of mask */ \ + p0_asub_q0_m = __msa_adds_u_b(p0_asub_q0_m, p0_asub_q0_m); \ + p1_asub_q1_m = SRAI_B(p1_asub_q1_m, 1); \ + p0_asub_q0_m = __msa_adds_u_b(p0_asub_q0_m, p1_asub_q1_m); \ + mask_out = (b_limit_in < p0_asub_q0_m); \ + mask_out = __msa_max_u_b(flat_out, mask_out); \ + p3_asub_p2_m = __msa_max_u_b(p3_asub_p2_m, p2_asub_p1_m); \ + mask_out = __msa_max_u_b(p3_asub_p2_m, mask_out); \ + q2_asub_q1_m = __msa_max_u_b(q2_asub_q1_m, q3_asub_q2_m); \ + mask_out = __msa_max_u_b(q2_asub_q1_m, mask_out); \ + mask_out = (limit_in < mask_out); \ + mask_out = __msa_xori_b(mask_out, 0xff); \ +} while (0) + +#define ST6x1_UB(in0, in0_idx, in1, in1_idx, pdst, stride) do { \ + const uint16_t tmp0_h = __msa_copy_s_h((v8i16)in1, in1_idx); \ + const uint32_t tmp0_w = __msa_copy_s_w((v4i32)in0, in0_idx); \ + SW(tmp0_w, pdst); \ + SH(tmp0_h, pdst + stride); \ +} while (0) + +#define ST6x4_UB(in0, start_in0_idx, in1, start_in1_idx, pdst, stride) do { \ + uint8_t* ptmp1 = (uint8_t*)pdst; \ + ST6x1_UB(in0, start_in0_idx, in1, start_in1_idx, ptmp1, 4); \ + ptmp1 += stride; \ + ST6x1_UB(in0, start_in0_idx + 1, in1, start_in1_idx + 1, ptmp1, 4); \ + ptmp1 += stride; \ + ST6x1_UB(in0, start_in0_idx + 2, in1, start_in1_idx + 2, ptmp1, 4); \ + ptmp1 += stride; \ + ST6x1_UB(in0, start_in0_idx + 3, in1, start_in1_idx + 3, ptmp1, 4); \ +} while (0) + +#define LPF_SIMPLE_FILT(p1_in, p0_in, q0_in, q1_in, mask) do { \ + v16i8 p1_m, p0_m, q0_m, q1_m, filt, filt1, filt2; \ + const v16i8 cnst4b = __msa_ldi_b(4); \ + const v16i8 cnst3b = __msa_ldi_b(3); \ + \ + FLIP_SIGN4(p1_in, p0_in, q0_in, q1_in, p1_m, p0_m, q0_m, q1_m); \ + filt = __msa_subs_s_b(p1_m, q1_m); \ + FILT_VAL(q0_m, p0_m, mask, filt); \ + filt1 = __msa_adds_s_b(filt, cnst4b); \ + filt1 = SRAI_B(filt1, 3); \ + filt2 = __msa_adds_s_b(filt, cnst3b); \ + filt2 = SRAI_B(filt2, 3); \ + q0_m = __msa_subs_s_b(q0_m, filt1); \ + p0_m = __msa_adds_s_b(p0_m, filt2); \ + q0_in = __msa_xori_b((v16u8)q0_m, 0x80); \ + p0_in = __msa_xori_b((v16u8)p0_m, 0x80); \ +} while (0) + +#define LPF_SIMPLE_MASK(p1, p0, q0, q1, b_limit, mask) do { \ + v16u8 p1_a_sub_q1, p0_a_sub_q0; \ + \ + p0_a_sub_q0 = __msa_asub_u_b(p0, q0); \ + p1_a_sub_q1 = __msa_asub_u_b(p1, q1); \ + p1_a_sub_q1 = (v16u8)__msa_srli_b((v16i8)p1_a_sub_q1, 1); \ + p0_a_sub_q0 = __msa_adds_u_b(p0_a_sub_q0, p0_a_sub_q0); \ + mask = __msa_adds_u_b(p0_a_sub_q0, p1_a_sub_q1); \ + mask = (mask <= b_limit); \ +} while (0) + +static void VFilter16(uint8_t* src, int stride, + int b_limit_in, int limit_in, int thresh_in) { + uint8_t* ptemp = src - 4 * stride; + v16u8 p3, p2, p1, p0, q3, q2, q1, q0; + v16u8 mask, hev; + const v16u8 thresh = (v16u8)__msa_fill_b(thresh_in); + const v16u8 limit = (v16u8)__msa_fill_b(limit_in); + const v16u8 b_limit = (v16u8)__msa_fill_b(b_limit_in); + + LD_UB8(ptemp, stride, p3, p2, p1, p0, q0, q1, q2, q3); + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask); + LPF_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev); + ptemp = src - 3 * stride; + ST_UB4(p2, p1, p0, q0, ptemp, stride); + ptemp += (4 * stride); + ST_UB2(q1, q2, ptemp, stride); +} + +static void HFilter16(uint8_t* src, int stride, + int b_limit_in, int limit_in, int thresh_in) { + uint8_t* ptmp = src - 4; + v16u8 p3, p2, p1, p0, q3, q2, q1, q0; + v16u8 mask, hev; + v16u8 row0, row1, row2, row3, row4, row5, row6, row7, row8; + v16u8 row9, row10, row11, row12, row13, row14, row15; + v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + const v16u8 b_limit = (v16u8)__msa_fill_b(b_limit_in); + const v16u8 limit = (v16u8)__msa_fill_b(limit_in); + const v16u8 thresh = (v16u8)__msa_fill_b(thresh_in); + + LD_UB8(ptmp, stride, row0, row1, row2, row3, row4, row5, row6, row7); + ptmp += (8 * stride); + LD_UB8(ptmp, stride, row8, row9, row10, row11, row12, row13, row14, row15); + TRANSPOSE16x8_UB_UB(row0, row1, row2, row3, row4, row5, row6, row7, + row8, row9, row10, row11, row12, row13, row14, row15, + p3, p2, p1, p0, q0, q1, q2, q3); + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask); + LPF_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev); + ILVR_B2_SH(p1, p2, q0, p0, tmp0, tmp1); + ILVRL_H2_SH(tmp1, tmp0, tmp3, tmp4); + ILVL_B2_SH(p1, p2, q0, p0, tmp0, tmp1); + ILVRL_H2_SH(tmp1, tmp0, tmp6, tmp7); + ILVRL_B2_SH(q2, q1, tmp2, tmp5); + ptmp = src - 3; + ST6x1_UB(tmp3, 0, tmp2, 0, ptmp, 4); + ptmp += stride; + ST6x1_UB(tmp3, 1, tmp2, 1, ptmp, 4); + ptmp += stride; + ST6x1_UB(tmp3, 2, tmp2, 2, ptmp, 4); + ptmp += stride; + ST6x1_UB(tmp3, 3, tmp2, 3, ptmp, 4); + ptmp += stride; + ST6x1_UB(tmp4, 0, tmp2, 4, ptmp, 4); + ptmp += stride; + ST6x1_UB(tmp4, 1, tmp2, 5, ptmp, 4); + ptmp += stride; + ST6x1_UB(tmp4, 2, tmp2, 6, ptmp, 4); + ptmp += stride; + ST6x1_UB(tmp4, 3, tmp2, 7, ptmp, 4); + ptmp += stride; + ST6x1_UB(tmp6, 0, tmp5, 0, ptmp, 4); + ptmp += stride; + ST6x1_UB(tmp6, 1, tmp5, 1, ptmp, 4); + ptmp += stride; + ST6x1_UB(tmp6, 2, tmp5, 2, ptmp, 4); + ptmp += stride; + ST6x1_UB(tmp6, 3, tmp5, 3, ptmp, 4); + ptmp += stride; + ST6x1_UB(tmp7, 0, tmp5, 4, ptmp, 4); + ptmp += stride; + ST6x1_UB(tmp7, 1, tmp5, 5, ptmp, 4); + ptmp += stride; + ST6x1_UB(tmp7, 2, tmp5, 6, ptmp, 4); + ptmp += stride; + ST6x1_UB(tmp7, 3, tmp5, 7, ptmp, 4); +} + +// on three inner edges +static void VFilterHorEdge16i(uint8_t* src, int stride, + int b_limit, int limit, int thresh) { + v16u8 mask, hev; + v16u8 p3, p2, p1, p0, q3, q2, q1, q0; + const v16u8 thresh0 = (v16u8)__msa_fill_b(thresh); + const v16u8 b_limit0 = (v16u8)__msa_fill_b(b_limit); + const v16u8 limit0 = (v16u8)__msa_fill_b(limit); + + LD_UB8((src - 4 * stride), stride, p3, p2, p1, p0, q0, q1, q2, q3); + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit0, b_limit0, thresh0, + hev, mask); + LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev); + ST_UB4(p1, p0, q0, q1, (src - 2 * stride), stride); +} + +static void VFilter16i(uint8_t* src_y, int stride, + int b_limit, int limit, int thresh) { + VFilterHorEdge16i(src_y + 4 * stride, stride, b_limit, limit, thresh); + VFilterHorEdge16i(src_y + 8 * stride, stride, b_limit, limit, thresh); + VFilterHorEdge16i(src_y + 12 * stride, stride, b_limit, limit, thresh); +} + +static void HFilterVertEdge16i(uint8_t* src, int stride, + int b_limit, int limit, int thresh) { + v16u8 mask, hev; + v16u8 p3, p2, p1, p0, q3, q2, q1, q0; + v16u8 row0, row1, row2, row3, row4, row5, row6, row7; + v16u8 row8, row9, row10, row11, row12, row13, row14, row15; + v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + const v16u8 thresh0 = (v16u8)__msa_fill_b(thresh); + const v16u8 b_limit0 = (v16u8)__msa_fill_b(b_limit); + const v16u8 limit0 = (v16u8)__msa_fill_b(limit); + + LD_UB8(src - 4, stride, row0, row1, row2, row3, row4, row5, row6, row7); + LD_UB8(src - 4 + (8 * stride), stride, + row8, row9, row10, row11, row12, row13, row14, row15); + TRANSPOSE16x8_UB_UB(row0, row1, row2, row3, row4, row5, row6, row7, + row8, row9, row10, row11, row12, row13, row14, row15, + p3, p2, p1, p0, q0, q1, q2, q3); + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit0, b_limit0, thresh0, + hev, mask); + LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev); + ILVR_B2_SH(p0, p1, q1, q0, tmp0, tmp1); + ILVRL_H2_SH(tmp1, tmp0, tmp2, tmp3); + ILVL_B2_SH(p0, p1, q1, q0, tmp0, tmp1); + ILVRL_H2_SH(tmp1, tmp0, tmp4, tmp5); + src -= 2; + ST4x8_UB(tmp2, tmp3, src, stride); + src += (8 * stride); + ST4x8_UB(tmp4, tmp5, src, stride); +} + +static void HFilter16i(uint8_t* src_y, int stride, + int b_limit, int limit, int thresh) { + HFilterVertEdge16i(src_y + 4, stride, b_limit, limit, thresh); + HFilterVertEdge16i(src_y + 8, stride, b_limit, limit, thresh); + HFilterVertEdge16i(src_y + 12, stride, b_limit, limit, thresh); +} + +// 8-pixels wide variants, for chroma filtering +static void VFilter8(uint8_t* src_u, uint8_t* src_v, int stride, + int b_limit_in, int limit_in, int thresh_in) { + uint8_t* ptmp_src_u = src_u - 4 * stride; + uint8_t* ptmp_src_v = src_v - 4 * stride; + uint64_t p2_d, p1_d, p0_d, q0_d, q1_d, q2_d; + v16u8 p3, p2, p1, p0, q3, q2, q1, q0, mask, hev; + v16u8 p3_u, p2_u, p1_u, p0_u, q3_u, q2_u, q1_u, q0_u; + v16u8 p3_v, p2_v, p1_v, p0_v, q3_v, q2_v, q1_v, q0_v; + const v16u8 b_limit = (v16u8)__msa_fill_b(b_limit_in); + const v16u8 limit = (v16u8)__msa_fill_b(limit_in); + const v16u8 thresh = (v16u8)__msa_fill_b(thresh_in); + + LD_UB8(ptmp_src_u, stride, p3_u, p2_u, p1_u, p0_u, q0_u, q1_u, q2_u, q3_u); + LD_UB8(ptmp_src_v, stride, p3_v, p2_v, p1_v, p0_v, q0_v, q1_v, q2_v, q3_v); + ILVR_D4_UB(p3_v, p3_u, p2_v, p2_u, p1_v, p1_u, p0_v, p0_u, p3, p2, p1, p0); + ILVR_D4_UB(q0_v, q0_u, q1_v, q1_u, q2_v, q2_u, q3_v, q3_u, q0, q1, q2, q3); + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask); + LPF_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev); + p2_d = __msa_copy_s_d((v2i64)p2, 0); + p1_d = __msa_copy_s_d((v2i64)p1, 0); + p0_d = __msa_copy_s_d((v2i64)p0, 0); + q0_d = __msa_copy_s_d((v2i64)q0, 0); + q1_d = __msa_copy_s_d((v2i64)q1, 0); + q2_d = __msa_copy_s_d((v2i64)q2, 0); + ptmp_src_u += stride; + SD4(p2_d, p1_d, p0_d, q0_d, ptmp_src_u, stride); + ptmp_src_u += (4 * stride); + SD(q1_d, ptmp_src_u); + ptmp_src_u += stride; + SD(q2_d, ptmp_src_u); + p2_d = __msa_copy_s_d((v2i64)p2, 1); + p1_d = __msa_copy_s_d((v2i64)p1, 1); + p0_d = __msa_copy_s_d((v2i64)p0, 1); + q0_d = __msa_copy_s_d((v2i64)q0, 1); + q1_d = __msa_copy_s_d((v2i64)q1, 1); + q2_d = __msa_copy_s_d((v2i64)q2, 1); + ptmp_src_v += stride; + SD4(p2_d, p1_d, p0_d, q0_d, ptmp_src_v, stride); + ptmp_src_v += (4 * stride); + SD(q1_d, ptmp_src_v); + ptmp_src_v += stride; + SD(q2_d, ptmp_src_v); +} + +static void HFilter8(uint8_t* src_u, uint8_t* src_v, int stride, + int b_limit_in, int limit_in, int thresh_in) { + uint8_t* ptmp_src_u = src_u - 4; + uint8_t* ptmp_src_v = src_v - 4; + v16u8 p3, p2, p1, p0, q3, q2, q1, q0, mask, hev; + v16u8 row0, row1, row2, row3, row4, row5, row6, row7, row8; + v16u8 row9, row10, row11, row12, row13, row14, row15; + v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + const v16u8 b_limit = (v16u8)__msa_fill_b(b_limit_in); + const v16u8 limit = (v16u8)__msa_fill_b(limit_in); + const v16u8 thresh = (v16u8)__msa_fill_b(thresh_in); + + LD_UB8(ptmp_src_u, stride, row0, row1, row2, row3, row4, row5, row6, row7); + LD_UB8(ptmp_src_v, stride, + row8, row9, row10, row11, row12, row13, row14, row15); + TRANSPOSE16x8_UB_UB(row0, row1, row2, row3, row4, row5, row6, row7, + row8, row9, row10, row11, row12, row13, row14, row15, + p3, p2, p1, p0, q0, q1, q2, q3); + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask); + LPF_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev); + ILVR_B2_SH(p1, p2, q0, p0, tmp0, tmp1); + ILVRL_H2_SH(tmp1, tmp0, tmp3, tmp4); + ILVL_B2_SH(p1, p2, q0, p0, tmp0, tmp1); + ILVRL_H2_SH(tmp1, tmp0, tmp6, tmp7); + ILVRL_B2_SH(q2, q1, tmp2, tmp5); + ptmp_src_u += 1; + ST6x4_UB(tmp3, 0, tmp2, 0, ptmp_src_u, stride); + ptmp_src_u += 4 * stride; + ST6x4_UB(tmp4, 0, tmp2, 4, ptmp_src_u, stride); + ptmp_src_v += 1; + ST6x4_UB(tmp6, 0, tmp5, 0, ptmp_src_v, stride); + ptmp_src_v += 4 * stride; + ST6x4_UB(tmp7, 0, tmp5, 4, ptmp_src_v, stride); +} + +static void VFilter8i(uint8_t* src_u, uint8_t* src_v, int stride, + int b_limit_in, int limit_in, int thresh_in) { + uint64_t p1_d, p0_d, q0_d, q1_d; + v16u8 p3, p2, p1, p0, q3, q2, q1, q0, mask, hev; + v16u8 p3_u, p2_u, p1_u, p0_u, q3_u, q2_u, q1_u, q0_u; + v16u8 p3_v, p2_v, p1_v, p0_v, q3_v, q2_v, q1_v, q0_v; + const v16u8 thresh = (v16u8)__msa_fill_b(thresh_in); + const v16u8 limit = (v16u8)__msa_fill_b(limit_in); + const v16u8 b_limit = (v16u8)__msa_fill_b(b_limit_in); + + LD_UB8(src_u, stride, p3_u, p2_u, p1_u, p0_u, q0_u, q1_u, q2_u, q3_u); + src_u += (5 * stride); + LD_UB8(src_v, stride, p3_v, p2_v, p1_v, p0_v, q0_v, q1_v, q2_v, q3_v); + src_v += (5 * stride); + ILVR_D4_UB(p3_v, p3_u, p2_v, p2_u, p1_v, p1_u, p0_v, p0_u, p3, p2, p1, p0); + ILVR_D4_UB(q0_v, q0_u, q1_v, q1_u, q2_v, q2_u, q3_v, q3_u, q0, q1, q2, q3); + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask); + LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev); + p1_d = __msa_copy_s_d((v2i64)p1, 0); + p0_d = __msa_copy_s_d((v2i64)p0, 0); + q0_d = __msa_copy_s_d((v2i64)q0, 0); + q1_d = __msa_copy_s_d((v2i64)q1, 0); + SD4(q1_d, q0_d, p0_d, p1_d, src_u, -stride); + p1_d = __msa_copy_s_d((v2i64)p1, 1); + p0_d = __msa_copy_s_d((v2i64)p0, 1); + q0_d = __msa_copy_s_d((v2i64)q0, 1); + q1_d = __msa_copy_s_d((v2i64)q1, 1); + SD4(q1_d, q0_d, p0_d, p1_d, src_v, -stride); +} + +static void HFilter8i(uint8_t* src_u, uint8_t* src_v, int stride, + int b_limit_in, int limit_in, int thresh_in) { + v16u8 p3, p2, p1, p0, q3, q2, q1, q0, mask, hev; + v16u8 row0, row1, row2, row3, row4, row5, row6, row7, row8; + v16u8 row9, row10, row11, row12, row13, row14, row15; + v4i32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + const v16u8 thresh = (v16u8)__msa_fill_b(thresh_in); + const v16u8 limit = (v16u8)__msa_fill_b(limit_in); + const v16u8 b_limit = (v16u8)__msa_fill_b(b_limit_in); + + LD_UB8(src_u, stride, row0, row1, row2, row3, row4, row5, row6, row7); + LD_UB8(src_v, stride, + row8, row9, row10, row11, row12, row13, row14, row15); + TRANSPOSE16x8_UB_UB(row0, row1, row2, row3, row4, row5, row6, row7, + row8, row9, row10, row11, row12, row13, row14, row15, + p3, p2, p1, p0, q0, q1, q2, q3); + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask); + LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev); + ILVR_B2_SW(p0, p1, q1, q0, tmp0, tmp1); + ILVRL_H2_SW(tmp1, tmp0, tmp2, tmp3); + ILVL_B2_SW(p0, p1, q1, q0, tmp0, tmp1); + ILVRL_H2_SW(tmp1, tmp0, tmp4, tmp5); + src_u += 2; + ST4x4_UB(tmp2, tmp2, 0, 1, 2, 3, src_u, stride); + src_u += 4 * stride; + ST4x4_UB(tmp3, tmp3, 0, 1, 2, 3, src_u, stride); + src_v += 2; + ST4x4_UB(tmp4, tmp4, 0, 1, 2, 3, src_v, stride); + src_v += 4 * stride; + ST4x4_UB(tmp5, tmp5, 0, 1, 2, 3, src_v, stride); +} + +static void SimpleVFilter16(uint8_t* src, int stride, int b_limit_in) { + v16u8 p1, p0, q1, q0, mask; + const v16u8 b_limit = (v16u8)__msa_fill_b(b_limit_in); + + LD_UB4(src - 2 * stride, stride, p1, p0, q0, q1); + LPF_SIMPLE_MASK(p1, p0, q0, q1, b_limit, mask); + LPF_SIMPLE_FILT(p1, p0, q0, q1, mask); + ST_UB2(p0, q0, src - stride, stride); +} + +static void SimpleHFilter16(uint8_t* src, int stride, int b_limit_in) { + v16u8 p1, p0, q1, q0, mask, row0, row1, row2, row3, row4, row5, row6, row7; + v16u8 row8, row9, row10, row11, row12, row13, row14, row15; + v8i16 tmp0, tmp1; + const v16u8 b_limit = (v16u8)__msa_fill_b(b_limit_in); + uint8_t* ptemp_src = src - 2; + + LD_UB8(ptemp_src, stride, row0, row1, row2, row3, row4, row5, row6, row7); + LD_UB8(ptemp_src + 8 * stride, stride, + row8, row9, row10, row11, row12, row13, row14, row15); + TRANSPOSE16x4_UB_UB(row0, row1, row2, row3, row4, row5, row6, row7, + row8, row9, row10, row11, row12, row13, row14, row15, + p1, p0, q0, q1); + LPF_SIMPLE_MASK(p1, p0, q0, q1, b_limit, mask); + LPF_SIMPLE_FILT(p1, p0, q0, q1, mask); + ILVRL_B2_SH(q0, p0, tmp1, tmp0); + ptemp_src += 1; + ST2x4_UB(tmp1, 0, ptemp_src, stride); + ptemp_src += 4 * stride; + ST2x4_UB(tmp1, 4, ptemp_src, stride); + ptemp_src += 4 * stride; + ST2x4_UB(tmp0, 0, ptemp_src, stride); + ptemp_src += 4 * stride; + ST2x4_UB(tmp0, 4, ptemp_src, stride); + ptemp_src += 4 * stride; +} + +static void SimpleVFilter16i(uint8_t* src_y, int stride, int b_limit_in) { + SimpleVFilter16(src_y + 4 * stride, stride, b_limit_in); + SimpleVFilter16(src_y + 8 * stride, stride, b_limit_in); + SimpleVFilter16(src_y + 12 * stride, stride, b_limit_in); +} + +static void SimpleHFilter16i(uint8_t* src_y, int stride, int b_limit_in) { + SimpleHFilter16(src_y + 4, stride, b_limit_in); + SimpleHFilter16(src_y + 8, stride, b_limit_in); + SimpleHFilter16(src_y + 12, stride, b_limit_in); +} + +//------------------------------------------------------------------------------ +// Intra predictions +//------------------------------------------------------------------------------ + +// 4x4 + +static void DC4(uint8_t* dst) { // DC + uint32_t dc = 4; + int i; + for (i = 0; i < 4; ++i) dc += dst[i - BPS] + dst[-1 + i * BPS]; + dc >>= 3; + dc = dc | (dc << 8) | (dc << 16) | (dc << 24); + SW4(dc, dc, dc, dc, dst, BPS); +} + +static void TM4(uint8_t* dst) { + const uint8_t* const ptemp = dst - BPS - 1; + v8i16 T, d, r0, r1, r2, r3; + const v16i8 zero = { 0 }; + const v8i16 TL = (v8i16)__msa_fill_h(ptemp[0 * BPS]); + const v8i16 L0 = (v8i16)__msa_fill_h(ptemp[1 * BPS]); + const v8i16 L1 = (v8i16)__msa_fill_h(ptemp[2 * BPS]); + const v8i16 L2 = (v8i16)__msa_fill_h(ptemp[3 * BPS]); + const v8i16 L3 = (v8i16)__msa_fill_h(ptemp[4 * BPS]); + const v16u8 T1 = LD_UB(ptemp + 1); + + T = (v8i16)__msa_ilvr_b(zero, (v16i8)T1); + d = T - TL; + ADD4(d, L0, d, L1, d, L2, d, L3, r0, r1, r2, r3); + CLIP_SH4_0_255(r0, r1, r2, r3); + PCKEV_ST4x4_UB(r0, r1, r2, r3, dst, BPS); +} + +static void VE4(uint8_t* dst) { // vertical + const uint8_t* const ptop = dst - BPS - 1; + const uint32_t val0 = LW(ptop + 0); + const uint32_t val1 = LW(ptop + 4); + uint32_t out; + v16u8 A = { 0 }, B, C, AC, B2, R; + + INSERT_W2_UB(val0, val1, A); + B = SLDI_UB(A, A, 1); + C = SLDI_UB(A, A, 2); + AC = __msa_ave_u_b(A, C); + B2 = __msa_ave_u_b(B, B); + R = __msa_aver_u_b(AC, B2); + out = __msa_copy_s_w((v4i32)R, 0); + SW4(out, out, out, out, dst, BPS); +} + +static void RD4(uint8_t* dst) { // Down-right + const uint8_t* const ptop = dst - 1 - BPS; + uint32_t val0 = LW(ptop + 0); + uint32_t val1 = LW(ptop + 4); + uint32_t val2, val3; + v16u8 A, B, C, AC, B2, R, A1 = { 0 }; + + INSERT_W2_UB(val0, val1, A1); + A = SLDI_UB(A1, A1, 12); + A = (v16u8)__msa_insert_b((v16i8)A, 3, ptop[1 * BPS]); + A = (v16u8)__msa_insert_b((v16i8)A, 2, ptop[2 * BPS]); + A = (v16u8)__msa_insert_b((v16i8)A, 1, ptop[3 * BPS]); + A = (v16u8)__msa_insert_b((v16i8)A, 0, ptop[4 * BPS]); + B = SLDI_UB(A, A, 1); + C = SLDI_UB(A, A, 2); + AC = __msa_ave_u_b(A, C); + B2 = __msa_ave_u_b(B, B); + R = __msa_aver_u_b(AC, B2); + val3 = __msa_copy_s_w((v4i32)R, 0); + R = SLDI_UB(R, R, 1); + val2 = __msa_copy_s_w((v4i32)R, 0); + R = SLDI_UB(R, R, 1); + val1 = __msa_copy_s_w((v4i32)R, 0); + R = SLDI_UB(R, R, 1); + val0 = __msa_copy_s_w((v4i32)R, 0); + SW4(val0, val1, val2, val3, dst, BPS); +} + +static void LD4(uint8_t* dst) { // Down-Left + const uint8_t* const ptop = dst - BPS; + uint32_t val0 = LW(ptop + 0); + uint32_t val1 = LW(ptop + 4); + uint32_t val2, val3; + v16u8 A = { 0 }, B, C, AC, B2, R; + + INSERT_W2_UB(val0, val1, A); + B = SLDI_UB(A, A, 1); + C = SLDI_UB(A, A, 2); + C = (v16u8)__msa_insert_b((v16i8)C, 6, ptop[7]); + AC = __msa_ave_u_b(A, C); + B2 = __msa_ave_u_b(B, B); + R = __msa_aver_u_b(AC, B2); + val0 = __msa_copy_s_w((v4i32)R, 0); + R = SLDI_UB(R, R, 1); + val1 = __msa_copy_s_w((v4i32)R, 0); + R = SLDI_UB(R, R, 1); + val2 = __msa_copy_s_w((v4i32)R, 0); + R = SLDI_UB(R, R, 1); + val3 = __msa_copy_s_w((v4i32)R, 0); + SW4(val0, val1, val2, val3, dst, BPS); +} + +// 16x16 + +static void DC16(uint8_t* dst) { // DC + uint32_t dc = 16; + int i; + const v16u8 rtop = LD_UB(dst - BPS); + const v8u16 dctop = __msa_hadd_u_h(rtop, rtop); + v16u8 out; + + for (i = 0; i < 16; ++i) { + dc += dst[-1 + i * BPS]; + } + dc += HADD_UH_U32(dctop); + out = (v16u8)__msa_fill_b(dc >> 5); + ST_UB8(out, out, out, out, out, out, out, out, dst, BPS); + ST_UB8(out, out, out, out, out, out, out, out, dst + 8 * BPS, BPS); +} + +static void TM16(uint8_t* dst) { + int j; + v8i16 d1, d2; + const v16i8 zero = { 0 }; + const v8i16 TL = (v8i16)__msa_fill_h(dst[-1 - BPS]); + const v16i8 T = LD_SB(dst - BPS); + + ILVRL_B2_SH(zero, T, d1, d2); + SUB2(d1, TL, d2, TL, d1, d2); + for (j = 0; j < 16; j += 4) { + v16i8 t0, t1, t2, t3; + v8i16 r0, r1, r2, r3, r4, r5, r6, r7; + const v8i16 L0 = (v8i16)__msa_fill_h(dst[-1 + 0 * BPS]); + const v8i16 L1 = (v8i16)__msa_fill_h(dst[-1 + 1 * BPS]); + const v8i16 L2 = (v8i16)__msa_fill_h(dst[-1 + 2 * BPS]); + const v8i16 L3 = (v8i16)__msa_fill_h(dst[-1 + 3 * BPS]); + ADD4(d1, L0, d1, L1, d1, L2, d1, L3, r0, r1, r2, r3); + ADD4(d2, L0, d2, L1, d2, L2, d2, L3, r4, r5, r6, r7); + CLIP_SH4_0_255(r0, r1, r2, r3); + CLIP_SH4_0_255(r4, r5, r6, r7); + PCKEV_B4_SB(r4, r0, r5, r1, r6, r2, r7, r3, t0, t1, t2, t3); + ST_SB4(t0, t1, t2, t3, dst, BPS); + dst += 4 * BPS; + } +} + +static void VE16(uint8_t* dst) { // vertical + const v16u8 rtop = LD_UB(dst - BPS); + ST_UB8(rtop, rtop, rtop, rtop, rtop, rtop, rtop, rtop, dst, BPS); + ST_UB8(rtop, rtop, rtop, rtop, rtop, rtop, rtop, rtop, dst + 8 * BPS, BPS); +} + +static void HE16(uint8_t* dst) { // horizontal + int j; + for (j = 16; j > 0; j -= 4) { + const v16u8 L0 = (v16u8)__msa_fill_b(dst[-1 + 0 * BPS]); + const v16u8 L1 = (v16u8)__msa_fill_b(dst[-1 + 1 * BPS]); + const v16u8 L2 = (v16u8)__msa_fill_b(dst[-1 + 2 * BPS]); + const v16u8 L3 = (v16u8)__msa_fill_b(dst[-1 + 3 * BPS]); + ST_UB4(L0, L1, L2, L3, dst, BPS); + dst += 4 * BPS; + } +} + +static void DC16NoTop(uint8_t* dst) { // DC with top samples not available + int j; + uint32_t dc = 8; + v16u8 out; + + for (j = 0; j < 16; ++j) { + dc += dst[-1 + j * BPS]; + } + out = (v16u8)__msa_fill_b(dc >> 4); + ST_UB8(out, out, out, out, out, out, out, out, dst, BPS); + ST_UB8(out, out, out, out, out, out, out, out, dst + 8 * BPS, BPS); +} + +static void DC16NoLeft(uint8_t* dst) { // DC with left samples not available + uint32_t dc = 8; + const v16u8 rtop = LD_UB(dst - BPS); + const v8u16 dctop = __msa_hadd_u_h(rtop, rtop); + v16u8 out; + + dc += HADD_UH_U32(dctop); + out = (v16u8)__msa_fill_b(dc >> 4); + ST_UB8(out, out, out, out, out, out, out, out, dst, BPS); + ST_UB8(out, out, out, out, out, out, out, out, dst + 8 * BPS, BPS); +} + +static void DC16NoTopLeft(uint8_t* dst) { // DC with nothing + const v16u8 out = (v16u8)__msa_fill_b(0x80); + ST_UB8(out, out, out, out, out, out, out, out, dst, BPS); + ST_UB8(out, out, out, out, out, out, out, out, dst + 8 * BPS, BPS); +} + +// Chroma + +#define STORE8x8(out, dst) do { \ + SD4(out, out, out, out, dst + 0 * BPS, BPS); \ + SD4(out, out, out, out, dst + 4 * BPS, BPS); \ +} while (0) + +static void DC8uv(uint8_t* dst) { // DC + uint32_t dc = 8; + int i; + uint64_t out; + const v16u8 rtop = LD_UB(dst - BPS); + const v8u16 temp0 = __msa_hadd_u_h(rtop, rtop); + const v4u32 temp1 = __msa_hadd_u_w(temp0, temp0); + const v2u64 temp2 = __msa_hadd_u_d(temp1, temp1); + v16u8 dctemp; + + for (i = 0; i < 8; ++i) { + dc += dst[-1 + i * BPS]; + } + dc += __msa_copy_s_w((v4i32)temp2, 0); + dctemp = (v16u8)__msa_fill_b(dc >> 4); + out = __msa_copy_s_d((v2i64)dctemp, 0); + STORE8x8(out, dst); +} + +static void TM8uv(uint8_t* dst) { + int j; + const v16i8 T1 = LD_SB(dst - BPS); + const v16i8 zero = { 0 }; + const v8i16 T = (v8i16)__msa_ilvr_b(zero, T1); + const v8i16 TL = (v8i16)__msa_fill_h(dst[-1 - BPS]); + const v8i16 d = T - TL; + + for (j = 0; j < 8; j += 4) { + v16i8 t0, t1; + v8i16 r0 = (v8i16)__msa_fill_h(dst[-1 + 0 * BPS]); + v8i16 r1 = (v8i16)__msa_fill_h(dst[-1 + 1 * BPS]); + v8i16 r2 = (v8i16)__msa_fill_h(dst[-1 + 2 * BPS]); + v8i16 r3 = (v8i16)__msa_fill_h(dst[-1 + 3 * BPS]); + ADD4(d, r0, d, r1, d, r2, d, r3, r0, r1, r2, r3); + CLIP_SH4_0_255(r0, r1, r2, r3); + PCKEV_B2_SB(r1, r0, r3, r2, t0, t1); + ST4x4_UB(t0, t1, 0, 2, 0, 2, dst, BPS); + ST4x4_UB(t0, t1, 1, 3, 1, 3, dst + 4, BPS); + dst += 4 * BPS; + } +} + +static void VE8uv(uint8_t* dst) { // vertical + const v16u8 rtop = LD_UB(dst - BPS); + const uint64_t out = __msa_copy_s_d((v2i64)rtop, 0); + STORE8x8(out, dst); +} + +static void HE8uv(uint8_t* dst) { // horizontal + int j; + for (j = 0; j < 8; j += 4) { + const v16u8 L0 = (v16u8)__msa_fill_b(dst[-1 + 0 * BPS]); + const v16u8 L1 = (v16u8)__msa_fill_b(dst[-1 + 1 * BPS]); + const v16u8 L2 = (v16u8)__msa_fill_b(dst[-1 + 2 * BPS]); + const v16u8 L3 = (v16u8)__msa_fill_b(dst[-1 + 3 * BPS]); + const uint64_t out0 = __msa_copy_s_d((v2i64)L0, 0); + const uint64_t out1 = __msa_copy_s_d((v2i64)L1, 0); + const uint64_t out2 = __msa_copy_s_d((v2i64)L2, 0); + const uint64_t out3 = __msa_copy_s_d((v2i64)L3, 0); + SD4(out0, out1, out2, out3, dst, BPS); + dst += 4 * BPS; + } +} + +static void DC8uvNoLeft(uint8_t* dst) { // DC with no left samples + const uint32_t dc = 4; + const v16u8 rtop = LD_UB(dst - BPS); + const v8u16 temp0 = __msa_hadd_u_h(rtop, rtop); + const v4u32 temp1 = __msa_hadd_u_w(temp0, temp0); + const v2u64 temp2 = __msa_hadd_u_d(temp1, temp1); + const uint32_t sum_m = __msa_copy_s_w((v4i32)temp2, 0); + const v16u8 dcval = (v16u8)__msa_fill_b((dc + sum_m) >> 3); + const uint64_t out = __msa_copy_s_d((v2i64)dcval, 0); + STORE8x8(out, dst); +} + +static void DC8uvNoTop(uint8_t* dst) { // DC with no top samples + uint32_t dc = 4; + int i; + uint64_t out; + v16u8 dctemp; + + for (i = 0; i < 8; ++i) { + dc += dst[-1 + i * BPS]; + } + dctemp = (v16u8)__msa_fill_b(dc >> 3); + out = __msa_copy_s_d((v2i64)dctemp, 0); + STORE8x8(out, dst); +} + +static void DC8uvNoTopLeft(uint8_t* dst) { // DC with nothing + const uint64_t out = 0x8080808080808080ULL; + STORE8x8(out, dst); +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8DspInitMSA(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitMSA(void) { + VP8TransformWHT = TransformWHT; + VP8Transform = TransformTwo; + VP8TransformDC = TransformDC; + VP8TransformAC3 = TransformAC3; + + VP8VFilter16 = VFilter16; + VP8HFilter16 = HFilter16; + VP8VFilter16i = VFilter16i; + VP8HFilter16i = HFilter16i; + VP8VFilter8 = VFilter8; + VP8HFilter8 = HFilter8; + VP8VFilter8i = VFilter8i; + VP8HFilter8i = HFilter8i; + VP8SimpleVFilter16 = SimpleVFilter16; + VP8SimpleHFilter16 = SimpleHFilter16; + VP8SimpleVFilter16i = SimpleVFilter16i; + VP8SimpleHFilter16i = SimpleHFilter16i; + + VP8PredLuma4[0] = DC4; + VP8PredLuma4[1] = TM4; + VP8PredLuma4[2] = VE4; + VP8PredLuma4[4] = RD4; + VP8PredLuma4[6] = LD4; + VP8PredLuma16[0] = DC16; + VP8PredLuma16[1] = TM16; + VP8PredLuma16[2] = VE16; + VP8PredLuma16[3] = HE16; + VP8PredLuma16[4] = DC16NoTop; + VP8PredLuma16[5] = DC16NoLeft; + VP8PredLuma16[6] = DC16NoTopLeft; + VP8PredChroma8[0] = DC8uv; + VP8PredChroma8[1] = TM8uv; + VP8PredChroma8[2] = VE8uv; + VP8PredChroma8[3] = HE8uv; + VP8PredChroma8[4] = DC8uvNoTop; + VP8PredChroma8[5] = DC8uvNoLeft; + VP8PredChroma8[6] = DC8uvNoTopLeft; +} + +#else // !WEBP_USE_MSA + +WEBP_DSP_INIT_STUB(VP8DspInitMSA) + +#endif // WEBP_USE_MSA diff --git a/third-party/webp/libwebp/src/dsp/dec_neon.c b/third-party/webp/libwebp/src/dsp/dec_neon.c new file mode 100644 index 0000000000..22784cf15a --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/dec_neon.c @@ -0,0 +1,1663 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// ARM NEON version of dsp functions and loop filtering. +// +// Authors: Somnath Banerjee (somnath@google.com) +// Johann Koenig (johannkoenig@google.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_NEON) + +#include "src/dsp/neon.h" +#include "src/dec/vp8i_dec.h" + +//------------------------------------------------------------------------------ +// NxM Loading functions + +#if !defined(WORK_AROUND_GCC) + +// This intrinsics version makes gcc-4.6.3 crash during Load4x??() compilation +// (register alloc, probably). The variants somewhat mitigate the problem, but +// not quite. HFilter16i() remains problematic. +static WEBP_INLINE uint8x8x4_t Load4x8_NEON(const uint8_t* const src, + int stride) { + const uint8x8_t zero = vdup_n_u8(0); + uint8x8x4_t out; + INIT_VECTOR4(out, zero, zero, zero, zero); + out = vld4_lane_u8(src + 0 * stride, out, 0); + out = vld4_lane_u8(src + 1 * stride, out, 1); + out = vld4_lane_u8(src + 2 * stride, out, 2); + out = vld4_lane_u8(src + 3 * stride, out, 3); + out = vld4_lane_u8(src + 4 * stride, out, 4); + out = vld4_lane_u8(src + 5 * stride, out, 5); + out = vld4_lane_u8(src + 6 * stride, out, 6); + out = vld4_lane_u8(src + 7 * stride, out, 7); + return out; +} + +static WEBP_INLINE void Load4x16_NEON(const uint8_t* const src, int stride, + uint8x16_t* const p1, + uint8x16_t* const p0, + uint8x16_t* const q0, + uint8x16_t* const q1) { + // row0 = p1[0..7]|p0[0..7]|q0[0..7]|q1[0..7] + // row8 = p1[8..15]|p0[8..15]|q0[8..15]|q1[8..15] + const uint8x8x4_t row0 = Load4x8_NEON(src - 2 + 0 * stride, stride); + const uint8x8x4_t row8 = Load4x8_NEON(src - 2 + 8 * stride, stride); + *p1 = vcombine_u8(row0.val[0], row8.val[0]); + *p0 = vcombine_u8(row0.val[1], row8.val[1]); + *q0 = vcombine_u8(row0.val[2], row8.val[2]); + *q1 = vcombine_u8(row0.val[3], row8.val[3]); +} + +#else // WORK_AROUND_GCC + +#define LOADQ_LANE_32b(VALUE, LANE) do { \ + (VALUE) = vld1q_lane_u32((const uint32_t*)src, (VALUE), (LANE)); \ + src += stride; \ +} while (0) + +static WEBP_INLINE void Load4x16_NEON(const uint8_t* src, int stride, + uint8x16_t* const p1, + uint8x16_t* const p0, + uint8x16_t* const q0, + uint8x16_t* const q1) { + const uint32x4_t zero = vdupq_n_u32(0); + uint32x4x4_t in; + INIT_VECTOR4(in, zero, zero, zero, zero); + src -= 2; + LOADQ_LANE_32b(in.val[0], 0); + LOADQ_LANE_32b(in.val[1], 0); + LOADQ_LANE_32b(in.val[2], 0); + LOADQ_LANE_32b(in.val[3], 0); + LOADQ_LANE_32b(in.val[0], 1); + LOADQ_LANE_32b(in.val[1], 1); + LOADQ_LANE_32b(in.val[2], 1); + LOADQ_LANE_32b(in.val[3], 1); + LOADQ_LANE_32b(in.val[0], 2); + LOADQ_LANE_32b(in.val[1], 2); + LOADQ_LANE_32b(in.val[2], 2); + LOADQ_LANE_32b(in.val[3], 2); + LOADQ_LANE_32b(in.val[0], 3); + LOADQ_LANE_32b(in.val[1], 3); + LOADQ_LANE_32b(in.val[2], 3); + LOADQ_LANE_32b(in.val[3], 3); + // Transpose four 4x4 parts: + { + const uint8x16x2_t row01 = vtrnq_u8(vreinterpretq_u8_u32(in.val[0]), + vreinterpretq_u8_u32(in.val[1])); + const uint8x16x2_t row23 = vtrnq_u8(vreinterpretq_u8_u32(in.val[2]), + vreinterpretq_u8_u32(in.val[3])); + const uint16x8x2_t row02 = vtrnq_u16(vreinterpretq_u16_u8(row01.val[0]), + vreinterpretq_u16_u8(row23.val[0])); + const uint16x8x2_t row13 = vtrnq_u16(vreinterpretq_u16_u8(row01.val[1]), + vreinterpretq_u16_u8(row23.val[1])); + *p1 = vreinterpretq_u8_u16(row02.val[0]); + *p0 = vreinterpretq_u8_u16(row13.val[0]); + *q0 = vreinterpretq_u8_u16(row02.val[1]); + *q1 = vreinterpretq_u8_u16(row13.val[1]); + } +} +#undef LOADQ_LANE_32b + +#endif // !WORK_AROUND_GCC + +static WEBP_INLINE void Load8x16_NEON( + const uint8_t* const src, int stride, + uint8x16_t* const p3, uint8x16_t* const p2, uint8x16_t* const p1, + uint8x16_t* const p0, uint8x16_t* const q0, uint8x16_t* const q1, + uint8x16_t* const q2, uint8x16_t* const q3) { + Load4x16_NEON(src - 2, stride, p3, p2, p1, p0); + Load4x16_NEON(src + 2, stride, q0, q1, q2, q3); +} + +static WEBP_INLINE void Load16x4_NEON(const uint8_t* const src, int stride, + uint8x16_t* const p1, + uint8x16_t* const p0, + uint8x16_t* const q0, + uint8x16_t* const q1) { + *p1 = vld1q_u8(src - 2 * stride); + *p0 = vld1q_u8(src - 1 * stride); + *q0 = vld1q_u8(src + 0 * stride); + *q1 = vld1q_u8(src + 1 * stride); +} + +static WEBP_INLINE void Load16x8_NEON( + const uint8_t* const src, int stride, + uint8x16_t* const p3, uint8x16_t* const p2, uint8x16_t* const p1, + uint8x16_t* const p0, uint8x16_t* const q0, uint8x16_t* const q1, + uint8x16_t* const q2, uint8x16_t* const q3) { + Load16x4_NEON(src - 2 * stride, stride, p3, p2, p1, p0); + Load16x4_NEON(src + 2 * stride, stride, q0, q1, q2, q3); +} + +static WEBP_INLINE void Load8x8x2_NEON( + const uint8_t* const u, const uint8_t* const v, int stride, + uint8x16_t* const p3, uint8x16_t* const p2, uint8x16_t* const p1, + uint8x16_t* const p0, uint8x16_t* const q0, uint8x16_t* const q1, + uint8x16_t* const q2, uint8x16_t* const q3) { + // We pack the 8x8 u-samples in the lower half of the uint8x16_t destination + // and the v-samples on the higher half. + *p3 = vcombine_u8(vld1_u8(u - 4 * stride), vld1_u8(v - 4 * stride)); + *p2 = vcombine_u8(vld1_u8(u - 3 * stride), vld1_u8(v - 3 * stride)); + *p1 = vcombine_u8(vld1_u8(u - 2 * stride), vld1_u8(v - 2 * stride)); + *p0 = vcombine_u8(vld1_u8(u - 1 * stride), vld1_u8(v - 1 * stride)); + *q0 = vcombine_u8(vld1_u8(u + 0 * stride), vld1_u8(v + 0 * stride)); + *q1 = vcombine_u8(vld1_u8(u + 1 * stride), vld1_u8(v + 1 * stride)); + *q2 = vcombine_u8(vld1_u8(u + 2 * stride), vld1_u8(v + 2 * stride)); + *q3 = vcombine_u8(vld1_u8(u + 3 * stride), vld1_u8(v + 3 * stride)); +} + +#if !defined(WORK_AROUND_GCC) + +#define LOAD_UV_8(ROW) \ + vcombine_u8(vld1_u8(u - 4 + (ROW) * stride), vld1_u8(v - 4 + (ROW) * stride)) + +static WEBP_INLINE void Load8x8x2T_NEON( + const uint8_t* const u, const uint8_t* const v, int stride, + uint8x16_t* const p3, uint8x16_t* const p2, uint8x16_t* const p1, + uint8x16_t* const p0, uint8x16_t* const q0, uint8x16_t* const q1, + uint8x16_t* const q2, uint8x16_t* const q3) { + // We pack the 8x8 u-samples in the lower half of the uint8x16_t destination + // and the v-samples on the higher half. + const uint8x16_t row0 = LOAD_UV_8(0); + const uint8x16_t row1 = LOAD_UV_8(1); + const uint8x16_t row2 = LOAD_UV_8(2); + const uint8x16_t row3 = LOAD_UV_8(3); + const uint8x16_t row4 = LOAD_UV_8(4); + const uint8x16_t row5 = LOAD_UV_8(5); + const uint8x16_t row6 = LOAD_UV_8(6); + const uint8x16_t row7 = LOAD_UV_8(7); + // Perform two side-by-side 8x8 transposes + // u00 u01 u02 u03 u04 u05 u06 u07 | v00 v01 v02 v03 v04 v05 v06 v07 + // u10 u11 u12 u13 u14 u15 u16 u17 | v10 v11 v12 ... + // u20 u21 u22 u23 u24 u25 u26 u27 | v20 v21 ... + // u30 u31 u32 u33 u34 u35 u36 u37 | ... + // u40 u41 u42 u43 u44 u45 u46 u47 | ... + // u50 u51 u52 u53 u54 u55 u56 u57 | ... + // u60 u61 u62 u63 u64 u65 u66 u67 | v60 ... + // u70 u71 u72 u73 u74 u75 u76 u77 | v70 v71 v72 ... + const uint8x16x2_t row01 = vtrnq_u8(row0, row1); // u00 u10 u02 u12 ... + // u01 u11 u03 u13 ... + const uint8x16x2_t row23 = vtrnq_u8(row2, row3); // u20 u30 u22 u32 ... + // u21 u31 u23 u33 ... + const uint8x16x2_t row45 = vtrnq_u8(row4, row5); // ... + const uint8x16x2_t row67 = vtrnq_u8(row6, row7); // ... + const uint16x8x2_t row02 = vtrnq_u16(vreinterpretq_u16_u8(row01.val[0]), + vreinterpretq_u16_u8(row23.val[0])); + const uint16x8x2_t row13 = vtrnq_u16(vreinterpretq_u16_u8(row01.val[1]), + vreinterpretq_u16_u8(row23.val[1])); + const uint16x8x2_t row46 = vtrnq_u16(vreinterpretq_u16_u8(row45.val[0]), + vreinterpretq_u16_u8(row67.val[0])); + const uint16x8x2_t row57 = vtrnq_u16(vreinterpretq_u16_u8(row45.val[1]), + vreinterpretq_u16_u8(row67.val[1])); + const uint32x4x2_t row04 = vtrnq_u32(vreinterpretq_u32_u16(row02.val[0]), + vreinterpretq_u32_u16(row46.val[0])); + const uint32x4x2_t row26 = vtrnq_u32(vreinterpretq_u32_u16(row02.val[1]), + vreinterpretq_u32_u16(row46.val[1])); + const uint32x4x2_t row15 = vtrnq_u32(vreinterpretq_u32_u16(row13.val[0]), + vreinterpretq_u32_u16(row57.val[0])); + const uint32x4x2_t row37 = vtrnq_u32(vreinterpretq_u32_u16(row13.val[1]), + vreinterpretq_u32_u16(row57.val[1])); + *p3 = vreinterpretq_u8_u32(row04.val[0]); + *p2 = vreinterpretq_u8_u32(row15.val[0]); + *p1 = vreinterpretq_u8_u32(row26.val[0]); + *p0 = vreinterpretq_u8_u32(row37.val[0]); + *q0 = vreinterpretq_u8_u32(row04.val[1]); + *q1 = vreinterpretq_u8_u32(row15.val[1]); + *q2 = vreinterpretq_u8_u32(row26.val[1]); + *q3 = vreinterpretq_u8_u32(row37.val[1]); +} +#undef LOAD_UV_8 + +#endif // !WORK_AROUND_GCC + +static WEBP_INLINE void Store2x8_NEON(const uint8x8x2_t v, + uint8_t* const dst, int stride) { + vst2_lane_u8(dst + 0 * stride, v, 0); + vst2_lane_u8(dst + 1 * stride, v, 1); + vst2_lane_u8(dst + 2 * stride, v, 2); + vst2_lane_u8(dst + 3 * stride, v, 3); + vst2_lane_u8(dst + 4 * stride, v, 4); + vst2_lane_u8(dst + 5 * stride, v, 5); + vst2_lane_u8(dst + 6 * stride, v, 6); + vst2_lane_u8(dst + 7 * stride, v, 7); +} + +static WEBP_INLINE void Store2x16_NEON(const uint8x16_t p0, const uint8x16_t q0, + uint8_t* const dst, int stride) { + uint8x8x2_t lo, hi; + lo.val[0] = vget_low_u8(p0); + lo.val[1] = vget_low_u8(q0); + hi.val[0] = vget_high_u8(p0); + hi.val[1] = vget_high_u8(q0); + Store2x8_NEON(lo, dst - 1 + 0 * stride, stride); + Store2x8_NEON(hi, dst - 1 + 8 * stride, stride); +} + +#if !defined(WORK_AROUND_GCC) +static WEBP_INLINE void Store4x8_NEON(const uint8x8x4_t v, + uint8_t* const dst, int stride) { + vst4_lane_u8(dst + 0 * stride, v, 0); + vst4_lane_u8(dst + 1 * stride, v, 1); + vst4_lane_u8(dst + 2 * stride, v, 2); + vst4_lane_u8(dst + 3 * stride, v, 3); + vst4_lane_u8(dst + 4 * stride, v, 4); + vst4_lane_u8(dst + 5 * stride, v, 5); + vst4_lane_u8(dst + 6 * stride, v, 6); + vst4_lane_u8(dst + 7 * stride, v, 7); +} + +static WEBP_INLINE void Store4x16_NEON(const uint8x16_t p1, const uint8x16_t p0, + const uint8x16_t q0, const uint8x16_t q1, + uint8_t* const dst, int stride) { + uint8x8x4_t lo, hi; + INIT_VECTOR4(lo, + vget_low_u8(p1), vget_low_u8(p0), + vget_low_u8(q0), vget_low_u8(q1)); + INIT_VECTOR4(hi, + vget_high_u8(p1), vget_high_u8(p0), + vget_high_u8(q0), vget_high_u8(q1)); + Store4x8_NEON(lo, dst - 2 + 0 * stride, stride); + Store4x8_NEON(hi, dst - 2 + 8 * stride, stride); +} +#endif // !WORK_AROUND_GCC + +static WEBP_INLINE void Store16x2_NEON(const uint8x16_t p0, const uint8x16_t q0, + uint8_t* const dst, int stride) { + vst1q_u8(dst - stride, p0); + vst1q_u8(dst, q0); +} + +static WEBP_INLINE void Store16x4_NEON(const uint8x16_t p1, const uint8x16_t p0, + const uint8x16_t q0, const uint8x16_t q1, + uint8_t* const dst, int stride) { + Store16x2_NEON(p1, p0, dst - stride, stride); + Store16x2_NEON(q0, q1, dst + stride, stride); +} + +static WEBP_INLINE void Store8x2x2_NEON(const uint8x16_t p0, + const uint8x16_t q0, + uint8_t* const u, uint8_t* const v, + int stride) { + // p0 and q0 contain the u+v samples packed in low/high halves. + vst1_u8(u - stride, vget_low_u8(p0)); + vst1_u8(u, vget_low_u8(q0)); + vst1_u8(v - stride, vget_high_u8(p0)); + vst1_u8(v, vget_high_u8(q0)); +} + +static WEBP_INLINE void Store8x4x2_NEON(const uint8x16_t p1, + const uint8x16_t p0, + const uint8x16_t q0, + const uint8x16_t q1, + uint8_t* const u, uint8_t* const v, + int stride) { + // The p1...q1 registers contain the u+v samples packed in low/high halves. + Store8x2x2_NEON(p1, p0, u - stride, v - stride, stride); + Store8x2x2_NEON(q0, q1, u + stride, v + stride, stride); +} + +#if !defined(WORK_AROUND_GCC) + +#define STORE6_LANE(DST, VAL0, VAL1, LANE) do { \ + vst3_lane_u8((DST) - 3, (VAL0), (LANE)); \ + vst3_lane_u8((DST) + 0, (VAL1), (LANE)); \ + (DST) += stride; \ +} while (0) + +static WEBP_INLINE void Store6x8x2_NEON( + const uint8x16_t p2, const uint8x16_t p1, const uint8x16_t p0, + const uint8x16_t q0, const uint8x16_t q1, const uint8x16_t q2, + uint8_t* u, uint8_t* v, int stride) { + uint8x8x3_t u0, u1, v0, v1; + INIT_VECTOR3(u0, vget_low_u8(p2), vget_low_u8(p1), vget_low_u8(p0)); + INIT_VECTOR3(u1, vget_low_u8(q0), vget_low_u8(q1), vget_low_u8(q2)); + INIT_VECTOR3(v0, vget_high_u8(p2), vget_high_u8(p1), vget_high_u8(p0)); + INIT_VECTOR3(v1, vget_high_u8(q0), vget_high_u8(q1), vget_high_u8(q2)); + STORE6_LANE(u, u0, u1, 0); + STORE6_LANE(u, u0, u1, 1); + STORE6_LANE(u, u0, u1, 2); + STORE6_LANE(u, u0, u1, 3); + STORE6_LANE(u, u0, u1, 4); + STORE6_LANE(u, u0, u1, 5); + STORE6_LANE(u, u0, u1, 6); + STORE6_LANE(u, u0, u1, 7); + STORE6_LANE(v, v0, v1, 0); + STORE6_LANE(v, v0, v1, 1); + STORE6_LANE(v, v0, v1, 2); + STORE6_LANE(v, v0, v1, 3); + STORE6_LANE(v, v0, v1, 4); + STORE6_LANE(v, v0, v1, 5); + STORE6_LANE(v, v0, v1, 6); + STORE6_LANE(v, v0, v1, 7); +} +#undef STORE6_LANE + +static WEBP_INLINE void Store4x8x2_NEON(const uint8x16_t p1, + const uint8x16_t p0, + const uint8x16_t q0, + const uint8x16_t q1, + uint8_t* const u, uint8_t* const v, + int stride) { + uint8x8x4_t u0, v0; + INIT_VECTOR4(u0, + vget_low_u8(p1), vget_low_u8(p0), + vget_low_u8(q0), vget_low_u8(q1)); + INIT_VECTOR4(v0, + vget_high_u8(p1), vget_high_u8(p0), + vget_high_u8(q0), vget_high_u8(q1)); + vst4_lane_u8(u - 2 + 0 * stride, u0, 0); + vst4_lane_u8(u - 2 + 1 * stride, u0, 1); + vst4_lane_u8(u - 2 + 2 * stride, u0, 2); + vst4_lane_u8(u - 2 + 3 * stride, u0, 3); + vst4_lane_u8(u - 2 + 4 * stride, u0, 4); + vst4_lane_u8(u - 2 + 5 * stride, u0, 5); + vst4_lane_u8(u - 2 + 6 * stride, u0, 6); + vst4_lane_u8(u - 2 + 7 * stride, u0, 7); + vst4_lane_u8(v - 2 + 0 * stride, v0, 0); + vst4_lane_u8(v - 2 + 1 * stride, v0, 1); + vst4_lane_u8(v - 2 + 2 * stride, v0, 2); + vst4_lane_u8(v - 2 + 3 * stride, v0, 3); + vst4_lane_u8(v - 2 + 4 * stride, v0, 4); + vst4_lane_u8(v - 2 + 5 * stride, v0, 5); + vst4_lane_u8(v - 2 + 6 * stride, v0, 6); + vst4_lane_u8(v - 2 + 7 * stride, v0, 7); +} + +#endif // !WORK_AROUND_GCC + +// Zero extend 'v' to an int16x8_t. +static WEBP_INLINE int16x8_t ConvertU8ToS16_NEON(uint8x8_t v) { + return vreinterpretq_s16_u16(vmovl_u8(v)); +} + +// Performs unsigned 8b saturation on 'dst01' and 'dst23' storing the result +// to the corresponding rows of 'dst'. +static WEBP_INLINE void SaturateAndStore4x4_NEON(uint8_t* const dst, + const int16x8_t dst01, + const int16x8_t dst23) { + // Unsigned saturate to 8b. + const uint8x8_t dst01_u8 = vqmovun_s16(dst01); + const uint8x8_t dst23_u8 = vqmovun_s16(dst23); + + // Store the results. + vst1_lane_u32((uint32_t*)(dst + 0 * BPS), vreinterpret_u32_u8(dst01_u8), 0); + vst1_lane_u32((uint32_t*)(dst + 1 * BPS), vreinterpret_u32_u8(dst01_u8), 1); + vst1_lane_u32((uint32_t*)(dst + 2 * BPS), vreinterpret_u32_u8(dst23_u8), 0); + vst1_lane_u32((uint32_t*)(dst + 3 * BPS), vreinterpret_u32_u8(dst23_u8), 1); +} + +static WEBP_INLINE void Add4x4_NEON(const int16x8_t row01, + const int16x8_t row23, + uint8_t* const dst) { + uint32x2_t dst01 = vdup_n_u32(0); + uint32x2_t dst23 = vdup_n_u32(0); + + // Load the source pixels. + dst01 = vld1_lane_u32((uint32_t*)(dst + 0 * BPS), dst01, 0); + dst23 = vld1_lane_u32((uint32_t*)(dst + 2 * BPS), dst23, 0); + dst01 = vld1_lane_u32((uint32_t*)(dst + 1 * BPS), dst01, 1); + dst23 = vld1_lane_u32((uint32_t*)(dst + 3 * BPS), dst23, 1); + + { + // Convert to 16b. + const int16x8_t dst01_s16 = ConvertU8ToS16_NEON(vreinterpret_u8_u32(dst01)); + const int16x8_t dst23_s16 = ConvertU8ToS16_NEON(vreinterpret_u8_u32(dst23)); + + // Descale with rounding. + const int16x8_t out01 = vrsraq_n_s16(dst01_s16, row01, 3); + const int16x8_t out23 = vrsraq_n_s16(dst23_s16, row23, 3); + // Add the inverse transform. + SaturateAndStore4x4_NEON(dst, out01, out23); + } +} + +//----------------------------------------------------------------------------- +// Simple In-loop filtering (Paragraph 15.2) + +static uint8x16_t NeedsFilter_NEON(const uint8x16_t p1, const uint8x16_t p0, + const uint8x16_t q0, const uint8x16_t q1, + int thresh) { + const uint8x16_t thresh_v = vdupq_n_u8((uint8_t)thresh); + const uint8x16_t a_p0_q0 = vabdq_u8(p0, q0); // abs(p0-q0) + const uint8x16_t a_p1_q1 = vabdq_u8(p1, q1); // abs(p1-q1) + const uint8x16_t a_p0_q0_2 = vqaddq_u8(a_p0_q0, a_p0_q0); // 2 * abs(p0-q0) + const uint8x16_t a_p1_q1_2 = vshrq_n_u8(a_p1_q1, 1); // abs(p1-q1) / 2 + const uint8x16_t sum = vqaddq_u8(a_p0_q0_2, a_p1_q1_2); + const uint8x16_t mask = vcgeq_u8(thresh_v, sum); + return mask; +} + +static int8x16_t FlipSign_NEON(const uint8x16_t v) { + const uint8x16_t sign_bit = vdupq_n_u8(0x80); + return vreinterpretq_s8_u8(veorq_u8(v, sign_bit)); +} + +static uint8x16_t FlipSignBack_NEON(const int8x16_t v) { + const int8x16_t sign_bit = vdupq_n_s8(0x80); + return vreinterpretq_u8_s8(veorq_s8(v, sign_bit)); +} + +static int8x16_t GetBaseDelta_NEON(const int8x16_t p1, const int8x16_t p0, + const int8x16_t q0, const int8x16_t q1) { + const int8x16_t q0_p0 = vqsubq_s8(q0, p0); // (q0-p0) + const int8x16_t p1_q1 = vqsubq_s8(p1, q1); // (p1-q1) + const int8x16_t s1 = vqaddq_s8(p1_q1, q0_p0); // (p1-q1) + 1 * (q0 - p0) + const int8x16_t s2 = vqaddq_s8(q0_p0, s1); // (p1-q1) + 2 * (q0 - p0) + const int8x16_t s3 = vqaddq_s8(q0_p0, s2); // (p1-q1) + 3 * (q0 - p0) + return s3; +} + +static int8x16_t GetBaseDelta0_NEON(const int8x16_t p0, const int8x16_t q0) { + const int8x16_t q0_p0 = vqsubq_s8(q0, p0); // (q0-p0) + const int8x16_t s1 = vqaddq_s8(q0_p0, q0_p0); // 2 * (q0 - p0) + const int8x16_t s2 = vqaddq_s8(q0_p0, s1); // 3 * (q0 - p0) + return s2; +} + +//------------------------------------------------------------------------------ + +static void ApplyFilter2NoFlip_NEON(const int8x16_t p0s, const int8x16_t q0s, + const int8x16_t delta, + int8x16_t* const op0, + int8x16_t* const oq0) { + const int8x16_t kCst3 = vdupq_n_s8(0x03); + const int8x16_t kCst4 = vdupq_n_s8(0x04); + const int8x16_t delta_p3 = vqaddq_s8(delta, kCst3); + const int8x16_t delta_p4 = vqaddq_s8(delta, kCst4); + const int8x16_t delta3 = vshrq_n_s8(delta_p3, 3); + const int8x16_t delta4 = vshrq_n_s8(delta_p4, 3); + *op0 = vqaddq_s8(p0s, delta3); + *oq0 = vqsubq_s8(q0s, delta4); +} + +#if defined(WEBP_USE_INTRINSICS) + +static void ApplyFilter2_NEON(const int8x16_t p0s, const int8x16_t q0s, + const int8x16_t delta, + uint8x16_t* const op0, uint8x16_t* const oq0) { + const int8x16_t kCst3 = vdupq_n_s8(0x03); + const int8x16_t kCst4 = vdupq_n_s8(0x04); + const int8x16_t delta_p3 = vqaddq_s8(delta, kCst3); + const int8x16_t delta_p4 = vqaddq_s8(delta, kCst4); + const int8x16_t delta3 = vshrq_n_s8(delta_p3, 3); + const int8x16_t delta4 = vshrq_n_s8(delta_p4, 3); + const int8x16_t sp0 = vqaddq_s8(p0s, delta3); + const int8x16_t sq0 = vqsubq_s8(q0s, delta4); + *op0 = FlipSignBack_NEON(sp0); + *oq0 = FlipSignBack_NEON(sq0); +} + +static void DoFilter2_NEON(const uint8x16_t p1, const uint8x16_t p0, + const uint8x16_t q0, const uint8x16_t q1, + const uint8x16_t mask, + uint8x16_t* const op0, uint8x16_t* const oq0) { + const int8x16_t p1s = FlipSign_NEON(p1); + const int8x16_t p0s = FlipSign_NEON(p0); + const int8x16_t q0s = FlipSign_NEON(q0); + const int8x16_t q1s = FlipSign_NEON(q1); + const int8x16_t delta0 = GetBaseDelta_NEON(p1s, p0s, q0s, q1s); + const int8x16_t delta1 = vandq_s8(delta0, vreinterpretq_s8_u8(mask)); + ApplyFilter2_NEON(p0s, q0s, delta1, op0, oq0); +} + +static void SimpleVFilter16_NEON(uint8_t* p, int stride, int thresh) { + uint8x16_t p1, p0, q0, q1, op0, oq0; + Load16x4_NEON(p, stride, &p1, &p0, &q0, &q1); + { + const uint8x16_t mask = NeedsFilter_NEON(p1, p0, q0, q1, thresh); + DoFilter2_NEON(p1, p0, q0, q1, mask, &op0, &oq0); + } + Store16x2_NEON(op0, oq0, p, stride); +} + +static void SimpleHFilter16_NEON(uint8_t* p, int stride, int thresh) { + uint8x16_t p1, p0, q0, q1, oq0, op0; + Load4x16_NEON(p, stride, &p1, &p0, &q0, &q1); + { + const uint8x16_t mask = NeedsFilter_NEON(p1, p0, q0, q1, thresh); + DoFilter2_NEON(p1, p0, q0, q1, mask, &op0, &oq0); + } + Store2x16_NEON(op0, oq0, p, stride); +} + +#else + +// Load/Store vertical edge +#define LOAD8x4(c1, c2, c3, c4, b1, b2, stride) \ + "vld4.8 {" #c1 "[0]," #c2 "[0]," #c3 "[0]," #c4 "[0]}," #b1 "," #stride "\n" \ + "vld4.8 {" #c1 "[1]," #c2 "[1]," #c3 "[1]," #c4 "[1]}," #b2 "," #stride "\n" \ + "vld4.8 {" #c1 "[2]," #c2 "[2]," #c3 "[2]," #c4 "[2]}," #b1 "," #stride "\n" \ + "vld4.8 {" #c1 "[3]," #c2 "[3]," #c3 "[3]," #c4 "[3]}," #b2 "," #stride "\n" \ + "vld4.8 {" #c1 "[4]," #c2 "[4]," #c3 "[4]," #c4 "[4]}," #b1 "," #stride "\n" \ + "vld4.8 {" #c1 "[5]," #c2 "[5]," #c3 "[5]," #c4 "[5]}," #b2 "," #stride "\n" \ + "vld4.8 {" #c1 "[6]," #c2 "[6]," #c3 "[6]," #c4 "[6]}," #b1 "," #stride "\n" \ + "vld4.8 {" #c1 "[7]," #c2 "[7]," #c3 "[7]," #c4 "[7]}," #b2 "," #stride "\n" + +#define STORE8x2(c1, c2, p, stride) \ + "vst2.8 {" #c1 "[0], " #c2 "[0]}," #p "," #stride " \n" \ + "vst2.8 {" #c1 "[1], " #c2 "[1]}," #p "," #stride " \n" \ + "vst2.8 {" #c1 "[2], " #c2 "[2]}," #p "," #stride " \n" \ + "vst2.8 {" #c1 "[3], " #c2 "[3]}," #p "," #stride " \n" \ + "vst2.8 {" #c1 "[4], " #c2 "[4]}," #p "," #stride " \n" \ + "vst2.8 {" #c1 "[5], " #c2 "[5]}," #p "," #stride " \n" \ + "vst2.8 {" #c1 "[6], " #c2 "[6]}," #p "," #stride " \n" \ + "vst2.8 {" #c1 "[7], " #c2 "[7]}," #p "," #stride " \n" + +#define QRegs "q0", "q1", "q2", "q3", \ + "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + +#define FLIP_SIGN_BIT2(a, b, s) \ + "veor " #a "," #a "," #s " \n" \ + "veor " #b "," #b "," #s " \n" \ + +#define FLIP_SIGN_BIT4(a, b, c, d, s) \ + FLIP_SIGN_BIT2(a, b, s) \ + FLIP_SIGN_BIT2(c, d, s) \ + +#define NEEDS_FILTER(p1, p0, q0, q1, thresh, mask) \ + "vabd.u8 q15," #p0 "," #q0 " \n" /* abs(p0 - q0) */ \ + "vabd.u8 q14," #p1 "," #q1 " \n" /* abs(p1 - q1) */ \ + "vqadd.u8 q15, q15, q15 \n" /* abs(p0 - q0) * 2 */ \ + "vshr.u8 q14, q14, #1 \n" /* abs(p1 - q1) / 2 */ \ + "vqadd.u8 q15, q15, q14 \n" /* abs(p0 - q0) * 2 + abs(p1 - q1) / 2 */ \ + "vdup.8 q14, " #thresh " \n" \ + "vcge.u8 " #mask ", q14, q15 \n" /* mask <= thresh */ + +#define GET_BASE_DELTA(p1, p0, q0, q1, o) \ + "vqsub.s8 q15," #q0 "," #p0 " \n" /* (q0 - p0) */ \ + "vqsub.s8 " #o "," #p1 "," #q1 " \n" /* (p1 - q1) */ \ + "vqadd.s8 " #o "," #o ", q15 \n" /* (p1 - q1) + 1 * (p0 - q0) */ \ + "vqadd.s8 " #o "," #o ", q15 \n" /* (p1 - q1) + 2 * (p0 - q0) */ \ + "vqadd.s8 " #o "," #o ", q15 \n" /* (p1 - q1) + 3 * (p0 - q0) */ + +#define DO_SIMPLE_FILTER(p0, q0, fl) \ + "vmov.i8 q15, #0x03 \n" \ + "vqadd.s8 q15, q15, " #fl " \n" /* filter1 = filter + 3 */ \ + "vshr.s8 q15, q15, #3 \n" /* filter1 >> 3 */ \ + "vqadd.s8 " #p0 "," #p0 ", q15 \n" /* p0 += filter1 */ \ + \ + "vmov.i8 q15, #0x04 \n" \ + "vqadd.s8 q15, q15, " #fl " \n" /* filter1 = filter + 4 */ \ + "vshr.s8 q15, q15, #3 \n" /* filter2 >> 3 */ \ + "vqsub.s8 " #q0 "," #q0 ", q15 \n" /* q0 -= filter2 */ + +// Applies filter on 2 pixels (p0 and q0) +#define DO_FILTER2(p1, p0, q0, q1, thresh) \ + NEEDS_FILTER(p1, p0, q0, q1, thresh, q9) /* filter mask in q9 */ \ + "vmov.i8 q10, #0x80 \n" /* sign bit */ \ + FLIP_SIGN_BIT4(p1, p0, q0, q1, q10) /* convert to signed value */ \ + GET_BASE_DELTA(p1, p0, q0, q1, q11) /* get filter level */ \ + "vand q9, q9, q11 \n" /* apply filter mask */ \ + DO_SIMPLE_FILTER(p0, q0, q9) /* apply filter */ \ + FLIP_SIGN_BIT2(p0, q0, q10) + +static void SimpleVFilter16_NEON(uint8_t* p, int stride, int thresh) { + __asm__ volatile ( + "sub %[p], %[p], %[stride], lsl #1 \n" // p -= 2 * stride + + "vld1.u8 {q1}, [%[p]], %[stride] \n" // p1 + "vld1.u8 {q2}, [%[p]], %[stride] \n" // p0 + "vld1.u8 {q3}, [%[p]], %[stride] \n" // q0 + "vld1.u8 {q12}, [%[p]] \n" // q1 + + DO_FILTER2(q1, q2, q3, q12, %[thresh]) + + "sub %[p], %[p], %[stride], lsl #1 \n" // p -= 2 * stride + + "vst1.u8 {q2}, [%[p]], %[stride] \n" // store op0 + "vst1.u8 {q3}, [%[p]] \n" // store oq0 + : [p] "+r"(p) + : [stride] "r"(stride), [thresh] "r"(thresh) + : "memory", QRegs + ); +} + +static void SimpleHFilter16_NEON(uint8_t* p, int stride, int thresh) { + __asm__ volatile ( + "sub r4, %[p], #2 \n" // base1 = p - 2 + "lsl r6, %[stride], #1 \n" // r6 = 2 * stride + "add r5, r4, %[stride] \n" // base2 = base1 + stride + + LOAD8x4(d2, d3, d4, d5, [r4], [r5], r6) + LOAD8x4(d24, d25, d26, d27, [r4], [r5], r6) + "vswp d3, d24 \n" // p1:q1 p0:q3 + "vswp d5, d26 \n" // q0:q2 q1:q4 + "vswp q2, q12 \n" // p1:q1 p0:q2 q0:q3 q1:q4 + + DO_FILTER2(q1, q2, q12, q13, %[thresh]) + + "sub %[p], %[p], #1 \n" // p - 1 + + "vswp d5, d24 \n" + STORE8x2(d4, d5, [%[p]], %[stride]) + STORE8x2(d24, d25, [%[p]], %[stride]) + + : [p] "+r"(p) + : [stride] "r"(stride), [thresh] "r"(thresh) + : "memory", "r4", "r5", "r6", QRegs + ); +} + +#undef LOAD8x4 +#undef STORE8x2 + +#endif // WEBP_USE_INTRINSICS + +static void SimpleVFilter16i_NEON(uint8_t* p, int stride, int thresh) { + uint32_t k; + for (k = 3; k != 0; --k) { + p += 4 * stride; + SimpleVFilter16_NEON(p, stride, thresh); + } +} + +static void SimpleHFilter16i_NEON(uint8_t* p, int stride, int thresh) { + uint32_t k; + for (k = 3; k != 0; --k) { + p += 4; + SimpleHFilter16_NEON(p, stride, thresh); + } +} + +//------------------------------------------------------------------------------ +// Complex In-loop filtering (Paragraph 15.3) + +static uint8x16_t NeedsHev_NEON(const uint8x16_t p1, const uint8x16_t p0, + const uint8x16_t q0, const uint8x16_t q1, + int hev_thresh) { + const uint8x16_t hev_thresh_v = vdupq_n_u8((uint8_t)hev_thresh); + const uint8x16_t a_p1_p0 = vabdq_u8(p1, p0); // abs(p1 - p0) + const uint8x16_t a_q1_q0 = vabdq_u8(q1, q0); // abs(q1 - q0) + const uint8x16_t a_max = vmaxq_u8(a_p1_p0, a_q1_q0); + const uint8x16_t mask = vcgtq_u8(a_max, hev_thresh_v); + return mask; +} + +static uint8x16_t NeedsFilter2_NEON(const uint8x16_t p3, const uint8x16_t p2, + const uint8x16_t p1, const uint8x16_t p0, + const uint8x16_t q0, const uint8x16_t q1, + const uint8x16_t q2, const uint8x16_t q3, + int ithresh, int thresh) { + const uint8x16_t ithresh_v = vdupq_n_u8((uint8_t)ithresh); + const uint8x16_t a_p3_p2 = vabdq_u8(p3, p2); // abs(p3 - p2) + const uint8x16_t a_p2_p1 = vabdq_u8(p2, p1); // abs(p2 - p1) + const uint8x16_t a_p1_p0 = vabdq_u8(p1, p0); // abs(p1 - p0) + const uint8x16_t a_q3_q2 = vabdq_u8(q3, q2); // abs(q3 - q2) + const uint8x16_t a_q2_q1 = vabdq_u8(q2, q1); // abs(q2 - q1) + const uint8x16_t a_q1_q0 = vabdq_u8(q1, q0); // abs(q1 - q0) + const uint8x16_t max1 = vmaxq_u8(a_p3_p2, a_p2_p1); + const uint8x16_t max2 = vmaxq_u8(a_p1_p0, a_q3_q2); + const uint8x16_t max3 = vmaxq_u8(a_q2_q1, a_q1_q0); + const uint8x16_t max12 = vmaxq_u8(max1, max2); + const uint8x16_t max123 = vmaxq_u8(max12, max3); + const uint8x16_t mask2 = vcgeq_u8(ithresh_v, max123); + const uint8x16_t mask1 = NeedsFilter_NEON(p1, p0, q0, q1, thresh); + const uint8x16_t mask = vandq_u8(mask1, mask2); + return mask; +} + +// 4-points filter + +static void ApplyFilter4_NEON( + const int8x16_t p1, const int8x16_t p0, + const int8x16_t q0, const int8x16_t q1, + const int8x16_t delta0, + uint8x16_t* const op1, uint8x16_t* const op0, + uint8x16_t* const oq0, uint8x16_t* const oq1) { + const int8x16_t kCst3 = vdupq_n_s8(0x03); + const int8x16_t kCst4 = vdupq_n_s8(0x04); + const int8x16_t delta1 = vqaddq_s8(delta0, kCst4); + const int8x16_t delta2 = vqaddq_s8(delta0, kCst3); + const int8x16_t a1 = vshrq_n_s8(delta1, 3); + const int8x16_t a2 = vshrq_n_s8(delta2, 3); + const int8x16_t a3 = vrshrq_n_s8(a1, 1); // a3 = (a1 + 1) >> 1 + *op0 = FlipSignBack_NEON(vqaddq_s8(p0, a2)); // clip(p0 + a2) + *oq0 = FlipSignBack_NEON(vqsubq_s8(q0, a1)); // clip(q0 - a1) + *op1 = FlipSignBack_NEON(vqaddq_s8(p1, a3)); // clip(p1 + a3) + *oq1 = FlipSignBack_NEON(vqsubq_s8(q1, a3)); // clip(q1 - a3) +} + +static void DoFilter4_NEON( + const uint8x16_t p1, const uint8x16_t p0, + const uint8x16_t q0, const uint8x16_t q1, + const uint8x16_t mask, const uint8x16_t hev_mask, + uint8x16_t* const op1, uint8x16_t* const op0, + uint8x16_t* const oq0, uint8x16_t* const oq1) { + // This is a fused version of DoFilter2() calling ApplyFilter2 directly + const int8x16_t p1s = FlipSign_NEON(p1); + int8x16_t p0s = FlipSign_NEON(p0); + int8x16_t q0s = FlipSign_NEON(q0); + const int8x16_t q1s = FlipSign_NEON(q1); + const uint8x16_t simple_lf_mask = vandq_u8(mask, hev_mask); + + // do_filter2 part (simple loopfilter on pixels with hev) + { + const int8x16_t delta = GetBaseDelta_NEON(p1s, p0s, q0s, q1s); + const int8x16_t simple_lf_delta = + vandq_s8(delta, vreinterpretq_s8_u8(simple_lf_mask)); + ApplyFilter2NoFlip_NEON(p0s, q0s, simple_lf_delta, &p0s, &q0s); + } + + // do_filter4 part (complex loopfilter on pixels without hev) + { + const int8x16_t delta0 = GetBaseDelta0_NEON(p0s, q0s); + // we use: (mask & hev_mask) ^ mask = mask & !hev_mask + const uint8x16_t complex_lf_mask = veorq_u8(simple_lf_mask, mask); + const int8x16_t complex_lf_delta = + vandq_s8(delta0, vreinterpretq_s8_u8(complex_lf_mask)); + ApplyFilter4_NEON(p1s, p0s, q0s, q1s, complex_lf_delta, op1, op0, oq0, oq1); + } +} + +// 6-points filter + +static void ApplyFilter6_NEON( + const int8x16_t p2, const int8x16_t p1, const int8x16_t p0, + const int8x16_t q0, const int8x16_t q1, const int8x16_t q2, + const int8x16_t delta, + uint8x16_t* const op2, uint8x16_t* const op1, uint8x16_t* const op0, + uint8x16_t* const oq0, uint8x16_t* const oq1, uint8x16_t* const oq2) { + // We have to compute: X = (9*a+63) >> 7, Y = (18*a+63)>>7, Z = (27*a+63) >> 7 + // Turns out, there's a common sub-expression S=9 * a - 1 that can be used + // with the special vqrshrn_n_s16 rounding-shift-and-narrow instruction: + // X = (S + 64) >> 7, Y = (S + 32) >> 6, Z = (18 * a + S + 64) >> 7 + const int8x8_t delta_lo = vget_low_s8(delta); + const int8x8_t delta_hi = vget_high_s8(delta); + const int8x8_t kCst9 = vdup_n_s8(9); + const int16x8_t kCstm1 = vdupq_n_s16(-1); + const int8x8_t kCst18 = vdup_n_s8(18); + const int16x8_t S_lo = vmlal_s8(kCstm1, kCst9, delta_lo); // S = 9 * a - 1 + const int16x8_t S_hi = vmlal_s8(kCstm1, kCst9, delta_hi); + const int16x8_t Z_lo = vmlal_s8(S_lo, kCst18, delta_lo); // S + 18 * a + const int16x8_t Z_hi = vmlal_s8(S_hi, kCst18, delta_hi); + const int8x8_t a3_lo = vqrshrn_n_s16(S_lo, 7); // (9 * a + 63) >> 7 + const int8x8_t a3_hi = vqrshrn_n_s16(S_hi, 7); + const int8x8_t a2_lo = vqrshrn_n_s16(S_lo, 6); // (9 * a + 31) >> 6 + const int8x8_t a2_hi = vqrshrn_n_s16(S_hi, 6); + const int8x8_t a1_lo = vqrshrn_n_s16(Z_lo, 7); // (27 * a + 63) >> 7 + const int8x8_t a1_hi = vqrshrn_n_s16(Z_hi, 7); + const int8x16_t a1 = vcombine_s8(a1_lo, a1_hi); + const int8x16_t a2 = vcombine_s8(a2_lo, a2_hi); + const int8x16_t a3 = vcombine_s8(a3_lo, a3_hi); + + *op0 = FlipSignBack_NEON(vqaddq_s8(p0, a1)); // clip(p0 + a1) + *oq0 = FlipSignBack_NEON(vqsubq_s8(q0, a1)); // clip(q0 - q1) + *oq1 = FlipSignBack_NEON(vqsubq_s8(q1, a2)); // clip(q1 - a2) + *op1 = FlipSignBack_NEON(vqaddq_s8(p1, a2)); // clip(p1 + a2) + *oq2 = FlipSignBack_NEON(vqsubq_s8(q2, a3)); // clip(q2 - a3) + *op2 = FlipSignBack_NEON(vqaddq_s8(p2, a3)); // clip(p2 + a3) +} + +static void DoFilter6_NEON( + const uint8x16_t p2, const uint8x16_t p1, const uint8x16_t p0, + const uint8x16_t q0, const uint8x16_t q1, const uint8x16_t q2, + const uint8x16_t mask, const uint8x16_t hev_mask, + uint8x16_t* const op2, uint8x16_t* const op1, uint8x16_t* const op0, + uint8x16_t* const oq0, uint8x16_t* const oq1, uint8x16_t* const oq2) { + // This is a fused version of DoFilter2() calling ApplyFilter2 directly + const int8x16_t p2s = FlipSign_NEON(p2); + const int8x16_t p1s = FlipSign_NEON(p1); + int8x16_t p0s = FlipSign_NEON(p0); + int8x16_t q0s = FlipSign_NEON(q0); + const int8x16_t q1s = FlipSign_NEON(q1); + const int8x16_t q2s = FlipSign_NEON(q2); + const uint8x16_t simple_lf_mask = vandq_u8(mask, hev_mask); + const int8x16_t delta0 = GetBaseDelta_NEON(p1s, p0s, q0s, q1s); + + // do_filter2 part (simple loopfilter on pixels with hev) + { + const int8x16_t simple_lf_delta = + vandq_s8(delta0, vreinterpretq_s8_u8(simple_lf_mask)); + ApplyFilter2NoFlip_NEON(p0s, q0s, simple_lf_delta, &p0s, &q0s); + } + + // do_filter6 part (complex loopfilter on pixels without hev) + { + // we use: (mask & hev_mask) ^ mask = mask & !hev_mask + const uint8x16_t complex_lf_mask = veorq_u8(simple_lf_mask, mask); + const int8x16_t complex_lf_delta = + vandq_s8(delta0, vreinterpretq_s8_u8(complex_lf_mask)); + ApplyFilter6_NEON(p2s, p1s, p0s, q0s, q1s, q2s, complex_lf_delta, + op2, op1, op0, oq0, oq1, oq2); + } +} + +// on macroblock edges + +static void VFilter16_NEON(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3; + Load16x8_NEON(p, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); + { + const uint8x16_t mask = NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3, + ithresh, thresh); + const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh); + uint8x16_t op2, op1, op0, oq0, oq1, oq2; + DoFilter6_NEON(p2, p1, p0, q0, q1, q2, mask, hev_mask, + &op2, &op1, &op0, &oq0, &oq1, &oq2); + Store16x2_NEON(op2, op1, p - 2 * stride, stride); + Store16x2_NEON(op0, oq0, p + 0 * stride, stride); + Store16x2_NEON(oq1, oq2, p + 2 * stride, stride); + } +} + +static void HFilter16_NEON(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3; + Load8x16_NEON(p, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); + { + const uint8x16_t mask = NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3, + ithresh, thresh); + const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh); + uint8x16_t op2, op1, op0, oq0, oq1, oq2; + DoFilter6_NEON(p2, p1, p0, q0, q1, q2, mask, hev_mask, + &op2, &op1, &op0, &oq0, &oq1, &oq2); + Store2x16_NEON(op2, op1, p - 2, stride); + Store2x16_NEON(op0, oq0, p + 0, stride); + Store2x16_NEON(oq1, oq2, p + 2, stride); + } +} + +// on three inner edges +static void VFilter16i_NEON(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + uint32_t k; + uint8x16_t p3, p2, p1, p0; + Load16x4_NEON(p + 2 * stride, stride, &p3, &p2, &p1, &p0); + for (k = 3; k != 0; --k) { + uint8x16_t q0, q1, q2, q3; + p += 4 * stride; + Load16x4_NEON(p + 2 * stride, stride, &q0, &q1, &q2, &q3); + { + const uint8x16_t mask = + NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3, ithresh, thresh); + const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh); + // p3 and p2 are not just temporary variables here: they will be + // re-used for next span. And q2/q3 will become p1/p0 accordingly. + DoFilter4_NEON(p1, p0, q0, q1, mask, hev_mask, &p1, &p0, &p3, &p2); + Store16x4_NEON(p1, p0, p3, p2, p, stride); + p1 = q2; + p0 = q3; + } + } +} + +#if !defined(WORK_AROUND_GCC) +static void HFilter16i_NEON(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + uint32_t k; + uint8x16_t p3, p2, p1, p0; + Load4x16_NEON(p + 2, stride, &p3, &p2, &p1, &p0); + for (k = 3; k != 0; --k) { + uint8x16_t q0, q1, q2, q3; + p += 4; + Load4x16_NEON(p + 2, stride, &q0, &q1, &q2, &q3); + { + const uint8x16_t mask = + NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3, ithresh, thresh); + const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh); + DoFilter4_NEON(p1, p0, q0, q1, mask, hev_mask, &p1, &p0, &p3, &p2); + Store4x16_NEON(p1, p0, p3, p2, p, stride); + p1 = q2; + p0 = q3; + } + } +} +#endif // !WORK_AROUND_GCC + +// 8-pixels wide variant, for chroma filtering +static void VFilter8_NEON(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3; + Load8x8x2_NEON(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); + { + const uint8x16_t mask = NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3, + ithresh, thresh); + const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh); + uint8x16_t op2, op1, op0, oq0, oq1, oq2; + DoFilter6_NEON(p2, p1, p0, q0, q1, q2, mask, hev_mask, + &op2, &op1, &op0, &oq0, &oq1, &oq2); + Store8x2x2_NEON(op2, op1, u - 2 * stride, v - 2 * stride, stride); + Store8x2x2_NEON(op0, oq0, u + 0 * stride, v + 0 * stride, stride); + Store8x2x2_NEON(oq1, oq2, u + 2 * stride, v + 2 * stride, stride); + } +} +static void VFilter8i_NEON(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3; + u += 4 * stride; + v += 4 * stride; + Load8x8x2_NEON(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); + { + const uint8x16_t mask = NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3, + ithresh, thresh); + const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh); + uint8x16_t op1, op0, oq0, oq1; + DoFilter4_NEON(p1, p0, q0, q1, mask, hev_mask, &op1, &op0, &oq0, &oq1); + Store8x4x2_NEON(op1, op0, oq0, oq1, u, v, stride); + } +} + +#if !defined(WORK_AROUND_GCC) +static void HFilter8_NEON(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3; + Load8x8x2T_NEON(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); + { + const uint8x16_t mask = NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3, + ithresh, thresh); + const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh); + uint8x16_t op2, op1, op0, oq0, oq1, oq2; + DoFilter6_NEON(p2, p1, p0, q0, q1, q2, mask, hev_mask, + &op2, &op1, &op0, &oq0, &oq1, &oq2); + Store6x8x2_NEON(op2, op1, op0, oq0, oq1, oq2, u, v, stride); + } +} + +static void HFilter8i_NEON(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3; + u += 4; + v += 4; + Load8x8x2T_NEON(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); + { + const uint8x16_t mask = NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3, + ithresh, thresh); + const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh); + uint8x16_t op1, op0, oq0, oq1; + DoFilter4_NEON(p1, p0, q0, q1, mask, hev_mask, &op1, &op0, &oq0, &oq1); + Store4x8x2_NEON(op1, op0, oq0, oq1, u, v, stride); + } +} +#endif // !WORK_AROUND_GCC + +//----------------------------------------------------------------------------- +// Inverse transforms (Paragraph 14.4) + +// Technically these are unsigned but vqdmulh is only available in signed. +// vqdmulh returns high half (effectively >> 16) but also doubles the value, +// changing the >> 16 to >> 15 and requiring an additional >> 1. +// We use this to our advantage with kC2. The canonical value is 35468. +// However, the high bit is set so treating it as signed will give incorrect +// results. We avoid this by down shifting by 1 here to clear the highest bit. +// Combined with the doubling effect of vqdmulh we get >> 16. +// This can not be applied to kC1 because the lowest bit is set. Down shifting +// the constant would reduce precision. + +// libwebp uses a trick to avoid some extra addition that libvpx does. +// Instead of: +// temp2 = ip[12] + ((ip[12] * cospi8sqrt2minus1) >> 16); +// libwebp adds 1 << 16 to cospi8sqrt2minus1 (kC1). However, this causes the +// same issue with kC1 and vqdmulh that we work around by down shifting kC2 + +static const int16_t kC1 = 20091; +static const int16_t kC2 = 17734; // half of kC2, actually. See comment above. + +#if defined(WEBP_USE_INTRINSICS) +static WEBP_INLINE void Transpose8x2_NEON(const int16x8_t in0, + const int16x8_t in1, + int16x8x2_t* const out) { + // a0 a1 a2 a3 | b0 b1 b2 b3 => a0 b0 c0 d0 | a1 b1 c1 d1 + // c0 c1 c2 c3 | d0 d1 d2 d3 a2 b2 c2 d2 | a3 b3 c3 d3 + const int16x8x2_t tmp0 = vzipq_s16(in0, in1); // a0 c0 a1 c1 a2 c2 ... + // b0 d0 b1 d1 b2 d2 ... + *out = vzipq_s16(tmp0.val[0], tmp0.val[1]); +} + +static WEBP_INLINE void TransformPass_NEON(int16x8x2_t* const rows) { + // {rows} = in0 | in4 + // in8 | in12 + // B1 = in4 | in12 + const int16x8_t B1 = + vcombine_s16(vget_high_s16(rows->val[0]), vget_high_s16(rows->val[1])); + // C0 = kC1 * in4 | kC1 * in12 + // C1 = kC2 * in4 | kC2 * in12 + const int16x8_t C0 = vsraq_n_s16(B1, vqdmulhq_n_s16(B1, kC1), 1); + const int16x8_t C1 = vqdmulhq_n_s16(B1, kC2); + const int16x4_t a = vqadd_s16(vget_low_s16(rows->val[0]), + vget_low_s16(rows->val[1])); // in0 + in8 + const int16x4_t b = vqsub_s16(vget_low_s16(rows->val[0]), + vget_low_s16(rows->val[1])); // in0 - in8 + // c = kC2 * in4 - kC1 * in12 + // d = kC1 * in4 + kC2 * in12 + const int16x4_t c = vqsub_s16(vget_low_s16(C1), vget_high_s16(C0)); + const int16x4_t d = vqadd_s16(vget_low_s16(C0), vget_high_s16(C1)); + const int16x8_t D0 = vcombine_s16(a, b); // D0 = a | b + const int16x8_t D1 = vcombine_s16(d, c); // D1 = d | c + const int16x8_t E0 = vqaddq_s16(D0, D1); // a+d | b+c + const int16x8_t E_tmp = vqsubq_s16(D0, D1); // a-d | b-c + const int16x8_t E1 = vcombine_s16(vget_high_s16(E_tmp), vget_low_s16(E_tmp)); + Transpose8x2_NEON(E0, E1, rows); +} + +static void TransformOne_NEON(const int16_t* in, uint8_t* dst) { + int16x8x2_t rows; + INIT_VECTOR2(rows, vld1q_s16(in + 0), vld1q_s16(in + 8)); + TransformPass_NEON(&rows); + TransformPass_NEON(&rows); + Add4x4_NEON(rows.val[0], rows.val[1], dst); +} + +#else + +static void TransformOne_NEON(const int16_t* in, uint8_t* dst) { + const int kBPS = BPS; + // kC1, kC2. Padded because vld1.16 loads 8 bytes + const int16_t constants[4] = { kC1, kC2, 0, 0 }; + /* Adapted from libvpx: vp8/common/arm/neon/shortidct4x4llm_neon.asm */ + __asm__ volatile ( + "vld1.16 {q1, q2}, [%[in]] \n" + "vld1.16 {d0}, [%[constants]] \n" + + /* d2: in[0] + * d3: in[8] + * d4: in[4] + * d5: in[12] + */ + "vswp d3, d4 \n" + + /* q8 = {in[4], in[12]} * kC1 * 2 >> 16 + * q9 = {in[4], in[12]} * kC2 >> 16 + */ + "vqdmulh.s16 q8, q2, d0[0] \n" + "vqdmulh.s16 q9, q2, d0[1] \n" + + /* d22 = a = in[0] + in[8] + * d23 = b = in[0] - in[8] + */ + "vqadd.s16 d22, d2, d3 \n" + "vqsub.s16 d23, d2, d3 \n" + + /* The multiplication should be x * kC1 >> 16 + * However, with vqdmulh we get x * kC1 * 2 >> 16 + * (multiply, double, return high half) + * We avoided this in kC2 by pre-shifting the constant. + * q8 = in[4]/[12] * kC1 >> 16 + */ + "vshr.s16 q8, q8, #1 \n" + + /* Add {in[4], in[12]} back after the multiplication. This is handled by + * adding 1 << 16 to kC1 in the libwebp C code. + */ + "vqadd.s16 q8, q2, q8 \n" + + /* d20 = c = in[4]*kC2 - in[12]*kC1 + * d21 = d = in[4]*kC1 + in[12]*kC2 + */ + "vqsub.s16 d20, d18, d17 \n" + "vqadd.s16 d21, d19, d16 \n" + + /* d2 = tmp[0] = a + d + * d3 = tmp[1] = b + c + * d4 = tmp[2] = b - c + * d5 = tmp[3] = a - d + */ + "vqadd.s16 d2, d22, d21 \n" + "vqadd.s16 d3, d23, d20 \n" + "vqsub.s16 d4, d23, d20 \n" + "vqsub.s16 d5, d22, d21 \n" + + "vzip.16 q1, q2 \n" + "vzip.16 q1, q2 \n" + + "vswp d3, d4 \n" + + /* q8 = {tmp[4], tmp[12]} * kC1 * 2 >> 16 + * q9 = {tmp[4], tmp[12]} * kC2 >> 16 + */ + "vqdmulh.s16 q8, q2, d0[0] \n" + "vqdmulh.s16 q9, q2, d0[1] \n" + + /* d22 = a = tmp[0] + tmp[8] + * d23 = b = tmp[0] - tmp[8] + */ + "vqadd.s16 d22, d2, d3 \n" + "vqsub.s16 d23, d2, d3 \n" + + /* See long winded explanations prior */ + "vshr.s16 q8, q8, #1 \n" + "vqadd.s16 q8, q2, q8 \n" + + /* d20 = c = in[4]*kC2 - in[12]*kC1 + * d21 = d = in[4]*kC1 + in[12]*kC2 + */ + "vqsub.s16 d20, d18, d17 \n" + "vqadd.s16 d21, d19, d16 \n" + + /* d2 = tmp[0] = a + d + * d3 = tmp[1] = b + c + * d4 = tmp[2] = b - c + * d5 = tmp[3] = a - d + */ + "vqadd.s16 d2, d22, d21 \n" + "vqadd.s16 d3, d23, d20 \n" + "vqsub.s16 d4, d23, d20 \n" + "vqsub.s16 d5, d22, d21 \n" + + "vld1.32 d6[0], [%[dst]], %[kBPS] \n" + "vld1.32 d6[1], [%[dst]], %[kBPS] \n" + "vld1.32 d7[0], [%[dst]], %[kBPS] \n" + "vld1.32 d7[1], [%[dst]], %[kBPS] \n" + + "sub %[dst], %[dst], %[kBPS], lsl #2 \n" + + /* (val) + 4 >> 3 */ + "vrshr.s16 d2, d2, #3 \n" + "vrshr.s16 d3, d3, #3 \n" + "vrshr.s16 d4, d4, #3 \n" + "vrshr.s16 d5, d5, #3 \n" + + "vzip.16 q1, q2 \n" + "vzip.16 q1, q2 \n" + + /* Must accumulate before saturating */ + "vmovl.u8 q8, d6 \n" + "vmovl.u8 q9, d7 \n" + + "vqadd.s16 q1, q1, q8 \n" + "vqadd.s16 q2, q2, q9 \n" + + "vqmovun.s16 d0, q1 \n" + "vqmovun.s16 d1, q2 \n" + + "vst1.32 d0[0], [%[dst]], %[kBPS] \n" + "vst1.32 d0[1], [%[dst]], %[kBPS] \n" + "vst1.32 d1[0], [%[dst]], %[kBPS] \n" + "vst1.32 d1[1], [%[dst]] \n" + + : [in] "+r"(in), [dst] "+r"(dst) /* modified registers */ + : [kBPS] "r"(kBPS), [constants] "r"(constants) /* constants */ + : "memory", "q0", "q1", "q2", "q8", "q9", "q10", "q11" /* clobbered */ + ); +} + +#endif // WEBP_USE_INTRINSICS + +static void TransformTwo_NEON(const int16_t* in, uint8_t* dst, int do_two) { + TransformOne_NEON(in, dst); + if (do_two) { + TransformOne_NEON(in + 16, dst + 4); + } +} + +static void TransformDC_NEON(const int16_t* in, uint8_t* dst) { + const int16x8_t DC = vdupq_n_s16(in[0]); + Add4x4_NEON(DC, DC, dst); +} + +//------------------------------------------------------------------------------ + +#define STORE_WHT(dst, col, rows) do { \ + *dst = vgetq_lane_s32(rows.val[0], col); (dst) += 16; \ + *dst = vgetq_lane_s32(rows.val[1], col); (dst) += 16; \ + *dst = vgetq_lane_s32(rows.val[2], col); (dst) += 16; \ + *dst = vgetq_lane_s32(rows.val[3], col); (dst) += 16; \ +} while (0) + +static void TransformWHT_NEON(const int16_t* in, int16_t* out) { + int32x4x4_t tmp; + + { + // Load the source. + const int16x4_t in00_03 = vld1_s16(in + 0); + const int16x4_t in04_07 = vld1_s16(in + 4); + const int16x4_t in08_11 = vld1_s16(in + 8); + const int16x4_t in12_15 = vld1_s16(in + 12); + const int32x4_t a0 = vaddl_s16(in00_03, in12_15); // in[0..3] + in[12..15] + const int32x4_t a1 = vaddl_s16(in04_07, in08_11); // in[4..7] + in[8..11] + const int32x4_t a2 = vsubl_s16(in04_07, in08_11); // in[4..7] - in[8..11] + const int32x4_t a3 = vsubl_s16(in00_03, in12_15); // in[0..3] - in[12..15] + tmp.val[0] = vaddq_s32(a0, a1); + tmp.val[1] = vaddq_s32(a3, a2); + tmp.val[2] = vsubq_s32(a0, a1); + tmp.val[3] = vsubq_s32(a3, a2); + // Arrange the temporary results column-wise. + tmp = Transpose4x4_NEON(tmp); + } + + { + const int32x4_t kCst3 = vdupq_n_s32(3); + const int32x4_t dc = vaddq_s32(tmp.val[0], kCst3); // add rounder + const int32x4_t a0 = vaddq_s32(dc, tmp.val[3]); + const int32x4_t a1 = vaddq_s32(tmp.val[1], tmp.val[2]); + const int32x4_t a2 = vsubq_s32(tmp.val[1], tmp.val[2]); + const int32x4_t a3 = vsubq_s32(dc, tmp.val[3]); + + tmp.val[0] = vaddq_s32(a0, a1); + tmp.val[1] = vaddq_s32(a3, a2); + tmp.val[2] = vsubq_s32(a0, a1); + tmp.val[3] = vsubq_s32(a3, a2); + + // right shift the results by 3. + tmp.val[0] = vshrq_n_s32(tmp.val[0], 3); + tmp.val[1] = vshrq_n_s32(tmp.val[1], 3); + tmp.val[2] = vshrq_n_s32(tmp.val[2], 3); + tmp.val[3] = vshrq_n_s32(tmp.val[3], 3); + + STORE_WHT(out, 0, tmp); + STORE_WHT(out, 1, tmp); + STORE_WHT(out, 2, tmp); + STORE_WHT(out, 3, tmp); + } +} + +#undef STORE_WHT + +//------------------------------------------------------------------------------ + +#define MUL(a, b) (((a) * (b)) >> 16) +static void TransformAC3_NEON(const int16_t* in, uint8_t* dst) { + static const int kC1_full = 20091 + (1 << 16); + static const int kC2_full = 35468; + const int16x4_t A = vld1_dup_s16(in); + const int16x4_t c4 = vdup_n_s16(MUL(in[4], kC2_full)); + const int16x4_t d4 = vdup_n_s16(MUL(in[4], kC1_full)); + const int c1 = MUL(in[1], kC2_full); + const int d1 = MUL(in[1], kC1_full); + const uint64_t cd = (uint64_t)( d1 & 0xffff) << 0 | + (uint64_t)( c1 & 0xffff) << 16 | + (uint64_t)(-c1 & 0xffff) << 32 | + (uint64_t)(-d1 & 0xffff) << 48; + const int16x4_t CD = vcreate_s16(cd); + const int16x4_t B = vqadd_s16(A, CD); + const int16x8_t m0_m1 = vcombine_s16(vqadd_s16(B, d4), vqadd_s16(B, c4)); + const int16x8_t m2_m3 = vcombine_s16(vqsub_s16(B, c4), vqsub_s16(B, d4)); + Add4x4_NEON(m0_m1, m2_m3, dst); +} +#undef MUL + +//------------------------------------------------------------------------------ +// 4x4 + +static void DC4_NEON(uint8_t* dst) { // DC + const uint8x8_t A = vld1_u8(dst - BPS); // top row + const uint16x4_t p0 = vpaddl_u8(A); // cascading summation of the top + const uint16x4_t p1 = vpadd_u16(p0, p0); + const uint8x8_t L0 = vld1_u8(dst + 0 * BPS - 1); + const uint8x8_t L1 = vld1_u8(dst + 1 * BPS - 1); + const uint8x8_t L2 = vld1_u8(dst + 2 * BPS - 1); + const uint8x8_t L3 = vld1_u8(dst + 3 * BPS - 1); + const uint16x8_t s0 = vaddl_u8(L0, L1); + const uint16x8_t s1 = vaddl_u8(L2, L3); + const uint16x8_t s01 = vaddq_u16(s0, s1); + const uint16x8_t sum = vaddq_u16(s01, vcombine_u16(p1, p1)); + const uint8x8_t dc0 = vrshrn_n_u16(sum, 3); // (sum + 4) >> 3 + const uint8x8_t dc = vdup_lane_u8(dc0, 0); + int i; + for (i = 0; i < 4; ++i) { + vst1_lane_u32((uint32_t*)(dst + i * BPS), vreinterpret_u32_u8(dc), 0); + } +} + +// TrueMotion (4x4 + 8x8) +static WEBP_INLINE void TrueMotion_NEON(uint8_t* dst, int size) { + const uint8x8_t TL = vld1_dup_u8(dst - BPS - 1); // top-left pixel 'A[-1]' + const uint8x8_t T = vld1_u8(dst - BPS); // top row 'A[0..3]' + const int16x8_t d = vreinterpretq_s16_u16(vsubl_u8(T, TL)); // A[c] - A[-1] + int y; + for (y = 0; y < size; y += 4) { + // left edge + const int16x8_t L0 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 0 * BPS - 1)); + const int16x8_t L1 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 1 * BPS - 1)); + const int16x8_t L2 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 2 * BPS - 1)); + const int16x8_t L3 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 3 * BPS - 1)); + const int16x8_t r0 = vaddq_s16(L0, d); // L[r] + A[c] - A[-1] + const int16x8_t r1 = vaddq_s16(L1, d); + const int16x8_t r2 = vaddq_s16(L2, d); + const int16x8_t r3 = vaddq_s16(L3, d); + // Saturate and store the result. + const uint32x2_t r0_u32 = vreinterpret_u32_u8(vqmovun_s16(r0)); + const uint32x2_t r1_u32 = vreinterpret_u32_u8(vqmovun_s16(r1)); + const uint32x2_t r2_u32 = vreinterpret_u32_u8(vqmovun_s16(r2)); + const uint32x2_t r3_u32 = vreinterpret_u32_u8(vqmovun_s16(r3)); + if (size == 4) { + vst1_lane_u32((uint32_t*)(dst + 0 * BPS), r0_u32, 0); + vst1_lane_u32((uint32_t*)(dst + 1 * BPS), r1_u32, 0); + vst1_lane_u32((uint32_t*)(dst + 2 * BPS), r2_u32, 0); + vst1_lane_u32((uint32_t*)(dst + 3 * BPS), r3_u32, 0); + } else { + vst1_u32((uint32_t*)(dst + 0 * BPS), r0_u32); + vst1_u32((uint32_t*)(dst + 1 * BPS), r1_u32); + vst1_u32((uint32_t*)(dst + 2 * BPS), r2_u32); + vst1_u32((uint32_t*)(dst + 3 * BPS), r3_u32); + } + dst += 4 * BPS; + } +} + +static void TM4_NEON(uint8_t* dst) { TrueMotion_NEON(dst, 4); } + +static void VE4_NEON(uint8_t* dst) { // vertical + // NB: avoid vld1_u64 here as an alignment hint may be added -> SIGBUS. + const uint64x1_t A0 = vreinterpret_u64_u8(vld1_u8(dst - BPS - 1)); // top row + const uint64x1_t A1 = vshr_n_u64(A0, 8); + const uint64x1_t A2 = vshr_n_u64(A0, 16); + const uint8x8_t ABCDEFGH = vreinterpret_u8_u64(A0); + const uint8x8_t BCDEFGH0 = vreinterpret_u8_u64(A1); + const uint8x8_t CDEFGH00 = vreinterpret_u8_u64(A2); + const uint8x8_t b = vhadd_u8(ABCDEFGH, CDEFGH00); + const uint8x8_t avg = vrhadd_u8(b, BCDEFGH0); + int i; + for (i = 0; i < 4; ++i) { + vst1_lane_u32((uint32_t*)(dst + i * BPS), vreinterpret_u32_u8(avg), 0); + } +} + +static void RD4_NEON(uint8_t* dst) { // Down-right + const uint8x8_t XABCD_u8 = vld1_u8(dst - BPS - 1); + const uint64x1_t XABCD = vreinterpret_u64_u8(XABCD_u8); + const uint64x1_t ____XABC = vshl_n_u64(XABCD, 32); + const uint32_t I = dst[-1 + 0 * BPS]; + const uint32_t J = dst[-1 + 1 * BPS]; + const uint32_t K = dst[-1 + 2 * BPS]; + const uint32_t L = dst[-1 + 3 * BPS]; + const uint64x1_t LKJI____ = + vcreate_u64((uint64_t)L | (K << 8) | (J << 16) | (I << 24)); + const uint64x1_t LKJIXABC = vorr_u64(LKJI____, ____XABC); + const uint8x8_t KJIXABC_ = vreinterpret_u8_u64(vshr_n_u64(LKJIXABC, 8)); + const uint8x8_t JIXABC__ = vreinterpret_u8_u64(vshr_n_u64(LKJIXABC, 16)); + const uint8_t D = vget_lane_u8(XABCD_u8, 4); + const uint8x8_t JIXABCD_ = vset_lane_u8(D, JIXABC__, 6); + const uint8x8_t LKJIXABC_u8 = vreinterpret_u8_u64(LKJIXABC); + const uint8x8_t avg1 = vhadd_u8(JIXABCD_, LKJIXABC_u8); + const uint8x8_t avg2 = vrhadd_u8(avg1, KJIXABC_); + const uint64x1_t avg2_u64 = vreinterpret_u64_u8(avg2); + const uint32x2_t r3 = vreinterpret_u32_u8(avg2); + const uint32x2_t r2 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 8)); + const uint32x2_t r1 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 16)); + const uint32x2_t r0 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 24)); + vst1_lane_u32((uint32_t*)(dst + 0 * BPS), r0, 0); + vst1_lane_u32((uint32_t*)(dst + 1 * BPS), r1, 0); + vst1_lane_u32((uint32_t*)(dst + 2 * BPS), r2, 0); + vst1_lane_u32((uint32_t*)(dst + 3 * BPS), r3, 0); +} + +static void LD4_NEON(uint8_t* dst) { // Down-left + // Note using the same shift trick as VE4() is slower here. + const uint8x8_t ABCDEFGH = vld1_u8(dst - BPS + 0); + const uint8x8_t BCDEFGH0 = vld1_u8(dst - BPS + 1); + const uint8x8_t CDEFGH00 = vld1_u8(dst - BPS + 2); + const uint8x8_t CDEFGHH0 = vset_lane_u8(dst[-BPS + 7], CDEFGH00, 6); + const uint8x8_t avg1 = vhadd_u8(ABCDEFGH, CDEFGHH0); + const uint8x8_t avg2 = vrhadd_u8(avg1, BCDEFGH0); + const uint64x1_t avg2_u64 = vreinterpret_u64_u8(avg2); + const uint32x2_t r0 = vreinterpret_u32_u8(avg2); + const uint32x2_t r1 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 8)); + const uint32x2_t r2 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 16)); + const uint32x2_t r3 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 24)); + vst1_lane_u32((uint32_t*)(dst + 0 * BPS), r0, 0); + vst1_lane_u32((uint32_t*)(dst + 1 * BPS), r1, 0); + vst1_lane_u32((uint32_t*)(dst + 2 * BPS), r2, 0); + vst1_lane_u32((uint32_t*)(dst + 3 * BPS), r3, 0); +} + +//------------------------------------------------------------------------------ +// Chroma + +static void VE8uv_NEON(uint8_t* dst) { // vertical + const uint8x8_t top = vld1_u8(dst - BPS); + int j; + for (j = 0; j < 8; ++j) { + vst1_u8(dst + j * BPS, top); + } +} + +static void HE8uv_NEON(uint8_t* dst) { // horizontal + int j; + for (j = 0; j < 8; ++j) { + const uint8x8_t left = vld1_dup_u8(dst - 1); + vst1_u8(dst, left); + dst += BPS; + } +} + +static WEBP_INLINE void DC8_NEON(uint8_t* dst, int do_top, int do_left) { + uint16x8_t sum_top; + uint16x8_t sum_left; + uint8x8_t dc0; + + if (do_top) { + const uint8x8_t A = vld1_u8(dst - BPS); // top row +#if WEBP_AARCH64 + const uint16_t p2 = vaddlv_u8(A); + sum_top = vdupq_n_u16(p2); +#else + const uint16x4_t p0 = vpaddl_u8(A); // cascading summation of the top + const uint16x4_t p1 = vpadd_u16(p0, p0); + const uint16x4_t p2 = vpadd_u16(p1, p1); + sum_top = vcombine_u16(p2, p2); +#endif + } + + if (do_left) { + const uint8x8_t L0 = vld1_u8(dst + 0 * BPS - 1); + const uint8x8_t L1 = vld1_u8(dst + 1 * BPS - 1); + const uint8x8_t L2 = vld1_u8(dst + 2 * BPS - 1); + const uint8x8_t L3 = vld1_u8(dst + 3 * BPS - 1); + const uint8x8_t L4 = vld1_u8(dst + 4 * BPS - 1); + const uint8x8_t L5 = vld1_u8(dst + 5 * BPS - 1); + const uint8x8_t L6 = vld1_u8(dst + 6 * BPS - 1); + const uint8x8_t L7 = vld1_u8(dst + 7 * BPS - 1); + const uint16x8_t s0 = vaddl_u8(L0, L1); + const uint16x8_t s1 = vaddl_u8(L2, L3); + const uint16x8_t s2 = vaddl_u8(L4, L5); + const uint16x8_t s3 = vaddl_u8(L6, L7); + const uint16x8_t s01 = vaddq_u16(s0, s1); + const uint16x8_t s23 = vaddq_u16(s2, s3); + sum_left = vaddq_u16(s01, s23); + } + + if (do_top && do_left) { + const uint16x8_t sum = vaddq_u16(sum_left, sum_top); + dc0 = vrshrn_n_u16(sum, 4); + } else if (do_top) { + dc0 = vrshrn_n_u16(sum_top, 3); + } else if (do_left) { + dc0 = vrshrn_n_u16(sum_left, 3); + } else { + dc0 = vdup_n_u8(0x80); + } + + { + const uint8x8_t dc = vdup_lane_u8(dc0, 0); + int i; + for (i = 0; i < 8; ++i) { + vst1_u32((uint32_t*)(dst + i * BPS), vreinterpret_u32_u8(dc)); + } + } +} + +static void DC8uv_NEON(uint8_t* dst) { DC8_NEON(dst, 1, 1); } +static void DC8uvNoTop_NEON(uint8_t* dst) { DC8_NEON(dst, 0, 1); } +static void DC8uvNoLeft_NEON(uint8_t* dst) { DC8_NEON(dst, 1, 0); } +static void DC8uvNoTopLeft_NEON(uint8_t* dst) { DC8_NEON(dst, 0, 0); } + +static void TM8uv_NEON(uint8_t* dst) { TrueMotion_NEON(dst, 8); } + +//------------------------------------------------------------------------------ +// 16x16 + +static void VE16_NEON(uint8_t* dst) { // vertical + const uint8x16_t top = vld1q_u8(dst - BPS); + int j; + for (j = 0; j < 16; ++j) { + vst1q_u8(dst + j * BPS, top); + } +} + +static void HE16_NEON(uint8_t* dst) { // horizontal + int j; + for (j = 0; j < 16; ++j) { + const uint8x16_t left = vld1q_dup_u8(dst - 1); + vst1q_u8(dst, left); + dst += BPS; + } +} + +static WEBP_INLINE void DC16_NEON(uint8_t* dst, int do_top, int do_left) { + uint16x8_t sum_top; + uint16x8_t sum_left; + uint8x8_t dc0; + + if (do_top) { + const uint8x16_t A = vld1q_u8(dst - BPS); // top row +#if WEBP_AARCH64 + const uint16_t p3 = vaddlvq_u8(A); + sum_top = vdupq_n_u16(p3); +#else + const uint16x8_t p0 = vpaddlq_u8(A); // cascading summation of the top + const uint16x4_t p1 = vadd_u16(vget_low_u16(p0), vget_high_u16(p0)); + const uint16x4_t p2 = vpadd_u16(p1, p1); + const uint16x4_t p3 = vpadd_u16(p2, p2); + sum_top = vcombine_u16(p3, p3); +#endif + } + + if (do_left) { + int i; + sum_left = vdupq_n_u16(0); + for (i = 0; i < 16; i += 8) { + const uint8x8_t L0 = vld1_u8(dst + (i + 0) * BPS - 1); + const uint8x8_t L1 = vld1_u8(dst + (i + 1) * BPS - 1); + const uint8x8_t L2 = vld1_u8(dst + (i + 2) * BPS - 1); + const uint8x8_t L3 = vld1_u8(dst + (i + 3) * BPS - 1); + const uint8x8_t L4 = vld1_u8(dst + (i + 4) * BPS - 1); + const uint8x8_t L5 = vld1_u8(dst + (i + 5) * BPS - 1); + const uint8x8_t L6 = vld1_u8(dst + (i + 6) * BPS - 1); + const uint8x8_t L7 = vld1_u8(dst + (i + 7) * BPS - 1); + const uint16x8_t s0 = vaddl_u8(L0, L1); + const uint16x8_t s1 = vaddl_u8(L2, L3); + const uint16x8_t s2 = vaddl_u8(L4, L5); + const uint16x8_t s3 = vaddl_u8(L6, L7); + const uint16x8_t s01 = vaddq_u16(s0, s1); + const uint16x8_t s23 = vaddq_u16(s2, s3); + const uint16x8_t sum = vaddq_u16(s01, s23); + sum_left = vaddq_u16(sum_left, sum); + } + } + + if (do_top && do_left) { + const uint16x8_t sum = vaddq_u16(sum_left, sum_top); + dc0 = vrshrn_n_u16(sum, 5); + } else if (do_top) { + dc0 = vrshrn_n_u16(sum_top, 4); + } else if (do_left) { + dc0 = vrshrn_n_u16(sum_left, 4); + } else { + dc0 = vdup_n_u8(0x80); + } + + { + const uint8x16_t dc = vdupq_lane_u8(dc0, 0); + int i; + for (i = 0; i < 16; ++i) { + vst1q_u8(dst + i * BPS, dc); + } + } +} + +static void DC16TopLeft_NEON(uint8_t* dst) { DC16_NEON(dst, 1, 1); } +static void DC16NoTop_NEON(uint8_t* dst) { DC16_NEON(dst, 0, 1); } +static void DC16NoLeft_NEON(uint8_t* dst) { DC16_NEON(dst, 1, 0); } +static void DC16NoTopLeft_NEON(uint8_t* dst) { DC16_NEON(dst, 0, 0); } + +static void TM16_NEON(uint8_t* dst) { + const uint8x8_t TL = vld1_dup_u8(dst - BPS - 1); // top-left pixel 'A[-1]' + const uint8x16_t T = vld1q_u8(dst - BPS); // top row 'A[0..15]' + // A[c] - A[-1] + const int16x8_t d_lo = vreinterpretq_s16_u16(vsubl_u8(vget_low_u8(T), TL)); + const int16x8_t d_hi = vreinterpretq_s16_u16(vsubl_u8(vget_high_u8(T), TL)); + int y; + for (y = 0; y < 16; y += 4) { + // left edge + const int16x8_t L0 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 0 * BPS - 1)); + const int16x8_t L1 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 1 * BPS - 1)); + const int16x8_t L2 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 2 * BPS - 1)); + const int16x8_t L3 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 3 * BPS - 1)); + const int16x8_t r0_lo = vaddq_s16(L0, d_lo); // L[r] + A[c] - A[-1] + const int16x8_t r1_lo = vaddq_s16(L1, d_lo); + const int16x8_t r2_lo = vaddq_s16(L2, d_lo); + const int16x8_t r3_lo = vaddq_s16(L3, d_lo); + const int16x8_t r0_hi = vaddq_s16(L0, d_hi); + const int16x8_t r1_hi = vaddq_s16(L1, d_hi); + const int16x8_t r2_hi = vaddq_s16(L2, d_hi); + const int16x8_t r3_hi = vaddq_s16(L3, d_hi); + // Saturate and store the result. + const uint8x16_t row0 = vcombine_u8(vqmovun_s16(r0_lo), vqmovun_s16(r0_hi)); + const uint8x16_t row1 = vcombine_u8(vqmovun_s16(r1_lo), vqmovun_s16(r1_hi)); + const uint8x16_t row2 = vcombine_u8(vqmovun_s16(r2_lo), vqmovun_s16(r2_hi)); + const uint8x16_t row3 = vcombine_u8(vqmovun_s16(r3_lo), vqmovun_s16(r3_hi)); + vst1q_u8(dst + 0 * BPS, row0); + vst1q_u8(dst + 1 * BPS, row1); + vst1q_u8(dst + 2 * BPS, row2); + vst1q_u8(dst + 3 * BPS, row3); + dst += 4 * BPS; + } +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8DspInitNEON(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitNEON(void) { + VP8Transform = TransformTwo_NEON; + VP8TransformAC3 = TransformAC3_NEON; + VP8TransformDC = TransformDC_NEON; + VP8TransformWHT = TransformWHT_NEON; + + VP8VFilter16 = VFilter16_NEON; + VP8VFilter16i = VFilter16i_NEON; + VP8HFilter16 = HFilter16_NEON; +#if !defined(WORK_AROUND_GCC) + VP8HFilter16i = HFilter16i_NEON; +#endif + VP8VFilter8 = VFilter8_NEON; + VP8VFilter8i = VFilter8i_NEON; +#if !defined(WORK_AROUND_GCC) + VP8HFilter8 = HFilter8_NEON; + VP8HFilter8i = HFilter8i_NEON; +#endif + VP8SimpleVFilter16 = SimpleVFilter16_NEON; + VP8SimpleHFilter16 = SimpleHFilter16_NEON; + VP8SimpleVFilter16i = SimpleVFilter16i_NEON; + VP8SimpleHFilter16i = SimpleHFilter16i_NEON; + + VP8PredLuma4[0] = DC4_NEON; + VP8PredLuma4[1] = TM4_NEON; + VP8PredLuma4[2] = VE4_NEON; + VP8PredLuma4[4] = RD4_NEON; + VP8PredLuma4[6] = LD4_NEON; + + VP8PredLuma16[0] = DC16TopLeft_NEON; + VP8PredLuma16[1] = TM16_NEON; + VP8PredLuma16[2] = VE16_NEON; + VP8PredLuma16[3] = HE16_NEON; + VP8PredLuma16[4] = DC16NoTop_NEON; + VP8PredLuma16[5] = DC16NoLeft_NEON; + VP8PredLuma16[6] = DC16NoTopLeft_NEON; + + VP8PredChroma8[0] = DC8uv_NEON; + VP8PredChroma8[1] = TM8uv_NEON; + VP8PredChroma8[2] = VE8uv_NEON; + VP8PredChroma8[3] = HE8uv_NEON; + VP8PredChroma8[4] = DC8uvNoTop_NEON; + VP8PredChroma8[5] = DC8uvNoLeft_NEON; + VP8PredChroma8[6] = DC8uvNoTopLeft_NEON; +} + +#else // !WEBP_USE_NEON + +WEBP_DSP_INIT_STUB(VP8DspInitNEON) + +#endif // WEBP_USE_NEON diff --git a/third-party/webp/libwebp/src/dsp/dec_sse2.c b/third-party/webp/libwebp/src/dsp/dec_sse2.c new file mode 100644 index 0000000000..01e6bcb636 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/dec_sse2.c @@ -0,0 +1,1228 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE2 version of some decoding functions (idct, loop filtering). +// +// Author: somnath@google.com (Somnath Banerjee) +// cduvivier@google.com (Christian Duvivier) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE2) + +// The 3-coeff sparse transform in SSE2 is not really faster than the plain-C +// one it seems => disable it by default. Uncomment the following to enable: +#if !defined(USE_TRANSFORM_AC3) +#define USE_TRANSFORM_AC3 0 // ALTERNATE_CODE +#endif + +#include +#include "src/dsp/common_sse2.h" +#include "src/dec/vp8i_dec.h" +#include "src/utils/utils.h" + +//------------------------------------------------------------------------------ +// Transforms (Paragraph 14.4) + +static void Transform_SSE2(const int16_t* in, uint8_t* dst, int do_two) { + // This implementation makes use of 16-bit fixed point versions of two + // multiply constants: + // K1 = sqrt(2) * cos (pi/8) ~= 85627 / 2^16 + // K2 = sqrt(2) * sin (pi/8) ~= 35468 / 2^16 + // + // To be able to use signed 16-bit integers, we use the following trick to + // have constants within range: + // - Associated constants are obtained by subtracting the 16-bit fixed point + // version of one: + // k = K - (1 << 16) => K = k + (1 << 16) + // K1 = 85267 => k1 = 20091 + // K2 = 35468 => k2 = -30068 + // - The multiplication of a variable by a constant become the sum of the + // variable and the multiplication of that variable by the associated + // constant: + // (x * K) >> 16 = (x * (k + (1 << 16))) >> 16 = ((x * k ) >> 16) + x + const __m128i k1 = _mm_set1_epi16(20091); + const __m128i k2 = _mm_set1_epi16(-30068); + __m128i T0, T1, T2, T3; + + // Load and concatenate the transform coefficients (we'll do two transforms + // in parallel). In the case of only one transform, the second half of the + // vectors will just contain random value we'll never use nor store. + __m128i in0, in1, in2, in3; + { + in0 = _mm_loadl_epi64((const __m128i*)&in[0]); + in1 = _mm_loadl_epi64((const __m128i*)&in[4]); + in2 = _mm_loadl_epi64((const __m128i*)&in[8]); + in3 = _mm_loadl_epi64((const __m128i*)&in[12]); + // a00 a10 a20 a30 x x x x + // a01 a11 a21 a31 x x x x + // a02 a12 a22 a32 x x x x + // a03 a13 a23 a33 x x x x + if (do_two) { + const __m128i inB0 = _mm_loadl_epi64((const __m128i*)&in[16]); + const __m128i inB1 = _mm_loadl_epi64((const __m128i*)&in[20]); + const __m128i inB2 = _mm_loadl_epi64((const __m128i*)&in[24]); + const __m128i inB3 = _mm_loadl_epi64((const __m128i*)&in[28]); + in0 = _mm_unpacklo_epi64(in0, inB0); + in1 = _mm_unpacklo_epi64(in1, inB1); + in2 = _mm_unpacklo_epi64(in2, inB2); + in3 = _mm_unpacklo_epi64(in3, inB3); + // a00 a10 a20 a30 b00 b10 b20 b30 + // a01 a11 a21 a31 b01 b11 b21 b31 + // a02 a12 a22 a32 b02 b12 b22 b32 + // a03 a13 a23 a33 b03 b13 b23 b33 + } + } + + // Vertical pass and subsequent transpose. + { + // First pass, c and d calculations are longer because of the "trick" + // multiplications. + const __m128i a = _mm_add_epi16(in0, in2); + const __m128i b = _mm_sub_epi16(in0, in2); + // c = MUL(in1, K2) - MUL(in3, K1) = MUL(in1, k2) - MUL(in3, k1) + in1 - in3 + const __m128i c1 = _mm_mulhi_epi16(in1, k2); + const __m128i c2 = _mm_mulhi_epi16(in3, k1); + const __m128i c3 = _mm_sub_epi16(in1, in3); + const __m128i c4 = _mm_sub_epi16(c1, c2); + const __m128i c = _mm_add_epi16(c3, c4); + // d = MUL(in1, K1) + MUL(in3, K2) = MUL(in1, k1) + MUL(in3, k2) + in1 + in3 + const __m128i d1 = _mm_mulhi_epi16(in1, k1); + const __m128i d2 = _mm_mulhi_epi16(in3, k2); + const __m128i d3 = _mm_add_epi16(in1, in3); + const __m128i d4 = _mm_add_epi16(d1, d2); + const __m128i d = _mm_add_epi16(d3, d4); + + // Second pass. + const __m128i tmp0 = _mm_add_epi16(a, d); + const __m128i tmp1 = _mm_add_epi16(b, c); + const __m128i tmp2 = _mm_sub_epi16(b, c); + const __m128i tmp3 = _mm_sub_epi16(a, d); + + // Transpose the two 4x4. + VP8Transpose_2_4x4_16b(&tmp0, &tmp1, &tmp2, &tmp3, &T0, &T1, &T2, &T3); + } + + // Horizontal pass and subsequent transpose. + { + // First pass, c and d calculations are longer because of the "trick" + // multiplications. + const __m128i four = _mm_set1_epi16(4); + const __m128i dc = _mm_add_epi16(T0, four); + const __m128i a = _mm_add_epi16(dc, T2); + const __m128i b = _mm_sub_epi16(dc, T2); + // c = MUL(T1, K2) - MUL(T3, K1) = MUL(T1, k2) - MUL(T3, k1) + T1 - T3 + const __m128i c1 = _mm_mulhi_epi16(T1, k2); + const __m128i c2 = _mm_mulhi_epi16(T3, k1); + const __m128i c3 = _mm_sub_epi16(T1, T3); + const __m128i c4 = _mm_sub_epi16(c1, c2); + const __m128i c = _mm_add_epi16(c3, c4); + // d = MUL(T1, K1) + MUL(T3, K2) = MUL(T1, k1) + MUL(T3, k2) + T1 + T3 + const __m128i d1 = _mm_mulhi_epi16(T1, k1); + const __m128i d2 = _mm_mulhi_epi16(T3, k2); + const __m128i d3 = _mm_add_epi16(T1, T3); + const __m128i d4 = _mm_add_epi16(d1, d2); + const __m128i d = _mm_add_epi16(d3, d4); + + // Second pass. + const __m128i tmp0 = _mm_add_epi16(a, d); + const __m128i tmp1 = _mm_add_epi16(b, c); + const __m128i tmp2 = _mm_sub_epi16(b, c); + const __m128i tmp3 = _mm_sub_epi16(a, d); + const __m128i shifted0 = _mm_srai_epi16(tmp0, 3); + const __m128i shifted1 = _mm_srai_epi16(tmp1, 3); + const __m128i shifted2 = _mm_srai_epi16(tmp2, 3); + const __m128i shifted3 = _mm_srai_epi16(tmp3, 3); + + // Transpose the two 4x4. + VP8Transpose_2_4x4_16b(&shifted0, &shifted1, &shifted2, &shifted3, &T0, &T1, + &T2, &T3); + } + + // Add inverse transform to 'dst' and store. + { + const __m128i zero = _mm_setzero_si128(); + // Load the reference(s). + __m128i dst0, dst1, dst2, dst3; + if (do_two) { + // Load eight bytes/pixels per line. + dst0 = _mm_loadl_epi64((__m128i*)(dst + 0 * BPS)); + dst1 = _mm_loadl_epi64((__m128i*)(dst + 1 * BPS)); + dst2 = _mm_loadl_epi64((__m128i*)(dst + 2 * BPS)); + dst3 = _mm_loadl_epi64((__m128i*)(dst + 3 * BPS)); + } else { + // Load four bytes/pixels per line. + dst0 = _mm_cvtsi32_si128(WebPMemToInt32(dst + 0 * BPS)); + dst1 = _mm_cvtsi32_si128(WebPMemToInt32(dst + 1 * BPS)); + dst2 = _mm_cvtsi32_si128(WebPMemToInt32(dst + 2 * BPS)); + dst3 = _mm_cvtsi32_si128(WebPMemToInt32(dst + 3 * BPS)); + } + // Convert to 16b. + dst0 = _mm_unpacklo_epi8(dst0, zero); + dst1 = _mm_unpacklo_epi8(dst1, zero); + dst2 = _mm_unpacklo_epi8(dst2, zero); + dst3 = _mm_unpacklo_epi8(dst3, zero); + // Add the inverse transform(s). + dst0 = _mm_add_epi16(dst0, T0); + dst1 = _mm_add_epi16(dst1, T1); + dst2 = _mm_add_epi16(dst2, T2); + dst3 = _mm_add_epi16(dst3, T3); + // Unsigned saturate to 8b. + dst0 = _mm_packus_epi16(dst0, dst0); + dst1 = _mm_packus_epi16(dst1, dst1); + dst2 = _mm_packus_epi16(dst2, dst2); + dst3 = _mm_packus_epi16(dst3, dst3); + // Store the results. + if (do_two) { + // Store eight bytes/pixels per line. + _mm_storel_epi64((__m128i*)(dst + 0 * BPS), dst0); + _mm_storel_epi64((__m128i*)(dst + 1 * BPS), dst1); + _mm_storel_epi64((__m128i*)(dst + 2 * BPS), dst2); + _mm_storel_epi64((__m128i*)(dst + 3 * BPS), dst3); + } else { + // Store four bytes/pixels per line. + WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(dst0)); + WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(dst1)); + WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(dst2)); + WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(dst3)); + } + } +} + +#if (USE_TRANSFORM_AC3 == 1) +#define MUL(a, b) (((a) * (b)) >> 16) +static void TransformAC3(const int16_t* in, uint8_t* dst) { + static const int kC1 = 20091 + (1 << 16); + static const int kC2 = 35468; + const __m128i A = _mm_set1_epi16(in[0] + 4); + const __m128i c4 = _mm_set1_epi16(MUL(in[4], kC2)); + const __m128i d4 = _mm_set1_epi16(MUL(in[4], kC1)); + const int c1 = MUL(in[1], kC2); + const int d1 = MUL(in[1], kC1); + const __m128i CD = _mm_set_epi16(0, 0, 0, 0, -d1, -c1, c1, d1); + const __m128i B = _mm_adds_epi16(A, CD); + const __m128i m0 = _mm_adds_epi16(B, d4); + const __m128i m1 = _mm_adds_epi16(B, c4); + const __m128i m2 = _mm_subs_epi16(B, c4); + const __m128i m3 = _mm_subs_epi16(B, d4); + const __m128i zero = _mm_setzero_si128(); + // Load the source pixels. + __m128i dst0 = _mm_cvtsi32_si128(WebPMemToInt32(dst + 0 * BPS)); + __m128i dst1 = _mm_cvtsi32_si128(WebPMemToInt32(dst + 1 * BPS)); + __m128i dst2 = _mm_cvtsi32_si128(WebPMemToInt32(dst + 2 * BPS)); + __m128i dst3 = _mm_cvtsi32_si128(WebPMemToInt32(dst + 3 * BPS)); + // Convert to 16b. + dst0 = _mm_unpacklo_epi8(dst0, zero); + dst1 = _mm_unpacklo_epi8(dst1, zero); + dst2 = _mm_unpacklo_epi8(dst2, zero); + dst3 = _mm_unpacklo_epi8(dst3, zero); + // Add the inverse transform. + dst0 = _mm_adds_epi16(dst0, _mm_srai_epi16(m0, 3)); + dst1 = _mm_adds_epi16(dst1, _mm_srai_epi16(m1, 3)); + dst2 = _mm_adds_epi16(dst2, _mm_srai_epi16(m2, 3)); + dst3 = _mm_adds_epi16(dst3, _mm_srai_epi16(m3, 3)); + // Unsigned saturate to 8b. + dst0 = _mm_packus_epi16(dst0, dst0); + dst1 = _mm_packus_epi16(dst1, dst1); + dst2 = _mm_packus_epi16(dst2, dst2); + dst3 = _mm_packus_epi16(dst3, dst3); + // Store the results. + WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(dst0)); + WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(dst1)); + WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(dst2)); + WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(dst3)); +} +#undef MUL +#endif // USE_TRANSFORM_AC3 + +//------------------------------------------------------------------------------ +// Loop Filter (Paragraph 15) + +// Compute abs(p - q) = subs(p - q) OR subs(q - p) +#define MM_ABS(p, q) _mm_or_si128( \ + _mm_subs_epu8((q), (p)), \ + _mm_subs_epu8((p), (q))) + +// Shift each byte of "x" by 3 bits while preserving by the sign bit. +static WEBP_INLINE void SignedShift8b_SSE2(__m128i* const x) { + const __m128i zero = _mm_setzero_si128(); + const __m128i lo_0 = _mm_unpacklo_epi8(zero, *x); + const __m128i hi_0 = _mm_unpackhi_epi8(zero, *x); + const __m128i lo_1 = _mm_srai_epi16(lo_0, 3 + 8); + const __m128i hi_1 = _mm_srai_epi16(hi_0, 3 + 8); + *x = _mm_packs_epi16(lo_1, hi_1); +} + +#define FLIP_SIGN_BIT2(a, b) { \ + (a) = _mm_xor_si128(a, sign_bit); \ + (b) = _mm_xor_si128(b, sign_bit); \ +} + +#define FLIP_SIGN_BIT4(a, b, c, d) { \ + FLIP_SIGN_BIT2(a, b); \ + FLIP_SIGN_BIT2(c, d); \ +} + +// input/output is uint8_t +static WEBP_INLINE void GetNotHEV_SSE2(const __m128i* const p1, + const __m128i* const p0, + const __m128i* const q0, + const __m128i* const q1, + int hev_thresh, __m128i* const not_hev) { + const __m128i zero = _mm_setzero_si128(); + const __m128i t_1 = MM_ABS(*p1, *p0); + const __m128i t_2 = MM_ABS(*q1, *q0); + + const __m128i h = _mm_set1_epi8(hev_thresh); + const __m128i t_max = _mm_max_epu8(t_1, t_2); + + const __m128i t_max_h = _mm_subs_epu8(t_max, h); + *not_hev = _mm_cmpeq_epi8(t_max_h, zero); // not_hev <= t1 && not_hev <= t2 +} + +// input pixels are int8_t +static WEBP_INLINE void GetBaseDelta_SSE2(const __m128i* const p1, + const __m128i* const p0, + const __m128i* const q0, + const __m128i* const q1, + __m128i* const delta) { + // beware of addition order, for saturation! + const __m128i p1_q1 = _mm_subs_epi8(*p1, *q1); // p1 - q1 + const __m128i q0_p0 = _mm_subs_epi8(*q0, *p0); // q0 - p0 + const __m128i s1 = _mm_adds_epi8(p1_q1, q0_p0); // p1 - q1 + 1 * (q0 - p0) + const __m128i s2 = _mm_adds_epi8(q0_p0, s1); // p1 - q1 + 2 * (q0 - p0) + const __m128i s3 = _mm_adds_epi8(q0_p0, s2); // p1 - q1 + 3 * (q0 - p0) + *delta = s3; +} + +// input and output are int8_t +static WEBP_INLINE void DoSimpleFilter_SSE2(__m128i* const p0, + __m128i* const q0, + const __m128i* const fl) { + const __m128i k3 = _mm_set1_epi8(3); + const __m128i k4 = _mm_set1_epi8(4); + __m128i v3 = _mm_adds_epi8(*fl, k3); + __m128i v4 = _mm_adds_epi8(*fl, k4); + + SignedShift8b_SSE2(&v4); // v4 >> 3 + SignedShift8b_SSE2(&v3); // v3 >> 3 + *q0 = _mm_subs_epi8(*q0, v4); // q0 -= v4 + *p0 = _mm_adds_epi8(*p0, v3); // p0 += v3 +} + +// Updates values of 2 pixels at MB edge during complex filtering. +// Update operations: +// q = q - delta and p = p + delta; where delta = [(a_hi >> 7), (a_lo >> 7)] +// Pixels 'pi' and 'qi' are int8_t on input, uint8_t on output (sign flip). +static WEBP_INLINE void Update2Pixels_SSE2(__m128i* const pi, __m128i* const qi, + const __m128i* const a0_lo, + const __m128i* const a0_hi) { + const __m128i a1_lo = _mm_srai_epi16(*a0_lo, 7); + const __m128i a1_hi = _mm_srai_epi16(*a0_hi, 7); + const __m128i delta = _mm_packs_epi16(a1_lo, a1_hi); + const __m128i sign_bit = _mm_set1_epi8((char)0x80); + *pi = _mm_adds_epi8(*pi, delta); + *qi = _mm_subs_epi8(*qi, delta); + FLIP_SIGN_BIT2(*pi, *qi); +} + +// input pixels are uint8_t +static WEBP_INLINE void NeedsFilter_SSE2(const __m128i* const p1, + const __m128i* const p0, + const __m128i* const q0, + const __m128i* const q1, + int thresh, __m128i* const mask) { + const __m128i m_thresh = _mm_set1_epi8((char)thresh); + const __m128i t1 = MM_ABS(*p1, *q1); // abs(p1 - q1) + const __m128i kFE = _mm_set1_epi8((char)0xFE); + const __m128i t2 = _mm_and_si128(t1, kFE); // set lsb of each byte to zero + const __m128i t3 = _mm_srli_epi16(t2, 1); // abs(p1 - q1) / 2 + + const __m128i t4 = MM_ABS(*p0, *q0); // abs(p0 - q0) + const __m128i t5 = _mm_adds_epu8(t4, t4); // abs(p0 - q0) * 2 + const __m128i t6 = _mm_adds_epu8(t5, t3); // abs(p0-q0)*2 + abs(p1-q1)/2 + + const __m128i t7 = _mm_subs_epu8(t6, m_thresh); // mask <= m_thresh + *mask = _mm_cmpeq_epi8(t7, _mm_setzero_si128()); +} + +//------------------------------------------------------------------------------ +// Edge filtering functions + +// Applies filter on 2 pixels (p0 and q0) +static WEBP_INLINE void DoFilter2_SSE2(__m128i* const p1, __m128i* const p0, + __m128i* const q0, __m128i* const q1, + int thresh) { + __m128i a, mask; + const __m128i sign_bit = _mm_set1_epi8((char)0x80); + // convert p1/q1 to int8_t (for GetBaseDelta_SSE2) + const __m128i p1s = _mm_xor_si128(*p1, sign_bit); + const __m128i q1s = _mm_xor_si128(*q1, sign_bit); + + NeedsFilter_SSE2(p1, p0, q0, q1, thresh, &mask); + + FLIP_SIGN_BIT2(*p0, *q0); + GetBaseDelta_SSE2(&p1s, p0, q0, &q1s, &a); + a = _mm_and_si128(a, mask); // mask filter values we don't care about + DoSimpleFilter_SSE2(p0, q0, &a); + FLIP_SIGN_BIT2(*p0, *q0); +} + +// Applies filter on 4 pixels (p1, p0, q0 and q1) +static WEBP_INLINE void DoFilter4_SSE2(__m128i* const p1, __m128i* const p0, + __m128i* const q0, __m128i* const q1, + const __m128i* const mask, + int hev_thresh) { + const __m128i zero = _mm_setzero_si128(); + const __m128i sign_bit = _mm_set1_epi8((char)0x80); + const __m128i k64 = _mm_set1_epi8(64); + const __m128i k3 = _mm_set1_epi8(3); + const __m128i k4 = _mm_set1_epi8(4); + __m128i not_hev; + __m128i t1, t2, t3; + + // compute hev mask + GetNotHEV_SSE2(p1, p0, q0, q1, hev_thresh, ¬_hev); + + // convert to signed values + FLIP_SIGN_BIT4(*p1, *p0, *q0, *q1); + + t1 = _mm_subs_epi8(*p1, *q1); // p1 - q1 + t1 = _mm_andnot_si128(not_hev, t1); // hev(p1 - q1) + t2 = _mm_subs_epi8(*q0, *p0); // q0 - p0 + t1 = _mm_adds_epi8(t1, t2); // hev(p1 - q1) + 1 * (q0 - p0) + t1 = _mm_adds_epi8(t1, t2); // hev(p1 - q1) + 2 * (q0 - p0) + t1 = _mm_adds_epi8(t1, t2); // hev(p1 - q1) + 3 * (q0 - p0) + t1 = _mm_and_si128(t1, *mask); // mask filter values we don't care about + + t2 = _mm_adds_epi8(t1, k3); // 3 * (q0 - p0) + hev(p1 - q1) + 3 + t3 = _mm_adds_epi8(t1, k4); // 3 * (q0 - p0) + hev(p1 - q1) + 4 + SignedShift8b_SSE2(&t2); // (3 * (q0 - p0) + hev(p1 - q1) + 3) >> 3 + SignedShift8b_SSE2(&t3); // (3 * (q0 - p0) + hev(p1 - q1) + 4) >> 3 + *p0 = _mm_adds_epi8(*p0, t2); // p0 += t2 + *q0 = _mm_subs_epi8(*q0, t3); // q0 -= t3 + FLIP_SIGN_BIT2(*p0, *q0); + + // this is equivalent to signed (a + 1) >> 1 calculation + t2 = _mm_add_epi8(t3, sign_bit); + t3 = _mm_avg_epu8(t2, zero); + t3 = _mm_sub_epi8(t3, k64); + + t3 = _mm_and_si128(not_hev, t3); // if !hev + *q1 = _mm_subs_epi8(*q1, t3); // q1 -= t3 + *p1 = _mm_adds_epi8(*p1, t3); // p1 += t3 + FLIP_SIGN_BIT2(*p1, *q1); +} + +// Applies filter on 6 pixels (p2, p1, p0, q0, q1 and q2) +static WEBP_INLINE void DoFilter6_SSE2(__m128i* const p2, __m128i* const p1, + __m128i* const p0, __m128i* const q0, + __m128i* const q1, __m128i* const q2, + const __m128i* const mask, + int hev_thresh) { + const __m128i zero = _mm_setzero_si128(); + const __m128i sign_bit = _mm_set1_epi8((char)0x80); + __m128i a, not_hev; + + // compute hev mask + GetNotHEV_SSE2(p1, p0, q0, q1, hev_thresh, ¬_hev); + + FLIP_SIGN_BIT4(*p1, *p0, *q0, *q1); + FLIP_SIGN_BIT2(*p2, *q2); + GetBaseDelta_SSE2(p1, p0, q0, q1, &a); + + { // do simple filter on pixels with hev + const __m128i m = _mm_andnot_si128(not_hev, *mask); + const __m128i f = _mm_and_si128(a, m); + DoSimpleFilter_SSE2(p0, q0, &f); + } + + { // do strong filter on pixels with not hev + const __m128i k9 = _mm_set1_epi16(0x0900); + const __m128i k63 = _mm_set1_epi16(63); + + const __m128i m = _mm_and_si128(not_hev, *mask); + const __m128i f = _mm_and_si128(a, m); + + const __m128i f_lo = _mm_unpacklo_epi8(zero, f); + const __m128i f_hi = _mm_unpackhi_epi8(zero, f); + + const __m128i f9_lo = _mm_mulhi_epi16(f_lo, k9); // Filter (lo) * 9 + const __m128i f9_hi = _mm_mulhi_epi16(f_hi, k9); // Filter (hi) * 9 + + const __m128i a2_lo = _mm_add_epi16(f9_lo, k63); // Filter * 9 + 63 + const __m128i a2_hi = _mm_add_epi16(f9_hi, k63); // Filter * 9 + 63 + + const __m128i a1_lo = _mm_add_epi16(a2_lo, f9_lo); // Filter * 18 + 63 + const __m128i a1_hi = _mm_add_epi16(a2_hi, f9_hi); // Filter * 18 + 63 + + const __m128i a0_lo = _mm_add_epi16(a1_lo, f9_lo); // Filter * 27 + 63 + const __m128i a0_hi = _mm_add_epi16(a1_hi, f9_hi); // Filter * 27 + 63 + + Update2Pixels_SSE2(p2, q2, &a2_lo, &a2_hi); + Update2Pixels_SSE2(p1, q1, &a1_lo, &a1_hi); + Update2Pixels_SSE2(p0, q0, &a0_lo, &a0_hi); + } +} + +// reads 8 rows across a vertical edge. +static WEBP_INLINE void Load8x4_SSE2(const uint8_t* const b, int stride, + __m128i* const p, __m128i* const q) { + // A0 = 63 62 61 60 23 22 21 20 43 42 41 40 03 02 01 00 + // A1 = 73 72 71 70 33 32 31 30 53 52 51 50 13 12 11 10 + const __m128i A0 = _mm_set_epi32( + WebPMemToInt32(&b[6 * stride]), WebPMemToInt32(&b[2 * stride]), + WebPMemToInt32(&b[4 * stride]), WebPMemToInt32(&b[0 * stride])); + const __m128i A1 = _mm_set_epi32( + WebPMemToInt32(&b[7 * stride]), WebPMemToInt32(&b[3 * stride]), + WebPMemToInt32(&b[5 * stride]), WebPMemToInt32(&b[1 * stride])); + + // B0 = 53 43 52 42 51 41 50 40 13 03 12 02 11 01 10 00 + // B1 = 73 63 72 62 71 61 70 60 33 23 32 22 31 21 30 20 + const __m128i B0 = _mm_unpacklo_epi8(A0, A1); + const __m128i B1 = _mm_unpackhi_epi8(A0, A1); + + // C0 = 33 23 13 03 32 22 12 02 31 21 11 01 30 20 10 00 + // C1 = 73 63 53 43 72 62 52 42 71 61 51 41 70 60 50 40 + const __m128i C0 = _mm_unpacklo_epi16(B0, B1); + const __m128i C1 = _mm_unpackhi_epi16(B0, B1); + + // *p = 71 61 51 41 31 21 11 01 70 60 50 40 30 20 10 00 + // *q = 73 63 53 43 33 23 13 03 72 62 52 42 32 22 12 02 + *p = _mm_unpacklo_epi32(C0, C1); + *q = _mm_unpackhi_epi32(C0, C1); +} + +static WEBP_INLINE void Load16x4_SSE2(const uint8_t* const r0, + const uint8_t* const r8, + int stride, + __m128i* const p1, __m128i* const p0, + __m128i* const q0, __m128i* const q1) { + // Assume the pixels around the edge (|) are numbered as follows + // 00 01 | 02 03 + // 10 11 | 12 13 + // ... | ... + // e0 e1 | e2 e3 + // f0 f1 | f2 f3 + // + // r0 is pointing to the 0th row (00) + // r8 is pointing to the 8th row (80) + + // Load + // p1 = 71 61 51 41 31 21 11 01 70 60 50 40 30 20 10 00 + // q0 = 73 63 53 43 33 23 13 03 72 62 52 42 32 22 12 02 + // p0 = f1 e1 d1 c1 b1 a1 91 81 f0 e0 d0 c0 b0 a0 90 80 + // q1 = f3 e3 d3 c3 b3 a3 93 83 f2 e2 d2 c2 b2 a2 92 82 + Load8x4_SSE2(r0, stride, p1, q0); + Load8x4_SSE2(r8, stride, p0, q1); + + { + // p1 = f0 e0 d0 c0 b0 a0 90 80 70 60 50 40 30 20 10 00 + // p0 = f1 e1 d1 c1 b1 a1 91 81 71 61 51 41 31 21 11 01 + // q0 = f2 e2 d2 c2 b2 a2 92 82 72 62 52 42 32 22 12 02 + // q1 = f3 e3 d3 c3 b3 a3 93 83 73 63 53 43 33 23 13 03 + const __m128i t1 = *p1; + const __m128i t2 = *q0; + *p1 = _mm_unpacklo_epi64(t1, *p0); + *p0 = _mm_unpackhi_epi64(t1, *p0); + *q0 = _mm_unpacklo_epi64(t2, *q1); + *q1 = _mm_unpackhi_epi64(t2, *q1); + } +} + +static WEBP_INLINE void Store4x4_SSE2(__m128i* const x, + uint8_t* dst, int stride) { + int i; + for (i = 0; i < 4; ++i, dst += stride) { + WebPInt32ToMem(dst, _mm_cvtsi128_si32(*x)); + *x = _mm_srli_si128(*x, 4); + } +} + +// Transpose back and store +static WEBP_INLINE void Store16x4_SSE2(const __m128i* const p1, + const __m128i* const p0, + const __m128i* const q0, + const __m128i* const q1, + uint8_t* r0, uint8_t* r8, + int stride) { + __m128i t1, p1_s, p0_s, q0_s, q1_s; + + // p0 = 71 70 61 60 51 50 41 40 31 30 21 20 11 10 01 00 + // p1 = f1 f0 e1 e0 d1 d0 c1 c0 b1 b0 a1 a0 91 90 81 80 + t1 = *p0; + p0_s = _mm_unpacklo_epi8(*p1, t1); + p1_s = _mm_unpackhi_epi8(*p1, t1); + + // q0 = 73 72 63 62 53 52 43 42 33 32 23 22 13 12 03 02 + // q1 = f3 f2 e3 e2 d3 d2 c3 c2 b3 b2 a3 a2 93 92 83 82 + t1 = *q0; + q0_s = _mm_unpacklo_epi8(t1, *q1); + q1_s = _mm_unpackhi_epi8(t1, *q1); + + // p0 = 33 32 31 30 23 22 21 20 13 12 11 10 03 02 01 00 + // q0 = 73 72 71 70 63 62 61 60 53 52 51 50 43 42 41 40 + t1 = p0_s; + p0_s = _mm_unpacklo_epi16(t1, q0_s); + q0_s = _mm_unpackhi_epi16(t1, q0_s); + + // p1 = b3 b2 b1 b0 a3 a2 a1 a0 93 92 91 90 83 82 81 80 + // q1 = f3 f2 f1 f0 e3 e2 e1 e0 d3 d2 d1 d0 c3 c2 c1 c0 + t1 = p1_s; + p1_s = _mm_unpacklo_epi16(t1, q1_s); + q1_s = _mm_unpackhi_epi16(t1, q1_s); + + Store4x4_SSE2(&p0_s, r0, stride); + r0 += 4 * stride; + Store4x4_SSE2(&q0_s, r0, stride); + + Store4x4_SSE2(&p1_s, r8, stride); + r8 += 4 * stride; + Store4x4_SSE2(&q1_s, r8, stride); +} + +//------------------------------------------------------------------------------ +// Simple In-loop filtering (Paragraph 15.2) + +static void SimpleVFilter16_SSE2(uint8_t* p, int stride, int thresh) { + // Load + __m128i p1 = _mm_loadu_si128((__m128i*)&p[-2 * stride]); + __m128i p0 = _mm_loadu_si128((__m128i*)&p[-stride]); + __m128i q0 = _mm_loadu_si128((__m128i*)&p[0]); + __m128i q1 = _mm_loadu_si128((__m128i*)&p[stride]); + + DoFilter2_SSE2(&p1, &p0, &q0, &q1, thresh); + + // Store + _mm_storeu_si128((__m128i*)&p[-stride], p0); + _mm_storeu_si128((__m128i*)&p[0], q0); +} + +static void SimpleHFilter16_SSE2(uint8_t* p, int stride, int thresh) { + __m128i p1, p0, q0, q1; + + p -= 2; // beginning of p1 + + Load16x4_SSE2(p, p + 8 * stride, stride, &p1, &p0, &q0, &q1); + DoFilter2_SSE2(&p1, &p0, &q0, &q1, thresh); + Store16x4_SSE2(&p1, &p0, &q0, &q1, p, p + 8 * stride, stride); +} + +static void SimpleVFilter16i_SSE2(uint8_t* p, int stride, int thresh) { + int k; + for (k = 3; k > 0; --k) { + p += 4 * stride; + SimpleVFilter16_SSE2(p, stride, thresh); + } +} + +static void SimpleHFilter16i_SSE2(uint8_t* p, int stride, int thresh) { + int k; + for (k = 3; k > 0; --k) { + p += 4; + SimpleHFilter16_SSE2(p, stride, thresh); + } +} + +//------------------------------------------------------------------------------ +// Complex In-loop filtering (Paragraph 15.3) + +#define MAX_DIFF1(p3, p2, p1, p0, m) do { \ + (m) = MM_ABS(p1, p0); \ + (m) = _mm_max_epu8(m, MM_ABS(p3, p2)); \ + (m) = _mm_max_epu8(m, MM_ABS(p2, p1)); \ +} while (0) + +#define MAX_DIFF2(p3, p2, p1, p0, m) do { \ + (m) = _mm_max_epu8(m, MM_ABS(p1, p0)); \ + (m) = _mm_max_epu8(m, MM_ABS(p3, p2)); \ + (m) = _mm_max_epu8(m, MM_ABS(p2, p1)); \ +} while (0) + +#define LOAD_H_EDGES4(p, stride, e1, e2, e3, e4) { \ + (e1) = _mm_loadu_si128((__m128i*)&(p)[0 * (stride)]); \ + (e2) = _mm_loadu_si128((__m128i*)&(p)[1 * (stride)]); \ + (e3) = _mm_loadu_si128((__m128i*)&(p)[2 * (stride)]); \ + (e4) = _mm_loadu_si128((__m128i*)&(p)[3 * (stride)]); \ +} + +#define LOADUV_H_EDGE(p, u, v, stride) do { \ + const __m128i U = _mm_loadl_epi64((__m128i*)&(u)[(stride)]); \ + const __m128i V = _mm_loadl_epi64((__m128i*)&(v)[(stride)]); \ + (p) = _mm_unpacklo_epi64(U, V); \ +} while (0) + +#define LOADUV_H_EDGES4(u, v, stride, e1, e2, e3, e4) { \ + LOADUV_H_EDGE(e1, u, v, 0 * (stride)); \ + LOADUV_H_EDGE(e2, u, v, 1 * (stride)); \ + LOADUV_H_EDGE(e3, u, v, 2 * (stride)); \ + LOADUV_H_EDGE(e4, u, v, 3 * (stride)); \ +} + +#define STOREUV(p, u, v, stride) { \ + _mm_storel_epi64((__m128i*)&(u)[(stride)], p); \ + (p) = _mm_srli_si128(p, 8); \ + _mm_storel_epi64((__m128i*)&(v)[(stride)], p); \ +} + +static WEBP_INLINE void ComplexMask_SSE2(const __m128i* const p1, + const __m128i* const p0, + const __m128i* const q0, + const __m128i* const q1, + int thresh, int ithresh, + __m128i* const mask) { + const __m128i it = _mm_set1_epi8(ithresh); + const __m128i diff = _mm_subs_epu8(*mask, it); + const __m128i thresh_mask = _mm_cmpeq_epi8(diff, _mm_setzero_si128()); + __m128i filter_mask; + NeedsFilter_SSE2(p1, p0, q0, q1, thresh, &filter_mask); + *mask = _mm_and_si128(thresh_mask, filter_mask); +} + +// on macroblock edges +static void VFilter16_SSE2(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + __m128i t1; + __m128i mask; + __m128i p2, p1, p0, q0, q1, q2; + + // Load p3, p2, p1, p0 + LOAD_H_EDGES4(p - 4 * stride, stride, t1, p2, p1, p0); + MAX_DIFF1(t1, p2, p1, p0, mask); + + // Load q0, q1, q2, q3 + LOAD_H_EDGES4(p, stride, q0, q1, q2, t1); + MAX_DIFF2(t1, q2, q1, q0, mask); + + ComplexMask_SSE2(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); + DoFilter6_SSE2(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh); + + // Store + _mm_storeu_si128((__m128i*)&p[-3 * stride], p2); + _mm_storeu_si128((__m128i*)&p[-2 * stride], p1); + _mm_storeu_si128((__m128i*)&p[-1 * stride], p0); + _mm_storeu_si128((__m128i*)&p[+0 * stride], q0); + _mm_storeu_si128((__m128i*)&p[+1 * stride], q1); + _mm_storeu_si128((__m128i*)&p[+2 * stride], q2); +} + +static void HFilter16_SSE2(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + __m128i mask; + __m128i p3, p2, p1, p0, q0, q1, q2, q3; + + uint8_t* const b = p - 4; + Load16x4_SSE2(b, b + 8 * stride, stride, &p3, &p2, &p1, &p0); + MAX_DIFF1(p3, p2, p1, p0, mask); + + Load16x4_SSE2(p, p + 8 * stride, stride, &q0, &q1, &q2, &q3); + MAX_DIFF2(q3, q2, q1, q0, mask); + + ComplexMask_SSE2(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); + DoFilter6_SSE2(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh); + + Store16x4_SSE2(&p3, &p2, &p1, &p0, b, b + 8 * stride, stride); + Store16x4_SSE2(&q0, &q1, &q2, &q3, p, p + 8 * stride, stride); +} + +// on three inner edges +static void VFilter16i_SSE2(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + int k; + __m128i p3, p2, p1, p0; // loop invariants + + LOAD_H_EDGES4(p, stride, p3, p2, p1, p0); // prologue + + for (k = 3; k > 0; --k) { + __m128i mask, tmp1, tmp2; + uint8_t* const b = p + 2 * stride; // beginning of p1 + p += 4 * stride; + + MAX_DIFF1(p3, p2, p1, p0, mask); // compute partial mask + LOAD_H_EDGES4(p, stride, p3, p2, tmp1, tmp2); + MAX_DIFF2(p3, p2, tmp1, tmp2, mask); + + // p3 and p2 are not just temporary variables here: they will be + // re-used for next span. And q2/q3 will become p1/p0 accordingly. + ComplexMask_SSE2(&p1, &p0, &p3, &p2, thresh, ithresh, &mask); + DoFilter4_SSE2(&p1, &p0, &p3, &p2, &mask, hev_thresh); + + // Store + _mm_storeu_si128((__m128i*)&b[0 * stride], p1); + _mm_storeu_si128((__m128i*)&b[1 * stride], p0); + _mm_storeu_si128((__m128i*)&b[2 * stride], p3); + _mm_storeu_si128((__m128i*)&b[3 * stride], p2); + + // rotate samples + p1 = tmp1; + p0 = tmp2; + } +} + +static void HFilter16i_SSE2(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + int k; + __m128i p3, p2, p1, p0; // loop invariants + + Load16x4_SSE2(p, p + 8 * stride, stride, &p3, &p2, &p1, &p0); // prologue + + for (k = 3; k > 0; --k) { + __m128i mask, tmp1, tmp2; + uint8_t* const b = p + 2; // beginning of p1 + + p += 4; // beginning of q0 (and next span) + + MAX_DIFF1(p3, p2, p1, p0, mask); // compute partial mask + Load16x4_SSE2(p, p + 8 * stride, stride, &p3, &p2, &tmp1, &tmp2); + MAX_DIFF2(p3, p2, tmp1, tmp2, mask); + + ComplexMask_SSE2(&p1, &p0, &p3, &p2, thresh, ithresh, &mask); + DoFilter4_SSE2(&p1, &p0, &p3, &p2, &mask, hev_thresh); + + Store16x4_SSE2(&p1, &p0, &p3, &p2, b, b + 8 * stride, stride); + + // rotate samples + p1 = tmp1; + p0 = tmp2; + } +} + +// 8-pixels wide variant, for chroma filtering +static void VFilter8_SSE2(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + __m128i mask; + __m128i t1, p2, p1, p0, q0, q1, q2; + + // Load p3, p2, p1, p0 + LOADUV_H_EDGES4(u - 4 * stride, v - 4 * stride, stride, t1, p2, p1, p0); + MAX_DIFF1(t1, p2, p1, p0, mask); + + // Load q0, q1, q2, q3 + LOADUV_H_EDGES4(u, v, stride, q0, q1, q2, t1); + MAX_DIFF2(t1, q2, q1, q0, mask); + + ComplexMask_SSE2(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); + DoFilter6_SSE2(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh); + + // Store + STOREUV(p2, u, v, -3 * stride); + STOREUV(p1, u, v, -2 * stride); + STOREUV(p0, u, v, -1 * stride); + STOREUV(q0, u, v, 0 * stride); + STOREUV(q1, u, v, 1 * stride); + STOREUV(q2, u, v, 2 * stride); +} + +static void HFilter8_SSE2(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + __m128i mask; + __m128i p3, p2, p1, p0, q0, q1, q2, q3; + + uint8_t* const tu = u - 4; + uint8_t* const tv = v - 4; + Load16x4_SSE2(tu, tv, stride, &p3, &p2, &p1, &p0); + MAX_DIFF1(p3, p2, p1, p0, mask); + + Load16x4_SSE2(u, v, stride, &q0, &q1, &q2, &q3); + MAX_DIFF2(q3, q2, q1, q0, mask); + + ComplexMask_SSE2(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); + DoFilter6_SSE2(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh); + + Store16x4_SSE2(&p3, &p2, &p1, &p0, tu, tv, stride); + Store16x4_SSE2(&q0, &q1, &q2, &q3, u, v, stride); +} + +static void VFilter8i_SSE2(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + __m128i mask; + __m128i t1, t2, p1, p0, q0, q1; + + // Load p3, p2, p1, p0 + LOADUV_H_EDGES4(u, v, stride, t2, t1, p1, p0); + MAX_DIFF1(t2, t1, p1, p0, mask); + + u += 4 * stride; + v += 4 * stride; + + // Load q0, q1, q2, q3 + LOADUV_H_EDGES4(u, v, stride, q0, q1, t1, t2); + MAX_DIFF2(t2, t1, q1, q0, mask); + + ComplexMask_SSE2(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); + DoFilter4_SSE2(&p1, &p0, &q0, &q1, &mask, hev_thresh); + + // Store + STOREUV(p1, u, v, -2 * stride); + STOREUV(p0, u, v, -1 * stride); + STOREUV(q0, u, v, 0 * stride); + STOREUV(q1, u, v, 1 * stride); +} + +static void HFilter8i_SSE2(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + __m128i mask; + __m128i t1, t2, p1, p0, q0, q1; + Load16x4_SSE2(u, v, stride, &t2, &t1, &p1, &p0); // p3, p2, p1, p0 + MAX_DIFF1(t2, t1, p1, p0, mask); + + u += 4; // beginning of q0 + v += 4; + Load16x4_SSE2(u, v, stride, &q0, &q1, &t1, &t2); // q0, q1, q2, q3 + MAX_DIFF2(t2, t1, q1, q0, mask); + + ComplexMask_SSE2(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); + DoFilter4_SSE2(&p1, &p0, &q0, &q1, &mask, hev_thresh); + + u -= 2; // beginning of p1 + v -= 2; + Store16x4_SSE2(&p1, &p0, &q0, &q1, u, v, stride); +} + +//------------------------------------------------------------------------------ +// 4x4 predictions + +#define DST(x, y) dst[(x) + (y) * BPS] +#define AVG3(a, b, c) (((a) + 2 * (b) + (c) + 2) >> 2) + +// We use the following 8b-arithmetic tricks: +// (a + 2 * b + c + 2) >> 2 = (AC + b + 1) >> 1 +// where: AC = (a + c) >> 1 = [(a + c + 1) >> 1] - [(a^c) & 1] +// and: +// (a + 2 * b + c + 2) >> 2 = (AB + BC + 1) >> 1 - (ab|bc)&lsb +// where: AC = (a + b + 1) >> 1, BC = (b + c + 1) >> 1 +// and ab = a ^ b, bc = b ^ c, lsb = (AC^BC)&1 + +static void VE4_SSE2(uint8_t* dst) { // vertical + const __m128i one = _mm_set1_epi8(1); + const __m128i ABCDEFGH = _mm_loadl_epi64((__m128i*)(dst - BPS - 1)); + const __m128i BCDEFGH0 = _mm_srli_si128(ABCDEFGH, 1); + const __m128i CDEFGH00 = _mm_srli_si128(ABCDEFGH, 2); + const __m128i a = _mm_avg_epu8(ABCDEFGH, CDEFGH00); + const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGH00), one); + const __m128i b = _mm_subs_epu8(a, lsb); + const __m128i avg = _mm_avg_epu8(b, BCDEFGH0); + const int vals = _mm_cvtsi128_si32(avg); + int i; + for (i = 0; i < 4; ++i) { + WebPInt32ToMem(dst + i * BPS, vals); + } +} + +static void LD4_SSE2(uint8_t* dst) { // Down-Left + const __m128i one = _mm_set1_epi8(1); + const __m128i ABCDEFGH = _mm_loadl_epi64((__m128i*)(dst - BPS)); + const __m128i BCDEFGH0 = _mm_srli_si128(ABCDEFGH, 1); + const __m128i CDEFGH00 = _mm_srli_si128(ABCDEFGH, 2); + const __m128i CDEFGHH0 = _mm_insert_epi16(CDEFGH00, dst[-BPS + 7], 3); + const __m128i avg1 = _mm_avg_epu8(ABCDEFGH, CDEFGHH0); + const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGHH0), one); + const __m128i avg2 = _mm_subs_epu8(avg1, lsb); + const __m128i abcdefg = _mm_avg_epu8(avg2, BCDEFGH0); + WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcdefg )); + WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1))); + WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2))); + WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3))); +} + +static void VR4_SSE2(uint8_t* dst) { // Vertical-Right + const __m128i one = _mm_set1_epi8(1); + const int I = dst[-1 + 0 * BPS]; + const int J = dst[-1 + 1 * BPS]; + const int K = dst[-1 + 2 * BPS]; + const int X = dst[-1 - BPS]; + const __m128i XABCD = _mm_loadl_epi64((__m128i*)(dst - BPS - 1)); + const __m128i ABCD0 = _mm_srli_si128(XABCD, 1); + const __m128i abcd = _mm_avg_epu8(XABCD, ABCD0); + const __m128i _XABCD = _mm_slli_si128(XABCD, 1); + const __m128i IXABCD = _mm_insert_epi16(_XABCD, (short)(I | (X << 8)), 0); + const __m128i avg1 = _mm_avg_epu8(IXABCD, ABCD0); + const __m128i lsb = _mm_and_si128(_mm_xor_si128(IXABCD, ABCD0), one); + const __m128i avg2 = _mm_subs_epu8(avg1, lsb); + const __m128i efgh = _mm_avg_epu8(avg2, XABCD); + WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcd )); + WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( efgh )); + WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(abcd, 1))); + WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(efgh, 1))); + + // these two are hard to implement in SSE2, so we keep the C-version: + DST(0, 2) = AVG3(J, I, X); + DST(0, 3) = AVG3(K, J, I); +} + +static void VL4_SSE2(uint8_t* dst) { // Vertical-Left + const __m128i one = _mm_set1_epi8(1); + const __m128i ABCDEFGH = _mm_loadl_epi64((__m128i*)(dst - BPS)); + const __m128i BCDEFGH_ = _mm_srli_si128(ABCDEFGH, 1); + const __m128i CDEFGH__ = _mm_srli_si128(ABCDEFGH, 2); + const __m128i avg1 = _mm_avg_epu8(ABCDEFGH, BCDEFGH_); + const __m128i avg2 = _mm_avg_epu8(CDEFGH__, BCDEFGH_); + const __m128i avg3 = _mm_avg_epu8(avg1, avg2); + const __m128i lsb1 = _mm_and_si128(_mm_xor_si128(avg1, avg2), one); + const __m128i ab = _mm_xor_si128(ABCDEFGH, BCDEFGH_); + const __m128i bc = _mm_xor_si128(CDEFGH__, BCDEFGH_); + const __m128i abbc = _mm_or_si128(ab, bc); + const __m128i lsb2 = _mm_and_si128(abbc, lsb1); + const __m128i avg4 = _mm_subs_epu8(avg3, lsb2); + const uint32_t extra_out = + (uint32_t)_mm_cvtsi128_si32(_mm_srli_si128(avg4, 4)); + WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( avg1 )); + WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( avg4 )); + WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg1, 1))); + WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg4, 1))); + + // these two are hard to get and irregular + DST(3, 2) = (extra_out >> 0) & 0xff; + DST(3, 3) = (extra_out >> 8) & 0xff; +} + +static void RD4_SSE2(uint8_t* dst) { // Down-right + const __m128i one = _mm_set1_epi8(1); + const __m128i XABCD = _mm_loadl_epi64((__m128i*)(dst - BPS - 1)); + const __m128i ____XABCD = _mm_slli_si128(XABCD, 4); + const uint32_t I = dst[-1 + 0 * BPS]; + const uint32_t J = dst[-1 + 1 * BPS]; + const uint32_t K = dst[-1 + 2 * BPS]; + const uint32_t L = dst[-1 + 3 * BPS]; + const __m128i LKJI_____ = + _mm_cvtsi32_si128((int)(L | (K << 8) | (J << 16) | (I << 24))); + const __m128i LKJIXABCD = _mm_or_si128(LKJI_____, ____XABCD); + const __m128i KJIXABCD_ = _mm_srli_si128(LKJIXABCD, 1); + const __m128i JIXABCD__ = _mm_srli_si128(LKJIXABCD, 2); + const __m128i avg1 = _mm_avg_epu8(JIXABCD__, LKJIXABCD); + const __m128i lsb = _mm_and_si128(_mm_xor_si128(JIXABCD__, LKJIXABCD), one); + const __m128i avg2 = _mm_subs_epu8(avg1, lsb); + const __m128i abcdefg = _mm_avg_epu8(avg2, KJIXABCD_); + WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32( abcdefg )); + WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1))); + WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2))); + WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3))); +} + +#undef DST +#undef AVG3 + +//------------------------------------------------------------------------------ +// Luma 16x16 + +static WEBP_INLINE void TrueMotion_SSE2(uint8_t* dst, int size) { + const uint8_t* top = dst - BPS; + const __m128i zero = _mm_setzero_si128(); + int y; + if (size == 4) { + const __m128i top_values = _mm_cvtsi32_si128(WebPMemToInt32(top)); + const __m128i top_base = _mm_unpacklo_epi8(top_values, zero); + for (y = 0; y < 4; ++y, dst += BPS) { + const int val = dst[-1] - top[-1]; + const __m128i base = _mm_set1_epi16(val); + const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero); + WebPInt32ToMem(dst, _mm_cvtsi128_si32(out)); + } + } else if (size == 8) { + const __m128i top_values = _mm_loadl_epi64((const __m128i*)top); + const __m128i top_base = _mm_unpacklo_epi8(top_values, zero); + for (y = 0; y < 8; ++y, dst += BPS) { + const int val = dst[-1] - top[-1]; + const __m128i base = _mm_set1_epi16(val); + const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero); + _mm_storel_epi64((__m128i*)dst, out); + } + } else { + const __m128i top_values = _mm_loadu_si128((const __m128i*)top); + const __m128i top_base_0 = _mm_unpacklo_epi8(top_values, zero); + const __m128i top_base_1 = _mm_unpackhi_epi8(top_values, zero); + for (y = 0; y < 16; ++y, dst += BPS) { + const int val = dst[-1] - top[-1]; + const __m128i base = _mm_set1_epi16(val); + const __m128i out_0 = _mm_add_epi16(base, top_base_0); + const __m128i out_1 = _mm_add_epi16(base, top_base_1); + const __m128i out = _mm_packus_epi16(out_0, out_1); + _mm_storeu_si128((__m128i*)dst, out); + } + } +} + +static void TM4_SSE2(uint8_t* dst) { TrueMotion_SSE2(dst, 4); } +static void TM8uv_SSE2(uint8_t* dst) { TrueMotion_SSE2(dst, 8); } +static void TM16_SSE2(uint8_t* dst) { TrueMotion_SSE2(dst, 16); } + +static void VE16_SSE2(uint8_t* dst) { + const __m128i top = _mm_loadu_si128((const __m128i*)(dst - BPS)); + int j; + for (j = 0; j < 16; ++j) { + _mm_storeu_si128((__m128i*)(dst + j * BPS), top); + } +} + +static void HE16_SSE2(uint8_t* dst) { // horizontal + int j; + for (j = 16; j > 0; --j) { + const __m128i values = _mm_set1_epi8((char)dst[-1]); + _mm_storeu_si128((__m128i*)dst, values); + dst += BPS; + } +} + +static WEBP_INLINE void Put16_SSE2(uint8_t v, uint8_t* dst) { + int j; + const __m128i values = _mm_set1_epi8((char)v); + for (j = 0; j < 16; ++j) { + _mm_storeu_si128((__m128i*)(dst + j * BPS), values); + } +} + +static void DC16_SSE2(uint8_t* dst) { // DC + const __m128i zero = _mm_setzero_si128(); + const __m128i top = _mm_loadu_si128((const __m128i*)(dst - BPS)); + const __m128i sad8x2 = _mm_sad_epu8(top, zero); + // sum the two sads: sad8x2[0:1] + sad8x2[8:9] + const __m128i sum = _mm_add_epi16(sad8x2, _mm_shuffle_epi32(sad8x2, 2)); + int left = 0; + int j; + for (j = 0; j < 16; ++j) { + left += dst[-1 + j * BPS]; + } + { + const int DC = _mm_cvtsi128_si32(sum) + left + 16; + Put16_SSE2(DC >> 5, dst); + } +} + +static void DC16NoTop_SSE2(uint8_t* dst) { // DC with top samples unavailable + int DC = 8; + int j; + for (j = 0; j < 16; ++j) { + DC += dst[-1 + j * BPS]; + } + Put16_SSE2(DC >> 4, dst); +} + +static void DC16NoLeft_SSE2(uint8_t* dst) { // DC with left samples unavailable + const __m128i zero = _mm_setzero_si128(); + const __m128i top = _mm_loadu_si128((const __m128i*)(dst - BPS)); + const __m128i sad8x2 = _mm_sad_epu8(top, zero); + // sum the two sads: sad8x2[0:1] + sad8x2[8:9] + const __m128i sum = _mm_add_epi16(sad8x2, _mm_shuffle_epi32(sad8x2, 2)); + const int DC = _mm_cvtsi128_si32(sum) + 8; + Put16_SSE2(DC >> 4, dst); +} + +static void DC16NoTopLeft_SSE2(uint8_t* dst) { // DC with no top & left samples + Put16_SSE2(0x80, dst); +} + +//------------------------------------------------------------------------------ +// Chroma + +static void VE8uv_SSE2(uint8_t* dst) { // vertical + int j; + const __m128i top = _mm_loadl_epi64((const __m128i*)(dst - BPS)); + for (j = 0; j < 8; ++j) { + _mm_storel_epi64((__m128i*)(dst + j * BPS), top); + } +} + +// helper for chroma-DC predictions +static WEBP_INLINE void Put8x8uv_SSE2(uint8_t v, uint8_t* dst) { + int j; + const __m128i values = _mm_set1_epi8((char)v); + for (j = 0; j < 8; ++j) { + _mm_storel_epi64((__m128i*)(dst + j * BPS), values); + } +} + +static void DC8uv_SSE2(uint8_t* dst) { // DC + const __m128i zero = _mm_setzero_si128(); + const __m128i top = _mm_loadl_epi64((const __m128i*)(dst - BPS)); + const __m128i sum = _mm_sad_epu8(top, zero); + int left = 0; + int j; + for (j = 0; j < 8; ++j) { + left += dst[-1 + j * BPS]; + } + { + const int DC = _mm_cvtsi128_si32(sum) + left + 8; + Put8x8uv_SSE2(DC >> 4, dst); + } +} + +static void DC8uvNoLeft_SSE2(uint8_t* dst) { // DC with no left samples + const __m128i zero = _mm_setzero_si128(); + const __m128i top = _mm_loadl_epi64((const __m128i*)(dst - BPS)); + const __m128i sum = _mm_sad_epu8(top, zero); + const int DC = _mm_cvtsi128_si32(sum) + 4; + Put8x8uv_SSE2(DC >> 3, dst); +} + +static void DC8uvNoTop_SSE2(uint8_t* dst) { // DC with no top samples + int dc0 = 4; + int i; + for (i = 0; i < 8; ++i) { + dc0 += dst[-1 + i * BPS]; + } + Put8x8uv_SSE2(dc0 >> 3, dst); +} + +static void DC8uvNoTopLeft_SSE2(uint8_t* dst) { // DC with nothing + Put8x8uv_SSE2(0x80, dst); +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8DspInitSSE2(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitSSE2(void) { + VP8Transform = Transform_SSE2; +#if (USE_TRANSFORM_AC3 == 1) + VP8TransformAC3 = TransformAC3_SSE2; +#endif + + VP8VFilter16 = VFilter16_SSE2; + VP8HFilter16 = HFilter16_SSE2; + VP8VFilter8 = VFilter8_SSE2; + VP8HFilter8 = HFilter8_SSE2; + VP8VFilter16i = VFilter16i_SSE2; + VP8HFilter16i = HFilter16i_SSE2; + VP8VFilter8i = VFilter8i_SSE2; + VP8HFilter8i = HFilter8i_SSE2; + + VP8SimpleVFilter16 = SimpleVFilter16_SSE2; + VP8SimpleHFilter16 = SimpleHFilter16_SSE2; + VP8SimpleVFilter16i = SimpleVFilter16i_SSE2; + VP8SimpleHFilter16i = SimpleHFilter16i_SSE2; + + VP8PredLuma4[1] = TM4_SSE2; + VP8PredLuma4[2] = VE4_SSE2; + VP8PredLuma4[4] = RD4_SSE2; + VP8PredLuma4[5] = VR4_SSE2; + VP8PredLuma4[6] = LD4_SSE2; + VP8PredLuma4[7] = VL4_SSE2; + + VP8PredLuma16[0] = DC16_SSE2; + VP8PredLuma16[1] = TM16_SSE2; + VP8PredLuma16[2] = VE16_SSE2; + VP8PredLuma16[3] = HE16_SSE2; + VP8PredLuma16[4] = DC16NoTop_SSE2; + VP8PredLuma16[5] = DC16NoLeft_SSE2; + VP8PredLuma16[6] = DC16NoTopLeft_SSE2; + + VP8PredChroma8[0] = DC8uv_SSE2; + VP8PredChroma8[1] = TM8uv_SSE2; + VP8PredChroma8[2] = VE8uv_SSE2; + VP8PredChroma8[4] = DC8uvNoTop_SSE2; + VP8PredChroma8[5] = DC8uvNoLeft_SSE2; + VP8PredChroma8[6] = DC8uvNoTopLeft_SSE2; +} + +#else // !WEBP_USE_SSE2 + +WEBP_DSP_INIT_STUB(VP8DspInitSSE2) + +#endif // WEBP_USE_SSE2 diff --git a/third-party/webp/libwebp/src/dsp/dec_sse41.c b/third-party/webp/libwebp/src/dsp/dec_sse41.c new file mode 100644 index 0000000000..08a3630272 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/dec_sse41.c @@ -0,0 +1,46 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE4 version of some decoding functions. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE41) + +#include +#include "src/dec/vp8i_dec.h" +#include "src/utils/utils.h" + +static void HE16_SSE41(uint8_t* dst) { // horizontal + int j; + const __m128i kShuffle3 = _mm_set1_epi8(3); + for (j = 16; j > 0; --j) { + const __m128i in = _mm_cvtsi32_si128(WebPMemToInt32(dst - 4)); + const __m128i values = _mm_shuffle_epi8(in, kShuffle3); + _mm_storeu_si128((__m128i*)dst, values); + dst += BPS; + } +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8DspInitSSE41(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitSSE41(void) { + VP8PredLuma16[3] = HE16_SSE41; +} + +#else // !WEBP_USE_SSE41 + +WEBP_DSP_INIT_STUB(VP8DspInitSSE41) + +#endif // WEBP_USE_SSE41 diff --git a/third-party/webp/libwebp/src/dsp/dsp.h b/third-party/webp/libwebp/src/dsp/dsp.h new file mode 100644 index 0000000000..d2000b8efc --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/dsp.h @@ -0,0 +1,504 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Speed-critical functions. +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_DSP_DSP_H_ +#define WEBP_DSP_DSP_H_ + +#ifdef HAVE_CONFIG_H +#include "src/webp/config.h" +#endif + +#include "src/dsp/cpu.h" +#include "src/webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define BPS 32 // this is the common stride for enc/dec + +//------------------------------------------------------------------------------ +// WEBP_RESTRICT + +// Declares a pointer with the restrict type qualifier if available. +// This allows code to hint to the compiler that only this pointer references a +// particular object or memory region within the scope of the block in which it +// is declared. This may allow for improved optimizations due to the lack of +// pointer aliasing. See also: +// https://en.cppreference.com/w/c/language/restrict +#if defined(__GNUC__) +#define WEBP_RESTRICT __restrict__ +#elif defined(_MSC_VER) +#define WEBP_RESTRICT __restrict +#else +#define WEBP_RESTRICT +#endif + + +//------------------------------------------------------------------------------ +// Init stub generator + +// Defines an init function stub to ensure each module exposes a symbol, +// avoiding a compiler warning. +#define WEBP_DSP_INIT_STUB(func) \ + extern void func(void); \ + void func(void) {} + +//------------------------------------------------------------------------------ +// Encoding + +// Transforms +// VP8Idct: Does one of two inverse transforms. If do_two is set, the transforms +// will be done for (ref, in, dst) and (ref + 4, in + 16, dst + 4). +typedef void (*VP8Idct)(const uint8_t* ref, const int16_t* in, uint8_t* dst, + int do_two); +typedef void (*VP8Fdct)(const uint8_t* src, const uint8_t* ref, int16_t* out); +typedef void (*VP8WHT)(const int16_t* in, int16_t* out); +extern VP8Idct VP8ITransform; +extern VP8Fdct VP8FTransform; +extern VP8Fdct VP8FTransform2; // performs two transforms at a time +extern VP8WHT VP8FTransformWHT; +// Predictions +// *dst is the destination block. *top and *left can be NULL. +typedef void (*VP8IntraPreds)(uint8_t* dst, const uint8_t* left, + const uint8_t* top); +typedef void (*VP8Intra4Preds)(uint8_t* dst, const uint8_t* top); +extern VP8Intra4Preds VP8EncPredLuma4; +extern VP8IntraPreds VP8EncPredLuma16; +extern VP8IntraPreds VP8EncPredChroma8; + +typedef int (*VP8Metric)(const uint8_t* pix, const uint8_t* ref); +extern VP8Metric VP8SSE16x16, VP8SSE16x8, VP8SSE8x8, VP8SSE4x4; +typedef int (*VP8WMetric)(const uint8_t* pix, const uint8_t* ref, + const uint16_t* const weights); +// The weights for VP8TDisto4x4 and VP8TDisto16x16 contain a row-major +// 4 by 4 symmetric matrix. +extern VP8WMetric VP8TDisto4x4, VP8TDisto16x16; + +// Compute the average (DC) of four 4x4 blocks. +// Each sub-4x4 block #i sum is stored in dc[i]. +typedef void (*VP8MeanMetric)(const uint8_t* ref, uint32_t dc[4]); +extern VP8MeanMetric VP8Mean16x4; + +typedef void (*VP8BlockCopy)(const uint8_t* src, uint8_t* dst); +extern VP8BlockCopy VP8Copy4x4; +extern VP8BlockCopy VP8Copy16x8; +// Quantization +struct VP8Matrix; // forward declaration +typedef int (*VP8QuantizeBlock)(int16_t in[16], int16_t out[16], + const struct VP8Matrix* const mtx); +// Same as VP8QuantizeBlock, but quantizes two consecutive blocks. +typedef int (*VP8Quantize2Blocks)(int16_t in[32], int16_t out[32], + const struct VP8Matrix* const mtx); + +extern VP8QuantizeBlock VP8EncQuantizeBlock; +extern VP8Quantize2Blocks VP8EncQuantize2Blocks; + +// specific to 2nd transform: +typedef int (*VP8QuantizeBlockWHT)(int16_t in[16], int16_t out[16], + const struct VP8Matrix* const mtx); +extern VP8QuantizeBlockWHT VP8EncQuantizeBlockWHT; + +extern const int VP8DspScan[16 + 4 + 4]; + +// Collect histogram for susceptibility calculation. +#define MAX_COEFF_THRESH 31 // size of histogram used by CollectHistogram. +typedef struct { + // We only need to store max_value and last_non_zero, not the distribution. + int max_value; + int last_non_zero; +} VP8Histogram; +typedef void (*VP8CHisto)(const uint8_t* ref, const uint8_t* pred, + int start_block, int end_block, + VP8Histogram* const histo); +extern VP8CHisto VP8CollectHistogram; +// General-purpose util function to help VP8CollectHistogram(). +void VP8SetHistogramData(const int distribution[MAX_COEFF_THRESH + 1], + VP8Histogram* const histo); + +// must be called before using any of the above +void VP8EncDspInit(void); + +//------------------------------------------------------------------------------ +// cost functions (encoding) + +extern const uint16_t VP8EntropyCost[256]; // 8bit fixed-point log(p) +// approximate cost per level: +extern const uint16_t VP8LevelFixedCosts[2047 /*MAX_LEVEL*/ + 1]; +extern const uint8_t VP8EncBands[16 + 1]; + +struct VP8Residual; +typedef void (*VP8SetResidualCoeffsFunc)(const int16_t* const coeffs, + struct VP8Residual* const res); +extern VP8SetResidualCoeffsFunc VP8SetResidualCoeffs; + +// Cost calculation function. +typedef int (*VP8GetResidualCostFunc)(int ctx0, + const struct VP8Residual* const res); +extern VP8GetResidualCostFunc VP8GetResidualCost; + +// must be called before anything using the above +void VP8EncDspCostInit(void); + +//------------------------------------------------------------------------------ +// SSIM / PSNR utils + +// struct for accumulating statistical moments +typedef struct { + uint32_t w; // sum(w_i) : sum of weights + uint32_t xm, ym; // sum(w_i * x_i), sum(w_i * y_i) + uint32_t xxm, xym, yym; // sum(w_i * x_i * x_i), etc. +} VP8DistoStats; + +// Compute the final SSIM value +// The non-clipped version assumes stats->w = (2 * VP8_SSIM_KERNEL + 1)^2. +double VP8SSIMFromStats(const VP8DistoStats* const stats); +double VP8SSIMFromStatsClipped(const VP8DistoStats* const stats); + +#define VP8_SSIM_KERNEL 3 // total size of the kernel: 2 * VP8_SSIM_KERNEL + 1 +typedef double (*VP8SSIMGetClippedFunc)(const uint8_t* src1, int stride1, + const uint8_t* src2, int stride2, + int xo, int yo, // center position + int W, int H); // plane dimension + +#if !defined(WEBP_REDUCE_SIZE) +// This version is called with the guarantee that you can load 8 bytes and +// 8 rows at offset src1 and src2 +typedef double (*VP8SSIMGetFunc)(const uint8_t* src1, int stride1, + const uint8_t* src2, int stride2); + +extern VP8SSIMGetFunc VP8SSIMGet; // unclipped / unchecked +extern VP8SSIMGetClippedFunc VP8SSIMGetClipped; // with clipping +#endif + +#if !defined(WEBP_DISABLE_STATS) +typedef uint32_t (*VP8AccumulateSSEFunc)(const uint8_t* src1, + const uint8_t* src2, int len); +extern VP8AccumulateSSEFunc VP8AccumulateSSE; +#endif + +// must be called before using any of the above directly +void VP8SSIMDspInit(void); + +//------------------------------------------------------------------------------ +// Decoding + +typedef void (*VP8DecIdct)(const int16_t* coeffs, uint8_t* dst); +// when doing two transforms, coeffs is actually int16_t[2][16]. +typedef void (*VP8DecIdct2)(const int16_t* coeffs, uint8_t* dst, int do_two); +extern VP8DecIdct2 VP8Transform; +extern VP8DecIdct VP8TransformAC3; +extern VP8DecIdct VP8TransformUV; +extern VP8DecIdct VP8TransformDC; +extern VP8DecIdct VP8TransformDCUV; +extern VP8WHT VP8TransformWHT; + +// *dst is the destination block, with stride BPS. Boundary samples are +// assumed accessible when needed. +typedef void (*VP8PredFunc)(uint8_t* dst); +extern VP8PredFunc VP8PredLuma16[/* NUM_B_DC_MODES */]; +extern VP8PredFunc VP8PredChroma8[/* NUM_B_DC_MODES */]; +extern VP8PredFunc VP8PredLuma4[/* NUM_BMODES */]; + +// clipping tables (for filtering) +extern const int8_t* const VP8ksclip1; // clips [-1020, 1020] to [-128, 127] +extern const int8_t* const VP8ksclip2; // clips [-112, 112] to [-16, 15] +extern const uint8_t* const VP8kclip1; // clips [-255,511] to [0,255] +extern const uint8_t* const VP8kabs0; // abs(x) for x in [-255,255] +// must be called first +void VP8InitClipTables(void); + +// simple filter (only for luma) +typedef void (*VP8SimpleFilterFunc)(uint8_t* p, int stride, int thresh); +extern VP8SimpleFilterFunc VP8SimpleVFilter16; +extern VP8SimpleFilterFunc VP8SimpleHFilter16; +extern VP8SimpleFilterFunc VP8SimpleVFilter16i; // filter 3 inner edges +extern VP8SimpleFilterFunc VP8SimpleHFilter16i; + +// regular filter (on both macroblock edges and inner edges) +typedef void (*VP8LumaFilterFunc)(uint8_t* luma, int stride, + int thresh, int ithresh, int hev_t); +typedef void (*VP8ChromaFilterFunc)(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_t); +// on outer edge +extern VP8LumaFilterFunc VP8VFilter16; +extern VP8LumaFilterFunc VP8HFilter16; +extern VP8ChromaFilterFunc VP8VFilter8; +extern VP8ChromaFilterFunc VP8HFilter8; + +// on inner edge +extern VP8LumaFilterFunc VP8VFilter16i; // filtering 3 inner edges altogether +extern VP8LumaFilterFunc VP8HFilter16i; +extern VP8ChromaFilterFunc VP8VFilter8i; // filtering u and v altogether +extern VP8ChromaFilterFunc VP8HFilter8i; + +// Dithering. Combines dithering values (centered around 128) with dst[], +// according to: dst[] = clip(dst[] + (((dither[]-128) + 8) >> 4) +#define VP8_DITHER_DESCALE 4 +#define VP8_DITHER_DESCALE_ROUNDER (1 << (VP8_DITHER_DESCALE - 1)) +#define VP8_DITHER_AMP_BITS 7 +#define VP8_DITHER_AMP_CENTER (1 << VP8_DITHER_AMP_BITS) +extern void (*VP8DitherCombine8x8)(const uint8_t* dither, uint8_t* dst, + int dst_stride); + +// must be called before anything using the above +void VP8DspInit(void); + +//------------------------------------------------------------------------------ +// WebP I/O + +#define FANCY_UPSAMPLING // undefined to remove fancy upsampling support + +// Convert a pair of y/u/v lines together to the output rgb/a colorspace. +// bottom_y can be NULL if only one line of output is needed (at top/bottom). +typedef void (*WebPUpsampleLinePairFunc)( + const uint8_t* top_y, const uint8_t* bottom_y, + const uint8_t* top_u, const uint8_t* top_v, + const uint8_t* cur_u, const uint8_t* cur_v, + uint8_t* top_dst, uint8_t* bottom_dst, int len); + +#ifdef FANCY_UPSAMPLING + +// Fancy upsampling functions to convert YUV to RGB(A) modes +extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */]; + +#endif // FANCY_UPSAMPLING + +// Per-row point-sampling methods. +typedef void (*WebPSamplerRowFunc)(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len); +// Generic function to apply 'WebPSamplerRowFunc' to the whole plane: +void WebPSamplerProcessPlane(const uint8_t* y, int y_stride, + const uint8_t* u, const uint8_t* v, int uv_stride, + uint8_t* dst, int dst_stride, + int width, int height, WebPSamplerRowFunc func); + +// Sampling functions to convert rows of YUV to RGB(A) +extern WebPSamplerRowFunc WebPSamplers[/* MODE_LAST */]; + +// General function for converting two lines of ARGB or RGBA. +// 'alpha_is_last' should be true if 0xff000000 is stored in memory as +// as 0x00, 0x00, 0x00, 0xff (little endian). +WebPUpsampleLinePairFunc WebPGetLinePairConverter(int alpha_is_last); + +// YUV444->RGB converters +typedef void (*WebPYUV444Converter)(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len); + +extern WebPYUV444Converter WebPYUV444Converters[/* MODE_LAST */]; + +// Must be called before using the WebPUpsamplers[] (and for premultiplied +// colorspaces like rgbA, rgbA4444, etc) +void WebPInitUpsamplers(void); +// Must be called before using WebPSamplers[] +void WebPInitSamplers(void); +// Must be called before using WebPYUV444Converters[] +void WebPInitYUV444Converters(void); + +//------------------------------------------------------------------------------ +// ARGB -> YUV converters + +// Convert ARGB samples to luma Y. +extern void (*WebPConvertARGBToY)(const uint32_t* argb, uint8_t* y, int width); +// Convert ARGB samples to U/V with downsampling. do_store should be '1' for +// even lines and '0' for odd ones. 'src_width' is the original width, not +// the U/V one. +extern void (*WebPConvertARGBToUV)(const uint32_t* argb, uint8_t* u, uint8_t* v, + int src_width, int do_store); + +// Convert a row of accumulated (four-values) of rgba32 toward U/V +extern void (*WebPConvertRGBA32ToUV)(const uint16_t* rgb, + uint8_t* u, uint8_t* v, int width); + +// Convert RGB or BGR to Y +extern void (*WebPConvertRGB24ToY)(const uint8_t* rgb, uint8_t* y, int width); +extern void (*WebPConvertBGR24ToY)(const uint8_t* bgr, uint8_t* y, int width); + +// used for plain-C fallback. +extern void WebPConvertARGBToUV_C(const uint32_t* argb, uint8_t* u, uint8_t* v, + int src_width, int do_store); +extern void WebPConvertRGBA32ToUV_C(const uint16_t* rgb, + uint8_t* u, uint8_t* v, int width); + +// Must be called before using the above. +void WebPInitConvertARGBToYUV(void); + +//------------------------------------------------------------------------------ +// Rescaler + +struct WebPRescaler; + +// Import a row of data and save its contribution in the rescaler. +// 'channel' denotes the channel number to be imported. 'Expand' corresponds to +// the wrk->x_expand case. Otherwise, 'Shrink' is to be used. +typedef void (*WebPRescalerImportRowFunc)(struct WebPRescaler* const wrk, + const uint8_t* src); + +extern WebPRescalerImportRowFunc WebPRescalerImportRowExpand; +extern WebPRescalerImportRowFunc WebPRescalerImportRowShrink; + +// Export one row (starting at x_out position) from rescaler. +// 'Expand' corresponds to the wrk->y_expand case. +// Otherwise 'Shrink' is to be used +typedef void (*WebPRescalerExportRowFunc)(struct WebPRescaler* const wrk); +extern WebPRescalerExportRowFunc WebPRescalerExportRowExpand; +extern WebPRescalerExportRowFunc WebPRescalerExportRowShrink; + +// Plain-C implementation, as fall-back. +extern void WebPRescalerImportRowExpand_C(struct WebPRescaler* const wrk, + const uint8_t* src); +extern void WebPRescalerImportRowShrink_C(struct WebPRescaler* const wrk, + const uint8_t* src); +extern void WebPRescalerExportRowExpand_C(struct WebPRescaler* const wrk); +extern void WebPRescalerExportRowShrink_C(struct WebPRescaler* const wrk); + +// Main entry calls: +extern void WebPRescalerImportRow(struct WebPRescaler* const wrk, + const uint8_t* src); +// Export one row (starting at x_out position) from rescaler. +extern void WebPRescalerExportRow(struct WebPRescaler* const wrk); + +// Must be called first before using the above. +void WebPRescalerDspInit(void); + +//------------------------------------------------------------------------------ +// Utilities for processing transparent channel. + +// Apply alpha pre-multiply on an rgba, bgra or argb plane of size w * h. +// alpha_first should be 0 for argb, 1 for rgba or bgra (where alpha is last). +extern void (*WebPApplyAlphaMultiply)( + uint8_t* rgba, int alpha_first, int w, int h, int stride); + +// Same, buf specifically for RGBA4444 format +extern void (*WebPApplyAlphaMultiply4444)( + uint8_t* rgba4444, int w, int h, int stride); + +// Dispatch the values from alpha[] plane to the ARGB destination 'dst'. +// Returns true if alpha[] plane has non-trivial values different from 0xff. +extern int (*WebPDispatchAlpha)(const uint8_t* WEBP_RESTRICT alpha, + int alpha_stride, int width, int height, + uint8_t* WEBP_RESTRICT dst, int dst_stride); + +// Transfer packed 8b alpha[] values to green channel in dst[], zero'ing the +// A/R/B values. 'dst_stride' is the stride for dst[] in uint32_t units. +extern void (*WebPDispatchAlphaToGreen)(const uint8_t* WEBP_RESTRICT alpha, + int alpha_stride, int width, int height, + uint32_t* WEBP_RESTRICT dst, + int dst_stride); + +// Extract the alpha values from 32b values in argb[] and pack them into alpha[] +// (this is the opposite of WebPDispatchAlpha). +// Returns true if there's only trivial 0xff alpha values. +extern int (*WebPExtractAlpha)(const uint8_t* WEBP_RESTRICT argb, + int argb_stride, int width, int height, + uint8_t* WEBP_RESTRICT alpha, + int alpha_stride); + +// Extract the green values from 32b values in argb[] and pack them into alpha[] +// (this is the opposite of WebPDispatchAlphaToGreen). +extern void (*WebPExtractGreen)(const uint32_t* WEBP_RESTRICT argb, + uint8_t* WEBP_RESTRICT alpha, int size); + +// Pre-Multiply operation transforms x into x * A / 255 (where x=Y,R,G or B). +// Un-Multiply operation transforms x into x * 255 / A. + +// Pre-Multiply or Un-Multiply (if 'inverse' is true) argb values in a row. +extern void (*WebPMultARGBRow)(uint32_t* const ptr, int width, int inverse); + +// Same a WebPMultARGBRow(), but for several rows. +void WebPMultARGBRows(uint8_t* ptr, int stride, int width, int num_rows, + int inverse); + +// Same for a row of single values, with side alpha values. +extern void (*WebPMultRow)(uint8_t* WEBP_RESTRICT const ptr, + const uint8_t* WEBP_RESTRICT const alpha, + int width, int inverse); + +// Same a WebPMultRow(), but for several 'num_rows' rows. +void WebPMultRows(uint8_t* WEBP_RESTRICT ptr, int stride, + const uint8_t* WEBP_RESTRICT alpha, int alpha_stride, + int width, int num_rows, int inverse); + +// Plain-C versions, used as fallback by some implementations. +void WebPMultRow_C(uint8_t* WEBP_RESTRICT const ptr, + const uint8_t* WEBP_RESTRICT const alpha, + int width, int inverse); +void WebPMultARGBRow_C(uint32_t* const ptr, int width, int inverse); + +#ifdef WORDS_BIGENDIAN +// ARGB packing function: a/r/g/b input is rgba or bgra order. +extern void (*WebPPackARGB)(const uint8_t* WEBP_RESTRICT a, + const uint8_t* WEBP_RESTRICT r, + const uint8_t* WEBP_RESTRICT g, + const uint8_t* WEBP_RESTRICT b, + int len, uint32_t* WEBP_RESTRICT out); +#endif + +// RGB packing function. 'step' can be 3 or 4. r/g/b input is rgb or bgr order. +extern void (*WebPPackRGB)(const uint8_t* WEBP_RESTRICT r, + const uint8_t* WEBP_RESTRICT g, + const uint8_t* WEBP_RESTRICT b, + int len, int step, uint32_t* WEBP_RESTRICT out); + +// This function returns true if src[i] contains a value different from 0xff. +extern int (*WebPHasAlpha8b)(const uint8_t* src, int length); +// This function returns true if src[4*i] contains a value different from 0xff. +extern int (*WebPHasAlpha32b)(const uint8_t* src, int length); +// replaces transparent values in src[] by 'color'. +extern void (*WebPAlphaReplace)(uint32_t* src, int length, uint32_t color); + +// To be called first before using the above. +void WebPInitAlphaProcessing(void); + +//------------------------------------------------------------------------------ +// Filter functions + +typedef enum { // Filter types. + WEBP_FILTER_NONE = 0, + WEBP_FILTER_HORIZONTAL, + WEBP_FILTER_VERTICAL, + WEBP_FILTER_GRADIENT, + WEBP_FILTER_LAST = WEBP_FILTER_GRADIENT + 1, // end marker + WEBP_FILTER_BEST, // meta-types + WEBP_FILTER_FAST +} WEBP_FILTER_TYPE; + +typedef void (*WebPFilterFunc)(const uint8_t* in, int width, int height, + int stride, uint8_t* out); +// In-place un-filtering. +// Warning! 'prev_line' pointer can be equal to 'cur_line' or 'preds'. +typedef void (*WebPUnfilterFunc)(const uint8_t* prev_line, const uint8_t* preds, + uint8_t* cur_line, int width); + +// Filter the given data using the given predictor. +// 'in' corresponds to a 2-dimensional pixel array of size (stride * height) +// in raster order. +// 'stride' is number of bytes per scan line (with possible padding). +// 'out' should be pre-allocated. +extern WebPFilterFunc WebPFilters[WEBP_FILTER_LAST]; + +// In-place reconstruct the original data from the given filtered data. +// The reconstruction will be done for 'num_rows' rows starting from 'row' +// (assuming rows upto 'row - 1' are already reconstructed). +extern WebPUnfilterFunc WebPUnfilters[WEBP_FILTER_LAST]; + +// To be called first before using the above. +void VP8FiltersInit(void); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_DSP_DSP_H_ diff --git a/third-party/webp/libwebp/src/dsp/enc.c b/third-party/webp/libwebp/src/dsp/enc.c new file mode 100644 index 0000000000..2ba97ba8d6 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/enc.c @@ -0,0 +1,831 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Speed-critical encoding functions. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include // for abs() + +#include "src/dsp/dsp.h" +#include "src/enc/vp8i_enc.h" + +static WEBP_INLINE uint8_t clip_8b(int v) { + return (!(v & ~0xff)) ? v : (v < 0) ? 0 : 255; +} + +#if !WEBP_NEON_OMIT_C_CODE +static WEBP_INLINE int clip_max(int v, int max) { + return (v > max) ? max : v; +} +#endif // !WEBP_NEON_OMIT_C_CODE + +//------------------------------------------------------------------------------ +// Compute susceptibility based on DCT-coeff histograms: +// the higher, the "easier" the macroblock is to compress. + +const int VP8DspScan[16 + 4 + 4] = { + // Luma + 0 + 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS, + 0 + 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS, + 0 + 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS, + 0 + 12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS, + + 0 + 0 * BPS, 4 + 0 * BPS, 0 + 4 * BPS, 4 + 4 * BPS, // U + 8 + 0 * BPS, 12 + 0 * BPS, 8 + 4 * BPS, 12 + 4 * BPS // V +}; + +// general-purpose util function +void VP8SetHistogramData(const int distribution[MAX_COEFF_THRESH + 1], + VP8Histogram* const histo) { + int max_value = 0, last_non_zero = 1; + int k; + for (k = 0; k <= MAX_COEFF_THRESH; ++k) { + const int value = distribution[k]; + if (value > 0) { + if (value > max_value) max_value = value; + last_non_zero = k; + } + } + histo->max_value = max_value; + histo->last_non_zero = last_non_zero; +} + +#if !WEBP_NEON_OMIT_C_CODE +static void CollectHistogram_C(const uint8_t* ref, const uint8_t* pred, + int start_block, int end_block, + VP8Histogram* const histo) { + int j; + int distribution[MAX_COEFF_THRESH + 1] = { 0 }; + for (j = start_block; j < end_block; ++j) { + int k; + int16_t out[16]; + + VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out); + + // Convert coefficients to bin. + for (k = 0; k < 16; ++k) { + const int v = abs(out[k]) >> 3; + const int clipped_value = clip_max(v, MAX_COEFF_THRESH); + ++distribution[clipped_value]; + } + } + VP8SetHistogramData(distribution, histo); +} +#endif // !WEBP_NEON_OMIT_C_CODE + +//------------------------------------------------------------------------------ +// run-time tables (~4k) + +static uint8_t clip1[255 + 510 + 1]; // clips [-255,510] to [0,255] + +// We declare this variable 'volatile' to prevent instruction reordering +// and make sure it's set to true _last_ (so as to be thread-safe) +static volatile int tables_ok = 0; + +static WEBP_TSAN_IGNORE_FUNCTION void InitTables(void) { + if (!tables_ok) { + int i; + for (i = -255; i <= 255 + 255; ++i) { + clip1[255 + i] = clip_8b(i); + } + tables_ok = 1; + } +} + + +//------------------------------------------------------------------------------ +// Transforms (Paragraph 14.4) + +#if !WEBP_NEON_OMIT_C_CODE + +#define STORE(x, y, v) \ + dst[(x) + (y) * BPS] = clip_8b(ref[(x) + (y) * BPS] + ((v) >> 3)) + +static const int kC1 = 20091 + (1 << 16); +static const int kC2 = 35468; +#define MUL(a, b) (((a) * (b)) >> 16) + +static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in, + uint8_t* dst) { + int C[4 * 4], *tmp; + int i; + tmp = C; + for (i = 0; i < 4; ++i) { // vertical pass + const int a = in[0] + in[8]; + const int b = in[0] - in[8]; + const int c = MUL(in[4], kC2) - MUL(in[12], kC1); + const int d = MUL(in[4], kC1) + MUL(in[12], kC2); + tmp[0] = a + d; + tmp[1] = b + c; + tmp[2] = b - c; + tmp[3] = a - d; + tmp += 4; + in++; + } + + tmp = C; + for (i = 0; i < 4; ++i) { // horizontal pass + const int dc = tmp[0] + 4; + const int a = dc + tmp[8]; + const int b = dc - tmp[8]; + const int c = MUL(tmp[4], kC2) - MUL(tmp[12], kC1); + const int d = MUL(tmp[4], kC1) + MUL(tmp[12], kC2); + STORE(0, i, a + d); + STORE(1, i, b + c); + STORE(2, i, b - c); + STORE(3, i, a - d); + tmp++; + } +} + +static void ITransform_C(const uint8_t* ref, const int16_t* in, uint8_t* dst, + int do_two) { + ITransformOne(ref, in, dst); + if (do_two) { + ITransformOne(ref + 4, in + 16, dst + 4); + } +} + +static void FTransform_C(const uint8_t* src, const uint8_t* ref, int16_t* out) { + int i; + int tmp[16]; + for (i = 0; i < 4; ++i, src += BPS, ref += BPS) { + const int d0 = src[0] - ref[0]; // 9bit dynamic range ([-255,255]) + const int d1 = src[1] - ref[1]; + const int d2 = src[2] - ref[2]; + const int d3 = src[3] - ref[3]; + const int a0 = (d0 + d3); // 10b [-510,510] + const int a1 = (d1 + d2); + const int a2 = (d1 - d2); + const int a3 = (d0 - d3); + tmp[0 + i * 4] = (a0 + a1) * 8; // 14b [-8160,8160] + tmp[1 + i * 4] = (a2 * 2217 + a3 * 5352 + 1812) >> 9; // [-7536,7542] + tmp[2 + i * 4] = (a0 - a1) * 8; + tmp[3 + i * 4] = (a3 * 2217 - a2 * 5352 + 937) >> 9; + } + for (i = 0; i < 4; ++i) { + const int a0 = (tmp[0 + i] + tmp[12 + i]); // 15b + const int a1 = (tmp[4 + i] + tmp[ 8 + i]); + const int a2 = (tmp[4 + i] - tmp[ 8 + i]); + const int a3 = (tmp[0 + i] - tmp[12 + i]); + out[0 + i] = (a0 + a1 + 7) >> 4; // 12b + out[4 + i] = ((a2 * 2217 + a3 * 5352 + 12000) >> 16) + (a3 != 0); + out[8 + i] = (a0 - a1 + 7) >> 4; + out[12+ i] = ((a3 * 2217 - a2 * 5352 + 51000) >> 16); + } +} +#endif // !WEBP_NEON_OMIT_C_CODE + +static void FTransform2_C(const uint8_t* src, const uint8_t* ref, + int16_t* out) { + VP8FTransform(src, ref, out); + VP8FTransform(src + 4, ref + 4, out + 16); +} + +#if !WEBP_NEON_OMIT_C_CODE +static void FTransformWHT_C(const int16_t* in, int16_t* out) { + // input is 12b signed + int32_t tmp[16]; + int i; + for (i = 0; i < 4; ++i, in += 64) { + const int a0 = (in[0 * 16] + in[2 * 16]); // 13b + const int a1 = (in[1 * 16] + in[3 * 16]); + const int a2 = (in[1 * 16] - in[3 * 16]); + const int a3 = (in[0 * 16] - in[2 * 16]); + tmp[0 + i * 4] = a0 + a1; // 14b + tmp[1 + i * 4] = a3 + a2; + tmp[2 + i * 4] = a3 - a2; + tmp[3 + i * 4] = a0 - a1; + } + for (i = 0; i < 4; ++i) { + const int a0 = (tmp[0 + i] + tmp[8 + i]); // 15b + const int a1 = (tmp[4 + i] + tmp[12+ i]); + const int a2 = (tmp[4 + i] - tmp[12+ i]); + const int a3 = (tmp[0 + i] - tmp[8 + i]); + const int b0 = a0 + a1; // 16b + const int b1 = a3 + a2; + const int b2 = a3 - a2; + const int b3 = a0 - a1; + out[ 0 + i] = b0 >> 1; // 15b + out[ 4 + i] = b1 >> 1; + out[ 8 + i] = b2 >> 1; + out[12 + i] = b3 >> 1; + } +} +#endif // !WEBP_NEON_OMIT_C_CODE + +#undef MUL +#undef STORE + +//------------------------------------------------------------------------------ +// Intra predictions + +static WEBP_INLINE void Fill(uint8_t* dst, int value, int size) { + int j; + for (j = 0; j < size; ++j) { + memset(dst + j * BPS, value, size); + } +} + +static WEBP_INLINE void VerticalPred(uint8_t* dst, + const uint8_t* top, int size) { + int j; + if (top != NULL) { + for (j = 0; j < size; ++j) memcpy(dst + j * BPS, top, size); + } else { + Fill(dst, 127, size); + } +} + +static WEBP_INLINE void HorizontalPred(uint8_t* dst, + const uint8_t* left, int size) { + if (left != NULL) { + int j; + for (j = 0; j < size; ++j) { + memset(dst + j * BPS, left[j], size); + } + } else { + Fill(dst, 129, size); + } +} + +static WEBP_INLINE void TrueMotion(uint8_t* dst, const uint8_t* left, + const uint8_t* top, int size) { + int y; + if (left != NULL) { + if (top != NULL) { + const uint8_t* const clip = clip1 + 255 - left[-1]; + for (y = 0; y < size; ++y) { + const uint8_t* const clip_table = clip + left[y]; + int x; + for (x = 0; x < size; ++x) { + dst[x] = clip_table[top[x]]; + } + dst += BPS; + } + } else { + HorizontalPred(dst, left, size); + } + } else { + // true motion without left samples (hence: with default 129 value) + // is equivalent to VE prediction where you just copy the top samples. + // Note that if top samples are not available, the default value is + // then 129, and not 127 as in the VerticalPred case. + if (top != NULL) { + VerticalPred(dst, top, size); + } else { + Fill(dst, 129, size); + } + } +} + +static WEBP_INLINE void DCMode(uint8_t* dst, const uint8_t* left, + const uint8_t* top, + int size, int round, int shift) { + int DC = 0; + int j; + if (top != NULL) { + for (j = 0; j < size; ++j) DC += top[j]; + if (left != NULL) { // top and left present + for (j = 0; j < size; ++j) DC += left[j]; + } else { // top, but no left + DC += DC; + } + DC = (DC + round) >> shift; + } else if (left != NULL) { // left but no top + for (j = 0; j < size; ++j) DC += left[j]; + DC += DC; + DC = (DC + round) >> shift; + } else { // no top, no left, nothing. + DC = 0x80; + } + Fill(dst, DC, size); +} + +//------------------------------------------------------------------------------ +// Chroma 8x8 prediction (paragraph 12.2) + +static void IntraChromaPreds_C(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { + // U block + DCMode(C8DC8 + dst, left, top, 8, 8, 4); + VerticalPred(C8VE8 + dst, top, 8); + HorizontalPred(C8HE8 + dst, left, 8); + TrueMotion(C8TM8 + dst, left, top, 8); + // V block + dst += 8; + if (top != NULL) top += 8; + if (left != NULL) left += 16; + DCMode(C8DC8 + dst, left, top, 8, 8, 4); + VerticalPred(C8VE8 + dst, top, 8); + HorizontalPred(C8HE8 + dst, left, 8); + TrueMotion(C8TM8 + dst, left, top, 8); +} + +//------------------------------------------------------------------------------ +// luma 16x16 prediction (paragraph 12.3) + +static void Intra16Preds_C(uint8_t* dst, + const uint8_t* left, const uint8_t* top) { + DCMode(I16DC16 + dst, left, top, 16, 16, 5); + VerticalPred(I16VE16 + dst, top, 16); + HorizontalPred(I16HE16 + dst, left, 16); + TrueMotion(I16TM16 + dst, left, top, 16); +} + +//------------------------------------------------------------------------------ +// luma 4x4 prediction + +#define DST(x, y) dst[(x) + (y) * BPS] +#define AVG3(a, b, c) ((uint8_t)(((a) + 2 * (b) + (c) + 2) >> 2)) +#define AVG2(a, b) (((a) + (b) + 1) >> 1) + +static void VE4(uint8_t* dst, const uint8_t* top) { // vertical + const uint8_t vals[4] = { + AVG3(top[-1], top[0], top[1]), + AVG3(top[ 0], top[1], top[2]), + AVG3(top[ 1], top[2], top[3]), + AVG3(top[ 2], top[3], top[4]) + }; + int i; + for (i = 0; i < 4; ++i) { + memcpy(dst + i * BPS, vals, 4); + } +} + +static void HE4(uint8_t* dst, const uint8_t* top) { // horizontal + const int X = top[-1]; + const int I = top[-2]; + const int J = top[-3]; + const int K = top[-4]; + const int L = top[-5]; + WebPUint32ToMem(dst + 0 * BPS, 0x01010101U * AVG3(X, I, J)); + WebPUint32ToMem(dst + 1 * BPS, 0x01010101U * AVG3(I, J, K)); + WebPUint32ToMem(dst + 2 * BPS, 0x01010101U * AVG3(J, K, L)); + WebPUint32ToMem(dst + 3 * BPS, 0x01010101U * AVG3(K, L, L)); +} + +static void DC4(uint8_t* dst, const uint8_t* top) { + uint32_t dc = 4; + int i; + for (i = 0; i < 4; ++i) dc += top[i] + top[-5 + i]; + Fill(dst, dc >> 3, 4); +} + +static void RD4(uint8_t* dst, const uint8_t* top) { + const int X = top[-1]; + const int I = top[-2]; + const int J = top[-3]; + const int K = top[-4]; + const int L = top[-5]; + const int A = top[0]; + const int B = top[1]; + const int C = top[2]; + const int D = top[3]; + DST(0, 3) = AVG3(J, K, L); + DST(0, 2) = DST(1, 3) = AVG3(I, J, K); + DST(0, 1) = DST(1, 2) = DST(2, 3) = AVG3(X, I, J); + DST(0, 0) = DST(1, 1) = DST(2, 2) = DST(3, 3) = AVG3(A, X, I); + DST(1, 0) = DST(2, 1) = DST(3, 2) = AVG3(B, A, X); + DST(2, 0) = DST(3, 1) = AVG3(C, B, A); + DST(3, 0) = AVG3(D, C, B); +} + +static void LD4(uint8_t* dst, const uint8_t* top) { + const int A = top[0]; + const int B = top[1]; + const int C = top[2]; + const int D = top[3]; + const int E = top[4]; + const int F = top[5]; + const int G = top[6]; + const int H = top[7]; + DST(0, 0) = AVG3(A, B, C); + DST(1, 0) = DST(0, 1) = AVG3(B, C, D); + DST(2, 0) = DST(1, 1) = DST(0, 2) = AVG3(C, D, E); + DST(3, 0) = DST(2, 1) = DST(1, 2) = DST(0, 3) = AVG3(D, E, F); + DST(3, 1) = DST(2, 2) = DST(1, 3) = AVG3(E, F, G); + DST(3, 2) = DST(2, 3) = AVG3(F, G, H); + DST(3, 3) = AVG3(G, H, H); +} + +static void VR4(uint8_t* dst, const uint8_t* top) { + const int X = top[-1]; + const int I = top[-2]; + const int J = top[-3]; + const int K = top[-4]; + const int A = top[0]; + const int B = top[1]; + const int C = top[2]; + const int D = top[3]; + DST(0, 0) = DST(1, 2) = AVG2(X, A); + DST(1, 0) = DST(2, 2) = AVG2(A, B); + DST(2, 0) = DST(3, 2) = AVG2(B, C); + DST(3, 0) = AVG2(C, D); + + DST(0, 3) = AVG3(K, J, I); + DST(0, 2) = AVG3(J, I, X); + DST(0, 1) = DST(1, 3) = AVG3(I, X, A); + DST(1, 1) = DST(2, 3) = AVG3(X, A, B); + DST(2, 1) = DST(3, 3) = AVG3(A, B, C); + DST(3, 1) = AVG3(B, C, D); +} + +static void VL4(uint8_t* dst, const uint8_t* top) { + const int A = top[0]; + const int B = top[1]; + const int C = top[2]; + const int D = top[3]; + const int E = top[4]; + const int F = top[5]; + const int G = top[6]; + const int H = top[7]; + DST(0, 0) = AVG2(A, B); + DST(1, 0) = DST(0, 2) = AVG2(B, C); + DST(2, 0) = DST(1, 2) = AVG2(C, D); + DST(3, 0) = DST(2, 2) = AVG2(D, E); + + DST(0, 1) = AVG3(A, B, C); + DST(1, 1) = DST(0, 3) = AVG3(B, C, D); + DST(2, 1) = DST(1, 3) = AVG3(C, D, E); + DST(3, 1) = DST(2, 3) = AVG3(D, E, F); + DST(3, 2) = AVG3(E, F, G); + DST(3, 3) = AVG3(F, G, H); +} + +static void HU4(uint8_t* dst, const uint8_t* top) { + const int I = top[-2]; + const int J = top[-3]; + const int K = top[-4]; + const int L = top[-5]; + DST(0, 0) = AVG2(I, J); + DST(2, 0) = DST(0, 1) = AVG2(J, K); + DST(2, 1) = DST(0, 2) = AVG2(K, L); + DST(1, 0) = AVG3(I, J, K); + DST(3, 0) = DST(1, 1) = AVG3(J, K, L); + DST(3, 1) = DST(1, 2) = AVG3(K, L, L); + DST(3, 2) = DST(2, 2) = + DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L; +} + +static void HD4(uint8_t* dst, const uint8_t* top) { + const int X = top[-1]; + const int I = top[-2]; + const int J = top[-3]; + const int K = top[-4]; + const int L = top[-5]; + const int A = top[0]; + const int B = top[1]; + const int C = top[2]; + + DST(0, 0) = DST(2, 1) = AVG2(I, X); + DST(0, 1) = DST(2, 2) = AVG2(J, I); + DST(0, 2) = DST(2, 3) = AVG2(K, J); + DST(0, 3) = AVG2(L, K); + + DST(3, 0) = AVG3(A, B, C); + DST(2, 0) = AVG3(X, A, B); + DST(1, 0) = DST(3, 1) = AVG3(I, X, A); + DST(1, 1) = DST(3, 2) = AVG3(J, I, X); + DST(1, 2) = DST(3, 3) = AVG3(K, J, I); + DST(1, 3) = AVG3(L, K, J); +} + +static void TM4(uint8_t* dst, const uint8_t* top) { + int x, y; + const uint8_t* const clip = clip1 + 255 - top[-1]; + for (y = 0; y < 4; ++y) { + const uint8_t* const clip_table = clip + top[-2 - y]; + for (x = 0; x < 4; ++x) { + dst[x] = clip_table[top[x]]; + } + dst += BPS; + } +} + +#undef DST +#undef AVG3 +#undef AVG2 + +// Left samples are top[-5 .. -2], top_left is top[-1], top are +// located at top[0..3], and top right is top[4..7] +static void Intra4Preds_C(uint8_t* dst, const uint8_t* top) { + DC4(I4DC4 + dst, top); + TM4(I4TM4 + dst, top); + VE4(I4VE4 + dst, top); + HE4(I4HE4 + dst, top); + RD4(I4RD4 + dst, top); + VR4(I4VR4 + dst, top); + LD4(I4LD4 + dst, top); + VL4(I4VL4 + dst, top); + HD4(I4HD4 + dst, top); + HU4(I4HU4 + dst, top); +} + +//------------------------------------------------------------------------------ +// Metric + +#if !WEBP_NEON_OMIT_C_CODE +static WEBP_INLINE int GetSSE(const uint8_t* a, const uint8_t* b, + int w, int h) { + int count = 0; + int y, x; + for (y = 0; y < h; ++y) { + for (x = 0; x < w; ++x) { + const int diff = (int)a[x] - b[x]; + count += diff * diff; + } + a += BPS; + b += BPS; + } + return count; +} + +static int SSE16x16_C(const uint8_t* a, const uint8_t* b) { + return GetSSE(a, b, 16, 16); +} +static int SSE16x8_C(const uint8_t* a, const uint8_t* b) { + return GetSSE(a, b, 16, 8); +} +static int SSE8x8_C(const uint8_t* a, const uint8_t* b) { + return GetSSE(a, b, 8, 8); +} +static int SSE4x4_C(const uint8_t* a, const uint8_t* b) { + return GetSSE(a, b, 4, 4); +} +#endif // !WEBP_NEON_OMIT_C_CODE + +static void Mean16x4_C(const uint8_t* ref, uint32_t dc[4]) { + int k, x, y; + for (k = 0; k < 4; ++k) { + uint32_t avg = 0; + for (y = 0; y < 4; ++y) { + for (x = 0; x < 4; ++x) { + avg += ref[x + y * BPS]; + } + } + dc[k] = avg; + ref += 4; // go to next 4x4 block. + } +} + +//------------------------------------------------------------------------------ +// Texture distortion +// +// We try to match the spectral content (weighted) between source and +// reconstructed samples. + +#if !WEBP_NEON_OMIT_C_CODE +// Hadamard transform +// Returns the weighted sum of the absolute value of transformed coefficients. +// w[] contains a row-major 4 by 4 symmetric matrix. +static int TTransform(const uint8_t* in, const uint16_t* w) { + int sum = 0; + int tmp[16]; + int i; + // horizontal pass + for (i = 0; i < 4; ++i, in += BPS) { + const int a0 = in[0] + in[2]; + const int a1 = in[1] + in[3]; + const int a2 = in[1] - in[3]; + const int a3 = in[0] - in[2]; + tmp[0 + i * 4] = a0 + a1; + tmp[1 + i * 4] = a3 + a2; + tmp[2 + i * 4] = a3 - a2; + tmp[3 + i * 4] = a0 - a1; + } + // vertical pass + for (i = 0; i < 4; ++i, ++w) { + const int a0 = tmp[0 + i] + tmp[8 + i]; + const int a1 = tmp[4 + i] + tmp[12+ i]; + const int a2 = tmp[4 + i] - tmp[12+ i]; + const int a3 = tmp[0 + i] - tmp[8 + i]; + const int b0 = a0 + a1; + const int b1 = a3 + a2; + const int b2 = a3 - a2; + const int b3 = a0 - a1; + + sum += w[ 0] * abs(b0); + sum += w[ 4] * abs(b1); + sum += w[ 8] * abs(b2); + sum += w[12] * abs(b3); + } + return sum; +} + +static int Disto4x4_C(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + const int sum1 = TTransform(a, w); + const int sum2 = TTransform(b, w); + return abs(sum2 - sum1) >> 5; +} + +static int Disto16x16_C(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + int D = 0; + int x, y; + for (y = 0; y < 16 * BPS; y += 4 * BPS) { + for (x = 0; x < 16; x += 4) { + D += Disto4x4_C(a + x + y, b + x + y, w); + } + } + return D; +} +#endif // !WEBP_NEON_OMIT_C_CODE + +//------------------------------------------------------------------------------ +// Quantization +// + +static const uint8_t kZigzag[16] = { + 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15 +}; + +// Simple quantization +static int QuantizeBlock_C(int16_t in[16], int16_t out[16], + const VP8Matrix* const mtx) { + int last = -1; + int n; + for (n = 0; n < 16; ++n) { + const int j = kZigzag[n]; + const int sign = (in[j] < 0); + const uint32_t coeff = (sign ? -in[j] : in[j]) + mtx->sharpen_[j]; + if (coeff > mtx->zthresh_[j]) { + const uint32_t Q = mtx->q_[j]; + const uint32_t iQ = mtx->iq_[j]; + const uint32_t B = mtx->bias_[j]; + int level = QUANTDIV(coeff, iQ, B); + if (level > MAX_LEVEL) level = MAX_LEVEL; + if (sign) level = -level; + in[j] = level * (int)Q; + out[n] = level; + if (level) last = n; + } else { + out[n] = 0; + in[j] = 0; + } + } + return (last >= 0); +} + +#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC +static int Quantize2Blocks_C(int16_t in[32], int16_t out[32], + const VP8Matrix* const mtx) { + int nz; + nz = VP8EncQuantizeBlock(in + 0 * 16, out + 0 * 16, mtx) << 0; + nz |= VP8EncQuantizeBlock(in + 1 * 16, out + 1 * 16, mtx) << 1; + return nz; +} +#endif // !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC + +//------------------------------------------------------------------------------ +// Block copy + +static WEBP_INLINE void Copy(const uint8_t* src, uint8_t* dst, int w, int h) { + int y; + for (y = 0; y < h; ++y) { + memcpy(dst, src, w); + src += BPS; + dst += BPS; + } +} + +static void Copy4x4_C(const uint8_t* src, uint8_t* dst) { + Copy(src, dst, 4, 4); +} + +static void Copy16x8_C(const uint8_t* src, uint8_t* dst) { + Copy(src, dst, 16, 8); +} + +//------------------------------------------------------------------------------ +// Initialization + +// Speed-critical function pointers. We have to initialize them to the default +// implementations within VP8EncDspInit(). +VP8CHisto VP8CollectHistogram; +VP8Idct VP8ITransform; +VP8Fdct VP8FTransform; +VP8Fdct VP8FTransform2; +VP8WHT VP8FTransformWHT; +VP8Intra4Preds VP8EncPredLuma4; +VP8IntraPreds VP8EncPredLuma16; +VP8IntraPreds VP8EncPredChroma8; +VP8Metric VP8SSE16x16; +VP8Metric VP8SSE8x8; +VP8Metric VP8SSE16x8; +VP8Metric VP8SSE4x4; +VP8WMetric VP8TDisto4x4; +VP8WMetric VP8TDisto16x16; +VP8MeanMetric VP8Mean16x4; +VP8QuantizeBlock VP8EncQuantizeBlock; +VP8Quantize2Blocks VP8EncQuantize2Blocks; +VP8QuantizeBlockWHT VP8EncQuantizeBlockWHT; +VP8BlockCopy VP8Copy4x4; +VP8BlockCopy VP8Copy16x8; + +extern VP8CPUInfo VP8GetCPUInfo; +extern void VP8EncDspInitSSE2(void); +extern void VP8EncDspInitSSE41(void); +extern void VP8EncDspInitNEON(void); +extern void VP8EncDspInitMIPS32(void); +extern void VP8EncDspInitMIPSdspR2(void); +extern void VP8EncDspInitMSA(void); + +WEBP_DSP_INIT_FUNC(VP8EncDspInit) { + VP8DspInit(); // common inverse transforms + InitTables(); + + // default C implementations +#if !WEBP_NEON_OMIT_C_CODE + VP8ITransform = ITransform_C; + VP8FTransform = FTransform_C; + VP8FTransformWHT = FTransformWHT_C; + VP8TDisto4x4 = Disto4x4_C; + VP8TDisto16x16 = Disto16x16_C; + VP8CollectHistogram = CollectHistogram_C; + VP8SSE16x16 = SSE16x16_C; + VP8SSE16x8 = SSE16x8_C; + VP8SSE8x8 = SSE8x8_C; + VP8SSE4x4 = SSE4x4_C; +#endif + +#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC + VP8EncQuantizeBlock = QuantizeBlock_C; + VP8EncQuantize2Blocks = Quantize2Blocks_C; +#endif + + VP8FTransform2 = FTransform2_C; + VP8EncPredLuma4 = Intra4Preds_C; + VP8EncPredLuma16 = Intra16Preds_C; + VP8EncPredChroma8 = IntraChromaPreds_C; + VP8Mean16x4 = Mean16x4_C; + VP8EncQuantizeBlockWHT = QuantizeBlock_C; + VP8Copy4x4 = Copy4x4_C; + VP8Copy16x8 = Copy16x8_C; + + // If defined, use CPUInfo() to overwrite some pointers with faster versions. + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_HAVE_SSE2) + if (VP8GetCPUInfo(kSSE2)) { + VP8EncDspInitSSE2(); +#if defined(WEBP_HAVE_SSE41) + if (VP8GetCPUInfo(kSSE4_1)) { + VP8EncDspInitSSE41(); + } +#endif + } +#endif +#if defined(WEBP_USE_MIPS32) + if (VP8GetCPUInfo(kMIPS32)) { + VP8EncDspInitMIPS32(); + } +#endif +#if defined(WEBP_USE_MIPS_DSP_R2) + if (VP8GetCPUInfo(kMIPSdspR2)) { + VP8EncDspInitMIPSdspR2(); + } +#endif +#if defined(WEBP_USE_MSA) + if (VP8GetCPUInfo(kMSA)) { + VP8EncDspInitMSA(); + } +#endif + } + +#if defined(WEBP_HAVE_NEON) + if (WEBP_NEON_OMIT_C_CODE || + (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) { + VP8EncDspInitNEON(); + } +#endif + + assert(VP8ITransform != NULL); + assert(VP8FTransform != NULL); + assert(VP8FTransformWHT != NULL); + assert(VP8TDisto4x4 != NULL); + assert(VP8TDisto16x16 != NULL); + assert(VP8CollectHistogram != NULL); + assert(VP8SSE16x16 != NULL); + assert(VP8SSE16x8 != NULL); + assert(VP8SSE8x8 != NULL); + assert(VP8SSE4x4 != NULL); + assert(VP8EncQuantizeBlock != NULL); + assert(VP8EncQuantize2Blocks != NULL); + assert(VP8FTransform2 != NULL); + assert(VP8EncPredLuma4 != NULL); + assert(VP8EncPredLuma16 != NULL); + assert(VP8EncPredChroma8 != NULL); + assert(VP8Mean16x4 != NULL); + assert(VP8EncQuantizeBlockWHT != NULL); + assert(VP8Copy4x4 != NULL); + assert(VP8Copy16x8 != NULL); +} diff --git a/third-party/webp/libwebp/src/dsp/enc_mips32.c b/third-party/webp/libwebp/src/dsp/enc_mips32.c new file mode 100644 index 0000000000..618f0fc0ee --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/enc_mips32.c @@ -0,0 +1,677 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MIPS version of speed-critical encoding functions. +// +// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) +// Jovan Zelincevic (jovan.zelincevic@imgtec.com) +// Slobodan Prijic (slobodan.prijic@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MIPS32) + +#include "src/dsp/mips_macro.h" +#include "src/enc/vp8i_enc.h" +#include "src/enc/cost_enc.h" + +static const int kC1 = 20091 + (1 << 16); +static const int kC2 = 35468; + +// macro for one vertical pass in ITransformOne +// MUL macro inlined +// temp0..temp15 holds tmp[0]..tmp[15] +// A..D - offsets in bytes to load from in buffer +// TEMP0..TEMP3 - registers for corresponding tmp elements +// TEMP4..TEMP5 - temporary registers +#define VERTICAL_PASS(A, B, C, D, TEMP4, TEMP0, TEMP1, TEMP2, TEMP3) \ + "lh %[temp16], " #A "(%[temp20]) \n\t" \ + "lh %[temp18], " #B "(%[temp20]) \n\t" \ + "lh %[temp17], " #C "(%[temp20]) \n\t" \ + "lh %[temp19], " #D "(%[temp20]) \n\t" \ + "addu %[" #TEMP4 "], %[temp16], %[temp18] \n\t" \ + "subu %[temp16], %[temp16], %[temp18] \n\t" \ + "mul %[" #TEMP0 "], %[temp17], %[kC2] \n\t" \ + "mul %[temp18], %[temp19], %[kC1] \n\t" \ + "mul %[temp17], %[temp17], %[kC1] \n\t" \ + "mul %[temp19], %[temp19], %[kC2] \n\t" \ + "sra %[" #TEMP0 "], %[" #TEMP0 "], 16 \n\n" \ + "sra %[temp18], %[temp18], 16 \n\n" \ + "sra %[temp17], %[temp17], 16 \n\n" \ + "sra %[temp19], %[temp19], 16 \n\n" \ + "subu %[" #TEMP2 "], %[" #TEMP0 "], %[temp18] \n\t" \ + "addu %[" #TEMP3 "], %[temp17], %[temp19] \n\t" \ + "addu %[" #TEMP0 "], %[" #TEMP4 "], %[" #TEMP3 "] \n\t" \ + "addu %[" #TEMP1 "], %[temp16], %[" #TEMP2 "] \n\t" \ + "subu %[" #TEMP2 "], %[temp16], %[" #TEMP2 "] \n\t" \ + "subu %[" #TEMP3 "], %[" #TEMP4 "], %[" #TEMP3 "] \n\t" + +// macro for one horizontal pass in ITransformOne +// MUL and STORE macros inlined +// a = clip_8b(a) is replaced with: a = max(a, 0); a = min(a, 255) +// temp0..temp15 holds tmp[0]..tmp[15] +// A - offset in bytes to load from ref and store to dst buffer +// TEMP0, TEMP4, TEMP8 and TEMP12 - registers for corresponding tmp elements +#define HORIZONTAL_PASS(A, TEMP0, TEMP4, TEMP8, TEMP12) \ + "addiu %[" #TEMP0 "], %[" #TEMP0 "], 4 \n\t" \ + "addu %[temp16], %[" #TEMP0 "], %[" #TEMP8 "] \n\t" \ + "subu %[temp17], %[" #TEMP0 "], %[" #TEMP8 "] \n\t" \ + "mul %[" #TEMP0 "], %[" #TEMP4 "], %[kC2] \n\t" \ + "mul %[" #TEMP8 "], %[" #TEMP12 "], %[kC1] \n\t" \ + "mul %[" #TEMP4 "], %[" #TEMP4 "], %[kC1] \n\t" \ + "mul %[" #TEMP12 "], %[" #TEMP12 "], %[kC2] \n\t" \ + "sra %[" #TEMP0 "], %[" #TEMP0 "], 16 \n\t" \ + "sra %[" #TEMP8 "], %[" #TEMP8 "], 16 \n\t" \ + "sra %[" #TEMP4 "], %[" #TEMP4 "], 16 \n\t" \ + "sra %[" #TEMP12 "], %[" #TEMP12 "], 16 \n\t" \ + "subu %[temp18], %[" #TEMP0 "], %[" #TEMP8 "] \n\t" \ + "addu %[temp19], %[" #TEMP4 "], %[" #TEMP12 "] \n\t" \ + "addu %[" #TEMP0 "], %[temp16], %[temp19] \n\t" \ + "addu %[" #TEMP4 "], %[temp17], %[temp18] \n\t" \ + "subu %[" #TEMP8 "], %[temp17], %[temp18] \n\t" \ + "subu %[" #TEMP12 "], %[temp16], %[temp19] \n\t" \ + "lw %[temp20], 0(%[args]) \n\t" \ + "sra %[" #TEMP0 "], %[" #TEMP0 "], 3 \n\t" \ + "sra %[" #TEMP4 "], %[" #TEMP4 "], 3 \n\t" \ + "sra %[" #TEMP8 "], %[" #TEMP8 "], 3 \n\t" \ + "sra %[" #TEMP12 "], %[" #TEMP12 "], 3 \n\t" \ + "lbu %[temp16], 0+" XSTR(BPS) "*" #A "(%[temp20]) \n\t" \ + "lbu %[temp17], 1+" XSTR(BPS) "*" #A "(%[temp20]) \n\t" \ + "lbu %[temp18], 2+" XSTR(BPS) "*" #A "(%[temp20]) \n\t" \ + "lbu %[temp19], 3+" XSTR(BPS) "*" #A "(%[temp20]) \n\t" \ + "addu %[" #TEMP0 "], %[temp16], %[" #TEMP0 "] \n\t" \ + "addu %[" #TEMP4 "], %[temp17], %[" #TEMP4 "] \n\t" \ + "addu %[" #TEMP8 "], %[temp18], %[" #TEMP8 "] \n\t" \ + "addu %[" #TEMP12 "], %[temp19], %[" #TEMP12 "] \n\t" \ + "slt %[temp16], %[" #TEMP0 "], $zero \n\t" \ + "slt %[temp17], %[" #TEMP4 "], $zero \n\t" \ + "slt %[temp18], %[" #TEMP8 "], $zero \n\t" \ + "slt %[temp19], %[" #TEMP12 "], $zero \n\t" \ + "movn %[" #TEMP0 "], $zero, %[temp16] \n\t" \ + "movn %[" #TEMP4 "], $zero, %[temp17] \n\t" \ + "movn %[" #TEMP8 "], $zero, %[temp18] \n\t" \ + "movn %[" #TEMP12 "], $zero, %[temp19] \n\t" \ + "addiu %[temp20], $zero, 255 \n\t" \ + "slt %[temp16], %[" #TEMP0 "], %[temp20] \n\t" \ + "slt %[temp17], %[" #TEMP4 "], %[temp20] \n\t" \ + "slt %[temp18], %[" #TEMP8 "], %[temp20] \n\t" \ + "slt %[temp19], %[" #TEMP12 "], %[temp20] \n\t" \ + "movz %[" #TEMP0 "], %[temp20], %[temp16] \n\t" \ + "movz %[" #TEMP4 "], %[temp20], %[temp17] \n\t" \ + "lw %[temp16], 8(%[args]) \n\t" \ + "movz %[" #TEMP8 "], %[temp20], %[temp18] \n\t" \ + "movz %[" #TEMP12 "], %[temp20], %[temp19] \n\t" \ + "sb %[" #TEMP0 "], 0+" XSTR(BPS) "*" #A "(%[temp16]) \n\t" \ + "sb %[" #TEMP4 "], 1+" XSTR(BPS) "*" #A "(%[temp16]) \n\t" \ + "sb %[" #TEMP8 "], 2+" XSTR(BPS) "*" #A "(%[temp16]) \n\t" \ + "sb %[" #TEMP12 "], 3+" XSTR(BPS) "*" #A "(%[temp16]) \n\t" + +// Does one or two inverse transforms. +static WEBP_INLINE void ITransformOne_MIPS32(const uint8_t* ref, + const int16_t* in, + uint8_t* dst) { + int temp0, temp1, temp2, temp3, temp4, temp5, temp6; + int temp7, temp8, temp9, temp10, temp11, temp12, temp13; + int temp14, temp15, temp16, temp17, temp18, temp19, temp20; + const int* args[3] = {(const int*)ref, (const int*)in, (const int*)dst}; + + __asm__ volatile( + "lw %[temp20], 4(%[args]) \n\t" + VERTICAL_PASS(0, 16, 8, 24, temp4, temp0, temp1, temp2, temp3) + VERTICAL_PASS(2, 18, 10, 26, temp8, temp4, temp5, temp6, temp7) + VERTICAL_PASS(4, 20, 12, 28, temp12, temp8, temp9, temp10, temp11) + VERTICAL_PASS(6, 22, 14, 30, temp20, temp12, temp13, temp14, temp15) + + HORIZONTAL_PASS(0, temp0, temp4, temp8, temp12) + HORIZONTAL_PASS(1, temp1, temp5, temp9, temp13) + HORIZONTAL_PASS(2, temp2, temp6, temp10, temp14) + HORIZONTAL_PASS(3, temp3, temp7, temp11, temp15) + + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), + [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11), + [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), [temp14]"=&r"(temp14), + [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), [temp17]"=&r"(temp17), + [temp18]"=&r"(temp18), [temp19]"=&r"(temp19), [temp20]"=&r"(temp20) + : [args]"r"(args), [kC1]"r"(kC1), [kC2]"r"(kC2) + : "memory", "hi", "lo" + ); +} + +static void ITransform_MIPS32(const uint8_t* ref, const int16_t* in, + uint8_t* dst, int do_two) { + ITransformOne_MIPS32(ref, in, dst); + if (do_two) { + ITransformOne_MIPS32(ref + 4, in + 16, dst + 4); + } +} + +#undef VERTICAL_PASS +#undef HORIZONTAL_PASS + +// macro for one pass through for loop in QuantizeBlock +// QUANTDIV macro inlined +// J - offset in bytes (kZigzag[n] * 2) +// K - offset in bytes (kZigzag[n] * 4) +// N - offset in bytes (n * 2) +#define QUANTIZE_ONE(J, K, N) \ + "lh %[temp0], " #J "(%[ppin]) \n\t" \ + "lhu %[temp1], " #J "(%[ppsharpen]) \n\t" \ + "lw %[temp2], " #K "(%[ppzthresh]) \n\t" \ + "sra %[sign], %[temp0], 15 \n\t" \ + "xor %[coeff], %[temp0], %[sign] \n\t" \ + "subu %[coeff], %[coeff], %[sign] \n\t" \ + "addu %[coeff], %[coeff], %[temp1] \n\t" \ + "slt %[temp4], %[temp2], %[coeff] \n\t" \ + "addiu %[temp5], $zero, 0 \n\t" \ + "addiu %[level], $zero, 0 \n\t" \ + "beqz %[temp4], 2f \n\t" \ + "lhu %[temp1], " #J "(%[ppiq]) \n\t" \ + "lw %[temp2], " #K "(%[ppbias]) \n\t" \ + "lhu %[temp3], " #J "(%[ppq]) \n\t" \ + "mul %[level], %[coeff], %[temp1] \n\t" \ + "addu %[level], %[level], %[temp2] \n\t" \ + "sra %[level], %[level], 17 \n\t" \ + "slt %[temp4], %[max_level], %[level] \n\t" \ + "movn %[level], %[max_level], %[temp4] \n\t" \ + "xor %[level], %[level], %[sign] \n\t" \ + "subu %[level], %[level], %[sign] \n\t" \ + "mul %[temp5], %[level], %[temp3] \n\t" \ +"2: \n\t" \ + "sh %[temp5], " #J "(%[ppin]) \n\t" \ + "sh %[level], " #N "(%[pout]) \n\t" + +static int QuantizeBlock_MIPS32(int16_t in[16], int16_t out[16], + const VP8Matrix* const mtx) { + int temp0, temp1, temp2, temp3, temp4, temp5; + int sign, coeff, level, i; + int max_level = MAX_LEVEL; + + int16_t* ppin = &in[0]; + int16_t* pout = &out[0]; + const uint16_t* ppsharpen = &mtx->sharpen_[0]; + const uint32_t* ppzthresh = &mtx->zthresh_[0]; + const uint16_t* ppq = &mtx->q_[0]; + const uint16_t* ppiq = &mtx->iq_[0]; + const uint32_t* ppbias = &mtx->bias_[0]; + + __asm__ volatile( + QUANTIZE_ONE( 0, 0, 0) + QUANTIZE_ONE( 2, 4, 2) + QUANTIZE_ONE( 8, 16, 4) + QUANTIZE_ONE(16, 32, 6) + QUANTIZE_ONE(10, 20, 8) + QUANTIZE_ONE( 4, 8, 10) + QUANTIZE_ONE( 6, 12, 12) + QUANTIZE_ONE(12, 24, 14) + QUANTIZE_ONE(18, 36, 16) + QUANTIZE_ONE(24, 48, 18) + QUANTIZE_ONE(26, 52, 20) + QUANTIZE_ONE(20, 40, 22) + QUANTIZE_ONE(14, 28, 24) + QUANTIZE_ONE(22, 44, 26) + QUANTIZE_ONE(28, 56, 28) + QUANTIZE_ONE(30, 60, 30) + + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [sign]"=&r"(sign), [coeff]"=&r"(coeff), + [level]"=&r"(level) + : [pout]"r"(pout), [ppin]"r"(ppin), + [ppiq]"r"(ppiq), [max_level]"r"(max_level), + [ppbias]"r"(ppbias), [ppzthresh]"r"(ppzthresh), + [ppsharpen]"r"(ppsharpen), [ppq]"r"(ppq) + : "memory", "hi", "lo" + ); + + // moved out from macro to increase possibility for earlier breaking + for (i = 15; i >= 0; i--) { + if (out[i]) return 1; + } + return 0; +} + +static int Quantize2Blocks_MIPS32(int16_t in[32], int16_t out[32], + const VP8Matrix* const mtx) { + int nz; + nz = QuantizeBlock_MIPS32(in + 0 * 16, out + 0 * 16, mtx) << 0; + nz |= QuantizeBlock_MIPS32(in + 1 * 16, out + 1 * 16, mtx) << 1; + return nz; +} + +#undef QUANTIZE_ONE + +// macro for one horizontal pass in Disto4x4 (TTransform) +// two calls of function TTransform are merged into single one +// A - offset in bytes to load from a and b buffers +// E..H - offsets in bytes to store first results to tmp buffer +// E1..H1 - offsets in bytes to store second results to tmp buffer +#define HORIZONTAL_PASS(A, E, F, G, H, E1, F1, G1, H1) \ + "lbu %[temp0], 0+" XSTR(BPS) "*" #A "(%[a]) \n\t" \ + "lbu %[temp1], 1+" XSTR(BPS) "*" #A "(%[a]) \n\t" \ + "lbu %[temp2], 2+" XSTR(BPS) "*" #A "(%[a]) \n\t" \ + "lbu %[temp3], 3+" XSTR(BPS) "*" #A "(%[a]) \n\t" \ + "lbu %[temp4], 0+" XSTR(BPS) "*" #A "(%[b]) \n\t" \ + "lbu %[temp5], 1+" XSTR(BPS) "*" #A "(%[b]) \n\t" \ + "lbu %[temp6], 2+" XSTR(BPS) "*" #A "(%[b]) \n\t" \ + "lbu %[temp7], 3+" XSTR(BPS) "*" #A "(%[b]) \n\t" \ + "addu %[temp8], %[temp0], %[temp2] \n\t" \ + "subu %[temp0], %[temp0], %[temp2] \n\t" \ + "addu %[temp2], %[temp1], %[temp3] \n\t" \ + "subu %[temp1], %[temp1], %[temp3] \n\t" \ + "addu %[temp3], %[temp4], %[temp6] \n\t" \ + "subu %[temp4], %[temp4], %[temp6] \n\t" \ + "addu %[temp6], %[temp5], %[temp7] \n\t" \ + "subu %[temp5], %[temp5], %[temp7] \n\t" \ + "addu %[temp7], %[temp8], %[temp2] \n\t" \ + "subu %[temp2], %[temp8], %[temp2] \n\t" \ + "addu %[temp8], %[temp0], %[temp1] \n\t" \ + "subu %[temp0], %[temp0], %[temp1] \n\t" \ + "addu %[temp1], %[temp3], %[temp6] \n\t" \ + "subu %[temp3], %[temp3], %[temp6] \n\t" \ + "addu %[temp6], %[temp4], %[temp5] \n\t" \ + "subu %[temp4], %[temp4], %[temp5] \n\t" \ + "sw %[temp7], " #E "(%[tmp]) \n\t" \ + "sw %[temp2], " #H "(%[tmp]) \n\t" \ + "sw %[temp8], " #F "(%[tmp]) \n\t" \ + "sw %[temp0], " #G "(%[tmp]) \n\t" \ + "sw %[temp1], " #E1 "(%[tmp]) \n\t" \ + "sw %[temp3], " #H1 "(%[tmp]) \n\t" \ + "sw %[temp6], " #F1 "(%[tmp]) \n\t" \ + "sw %[temp4], " #G1 "(%[tmp]) \n\t" + +// macro for one vertical pass in Disto4x4 (TTransform) +// two calls of function TTransform are merged into single one +// since only one accu is available in mips32r1 instruction set +// first is done second call of function TTransform and after +// that first one. +// const int sum1 = TTransform(a, w); +// const int sum2 = TTransform(b, w); +// return abs(sum2 - sum1) >> 5; +// (sum2 - sum1) is calculated with madds (sub2) and msubs (sub1) +// A..D - offsets in bytes to load first results from tmp buffer +// A1..D1 - offsets in bytes to load second results from tmp buffer +// E..H - offsets in bytes to load from w buffer +#define VERTICAL_PASS(A, B, C, D, A1, B1, C1, D1, E, F, G, H) \ + "lw %[temp0], " #A1 "(%[tmp]) \n\t" \ + "lw %[temp1], " #C1 "(%[tmp]) \n\t" \ + "lw %[temp2], " #B1 "(%[tmp]) \n\t" \ + "lw %[temp3], " #D1 "(%[tmp]) \n\t" \ + "addu %[temp8], %[temp0], %[temp1] \n\t" \ + "subu %[temp0], %[temp0], %[temp1] \n\t" \ + "addu %[temp1], %[temp2], %[temp3] \n\t" \ + "subu %[temp2], %[temp2], %[temp3] \n\t" \ + "addu %[temp3], %[temp8], %[temp1] \n\t" \ + "subu %[temp8], %[temp8], %[temp1] \n\t" \ + "addu %[temp1], %[temp0], %[temp2] \n\t" \ + "subu %[temp0], %[temp0], %[temp2] \n\t" \ + "sra %[temp4], %[temp3], 31 \n\t" \ + "sra %[temp5], %[temp1], 31 \n\t" \ + "sra %[temp6], %[temp0], 31 \n\t" \ + "sra %[temp7], %[temp8], 31 \n\t" \ + "xor %[temp3], %[temp3], %[temp4] \n\t" \ + "xor %[temp1], %[temp1], %[temp5] \n\t" \ + "xor %[temp0], %[temp0], %[temp6] \n\t" \ + "xor %[temp8], %[temp8], %[temp7] \n\t" \ + "subu %[temp3], %[temp3], %[temp4] \n\t" \ + "subu %[temp1], %[temp1], %[temp5] \n\t" \ + "subu %[temp0], %[temp0], %[temp6] \n\t" \ + "subu %[temp8], %[temp8], %[temp7] \n\t" \ + "lhu %[temp4], " #E "(%[w]) \n\t" \ + "lhu %[temp5], " #F "(%[w]) \n\t" \ + "lhu %[temp6], " #G "(%[w]) \n\t" \ + "lhu %[temp7], " #H "(%[w]) \n\t" \ + "madd %[temp4], %[temp3] \n\t" \ + "madd %[temp5], %[temp1] \n\t" \ + "madd %[temp6], %[temp0] \n\t" \ + "madd %[temp7], %[temp8] \n\t" \ + "lw %[temp0], " #A "(%[tmp]) \n\t" \ + "lw %[temp1], " #C "(%[tmp]) \n\t" \ + "lw %[temp2], " #B "(%[tmp]) \n\t" \ + "lw %[temp3], " #D "(%[tmp]) \n\t" \ + "addu %[temp8], %[temp0], %[temp1] \n\t" \ + "subu %[temp0], %[temp0], %[temp1] \n\t" \ + "addu %[temp1], %[temp2], %[temp3] \n\t" \ + "subu %[temp2], %[temp2], %[temp3] \n\t" \ + "addu %[temp3], %[temp8], %[temp1] \n\t" \ + "subu %[temp1], %[temp8], %[temp1] \n\t" \ + "addu %[temp8], %[temp0], %[temp2] \n\t" \ + "subu %[temp0], %[temp0], %[temp2] \n\t" \ + "sra %[temp2], %[temp3], 31 \n\t" \ + "xor %[temp3], %[temp3], %[temp2] \n\t" \ + "subu %[temp3], %[temp3], %[temp2] \n\t" \ + "msub %[temp4], %[temp3] \n\t" \ + "sra %[temp2], %[temp8], 31 \n\t" \ + "sra %[temp3], %[temp0], 31 \n\t" \ + "sra %[temp4], %[temp1], 31 \n\t" \ + "xor %[temp8], %[temp8], %[temp2] \n\t" \ + "xor %[temp0], %[temp0], %[temp3] \n\t" \ + "xor %[temp1], %[temp1], %[temp4] \n\t" \ + "subu %[temp8], %[temp8], %[temp2] \n\t" \ + "subu %[temp0], %[temp0], %[temp3] \n\t" \ + "subu %[temp1], %[temp1], %[temp4] \n\t" \ + "msub %[temp5], %[temp8] \n\t" \ + "msub %[temp6], %[temp0] \n\t" \ + "msub %[temp7], %[temp1] \n\t" + +static int Disto4x4_MIPS32(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + int tmp[32]; + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8; + + __asm__ volatile( + HORIZONTAL_PASS(0, 0, 4, 8, 12, 64, 68, 72, 76) + HORIZONTAL_PASS(1, 16, 20, 24, 28, 80, 84, 88, 92) + HORIZONTAL_PASS(2, 32, 36, 40, 44, 96, 100, 104, 108) + HORIZONTAL_PASS(3, 48, 52, 56, 60, 112, 116, 120, 124) + "mthi $zero \n\t" + "mtlo $zero \n\t" + VERTICAL_PASS( 0, 16, 32, 48, 64, 80, 96, 112, 0, 8, 16, 24) + VERTICAL_PASS( 4, 20, 36, 52, 68, 84, 100, 116, 2, 10, 18, 26) + VERTICAL_PASS( 8, 24, 40, 56, 72, 88, 104, 120, 4, 12, 20, 28) + VERTICAL_PASS(12, 28, 44, 60, 76, 92, 108, 124, 6, 14, 22, 30) + "mflo %[temp0] \n\t" + "sra %[temp1], %[temp0], 31 \n\t" + "xor %[temp0], %[temp0], %[temp1] \n\t" + "subu %[temp0], %[temp0], %[temp1] \n\t" + "sra %[temp0], %[temp0], 5 \n\t" + + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8) + : [a]"r"(a), [b]"r"(b), [w]"r"(w), [tmp]"r"(tmp) + : "memory", "hi", "lo" + ); + + return temp0; +} + +#undef VERTICAL_PASS +#undef HORIZONTAL_PASS + +static int Disto16x16_MIPS32(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + int D = 0; + int x, y; + for (y = 0; y < 16 * BPS; y += 4 * BPS) { + for (x = 0; x < 16; x += 4) { + D += Disto4x4_MIPS32(a + x + y, b + x + y, w); + } + } + return D; +} + +// macro for one horizontal pass in FTransform +// temp0..temp15 holds tmp[0]..tmp[15] +// A - offset in bytes to load from src and ref buffers +// TEMP0..TEMP3 - registers for corresponding tmp elements +#define HORIZONTAL_PASS(A, TEMP0, TEMP1, TEMP2, TEMP3) \ + "lw %[" #TEMP1 "], 0(%[args]) \n\t" \ + "lw %[" #TEMP2 "], 4(%[args]) \n\t" \ + "lbu %[temp16], 0+" XSTR(BPS) "*" #A "(%[" #TEMP1 "]) \n\t" \ + "lbu %[temp17], 0+" XSTR(BPS) "*" #A "(%[" #TEMP2 "]) \n\t" \ + "lbu %[temp18], 1+" XSTR(BPS) "*" #A "(%[" #TEMP1 "]) \n\t" \ + "lbu %[temp19], 1+" XSTR(BPS) "*" #A "(%[" #TEMP2 "]) \n\t" \ + "subu %[temp20], %[temp16], %[temp17] \n\t" \ + "lbu %[temp16], 2+" XSTR(BPS) "*" #A "(%[" #TEMP1 "]) \n\t" \ + "lbu %[temp17], 2+" XSTR(BPS) "*" #A "(%[" #TEMP2 "]) \n\t" \ + "subu %[" #TEMP0 "], %[temp18], %[temp19] \n\t" \ + "lbu %[temp18], 3+" XSTR(BPS) "*" #A "(%[" #TEMP1 "]) \n\t" \ + "lbu %[temp19], 3+" XSTR(BPS) "*" #A "(%[" #TEMP2 "]) \n\t" \ + "subu %[" #TEMP1 "], %[temp16], %[temp17] \n\t" \ + "subu %[" #TEMP2 "], %[temp18], %[temp19] \n\t" \ + "addu %[" #TEMP3 "], %[temp20], %[" #TEMP2 "] \n\t" \ + "subu %[" #TEMP2 "], %[temp20], %[" #TEMP2 "] \n\t" \ + "addu %[temp20], %[" #TEMP0 "], %[" #TEMP1 "] \n\t" \ + "subu %[" #TEMP0 "], %[" #TEMP0 "], %[" #TEMP1 "] \n\t" \ + "mul %[temp16], %[" #TEMP2 "], %[c5352] \n\t" \ + "mul %[temp17], %[" #TEMP2 "], %[c2217] \n\t" \ + "mul %[temp18], %[" #TEMP0 "], %[c5352] \n\t" \ + "mul %[temp19], %[" #TEMP0 "], %[c2217] \n\t" \ + "addu %[" #TEMP1 "], %[" #TEMP3 "], %[temp20] \n\t" \ + "subu %[temp20], %[" #TEMP3 "], %[temp20] \n\t" \ + "sll %[" #TEMP0 "], %[" #TEMP1 "], 3 \n\t" \ + "sll %[" #TEMP2 "], %[temp20], 3 \n\t" \ + "addiu %[temp16], %[temp16], 1812 \n\t" \ + "addiu %[temp17], %[temp17], 937 \n\t" \ + "addu %[temp16], %[temp16], %[temp19] \n\t" \ + "subu %[temp17], %[temp17], %[temp18] \n\t" \ + "sra %[" #TEMP1 "], %[temp16], 9 \n\t" \ + "sra %[" #TEMP3 "], %[temp17], 9 \n\t" + +// macro for one vertical pass in FTransform +// temp0..temp15 holds tmp[0]..tmp[15] +// A..D - offsets in bytes to store to out buffer +// TEMP0, TEMP4, TEMP8 and TEMP12 - registers for corresponding tmp elements +#define VERTICAL_PASS(A, B, C, D, TEMP0, TEMP4, TEMP8, TEMP12) \ + "addu %[temp16], %[" #TEMP0 "], %[" #TEMP12 "] \n\t" \ + "subu %[temp19], %[" #TEMP0 "], %[" #TEMP12 "] \n\t" \ + "addu %[temp17], %[" #TEMP4 "], %[" #TEMP8 "] \n\t" \ + "subu %[temp18], %[" #TEMP4 "], %[" #TEMP8 "] \n\t" \ + "mul %[" #TEMP8 "], %[temp19], %[c2217] \n\t" \ + "mul %[" #TEMP12 "], %[temp18], %[c2217] \n\t" \ + "mul %[" #TEMP4 "], %[temp19], %[c5352] \n\t" \ + "mul %[temp18], %[temp18], %[c5352] \n\t" \ + "addiu %[temp16], %[temp16], 7 \n\t" \ + "addu %[" #TEMP0 "], %[temp16], %[temp17] \n\t" \ + "sra %[" #TEMP0 "], %[" #TEMP0 "], 4 \n\t" \ + "addu %[" #TEMP12 "], %[" #TEMP12 "], %[" #TEMP4 "] \n\t" \ + "subu %[" #TEMP4 "], %[temp16], %[temp17] \n\t" \ + "sra %[" #TEMP4 "], %[" #TEMP4 "], 4 \n\t" \ + "addiu %[" #TEMP8 "], %[" #TEMP8 "], 30000 \n\t" \ + "addiu %[" #TEMP12 "], %[" #TEMP12 "], 12000 \n\t" \ + "addiu %[" #TEMP8 "], %[" #TEMP8 "], 21000 \n\t" \ + "subu %[" #TEMP8 "], %[" #TEMP8 "], %[temp18] \n\t" \ + "sra %[" #TEMP12 "], %[" #TEMP12 "], 16 \n\t" \ + "sra %[" #TEMP8 "], %[" #TEMP8 "], 16 \n\t" \ + "addiu %[temp16], %[" #TEMP12 "], 1 \n\t" \ + "movn %[" #TEMP12 "], %[temp16], %[temp19] \n\t" \ + "sh %[" #TEMP0 "], " #A "(%[temp20]) \n\t" \ + "sh %[" #TEMP4 "], " #C "(%[temp20]) \n\t" \ + "sh %[" #TEMP8 "], " #D "(%[temp20]) \n\t" \ + "sh %[" #TEMP12 "], " #B "(%[temp20]) \n\t" + +static void FTransform_MIPS32(const uint8_t* src, const uint8_t* ref, + int16_t* out) { + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8; + int temp9, temp10, temp11, temp12, temp13, temp14, temp15, temp16; + int temp17, temp18, temp19, temp20; + const int c2217 = 2217; + const int c5352 = 5352; + const int* const args[3] = + { (const int*)src, (const int*)ref, (const int*)out }; + + __asm__ volatile( + HORIZONTAL_PASS(0, temp0, temp1, temp2, temp3) + HORIZONTAL_PASS(1, temp4, temp5, temp6, temp7) + HORIZONTAL_PASS(2, temp8, temp9, temp10, temp11) + HORIZONTAL_PASS(3, temp12, temp13, temp14, temp15) + "lw %[temp20], 8(%[args]) \n\t" + VERTICAL_PASS(0, 8, 16, 24, temp0, temp4, temp8, temp12) + VERTICAL_PASS(2, 10, 18, 26, temp1, temp5, temp9, temp13) + VERTICAL_PASS(4, 12, 20, 28, temp2, temp6, temp10, temp14) + VERTICAL_PASS(6, 14, 22, 30, temp3, temp7, temp11, temp15) + + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), + [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11), + [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), [temp14]"=&r"(temp14), + [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), [temp17]"=&r"(temp17), + [temp18]"=&r"(temp18), [temp19]"=&r"(temp19), [temp20]"=&r"(temp20) + : [args]"r"(args), [c2217]"r"(c2217), [c5352]"r"(c5352) + : "memory", "hi", "lo" + ); +} + +#undef VERTICAL_PASS +#undef HORIZONTAL_PASS + +#if !defined(WORK_AROUND_GCC) + +#define GET_SSE_INNER(A, B, C, D) \ + "lbu %[temp0], " #A "(%[a]) \n\t" \ + "lbu %[temp1], " #A "(%[b]) \n\t" \ + "lbu %[temp2], " #B "(%[a]) \n\t" \ + "lbu %[temp3], " #B "(%[b]) \n\t" \ + "lbu %[temp4], " #C "(%[a]) \n\t" \ + "lbu %[temp5], " #C "(%[b]) \n\t" \ + "lbu %[temp6], " #D "(%[a]) \n\t" \ + "lbu %[temp7], " #D "(%[b]) \n\t" \ + "subu %[temp0], %[temp0], %[temp1] \n\t" \ + "subu %[temp2], %[temp2], %[temp3] \n\t" \ + "subu %[temp4], %[temp4], %[temp5] \n\t" \ + "subu %[temp6], %[temp6], %[temp7] \n\t" \ + "madd %[temp0], %[temp0] \n\t" \ + "madd %[temp2], %[temp2] \n\t" \ + "madd %[temp4], %[temp4] \n\t" \ + "madd %[temp6], %[temp6] \n\t" + +#define GET_SSE(A, B, C, D) \ + GET_SSE_INNER(A, A + 1, A + 2, A + 3) \ + GET_SSE_INNER(B, B + 1, B + 2, B + 3) \ + GET_SSE_INNER(C, C + 1, C + 2, C + 3) \ + GET_SSE_INNER(D, D + 1, D + 2, D + 3) + +static int SSE16x16_MIPS32(const uint8_t* a, const uint8_t* b) { + int count; + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + + __asm__ volatile( + "mult $zero, $zero \n\t" + + GET_SSE( 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS) + GET_SSE( 1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS) + GET_SSE( 2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS) + GET_SSE( 3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS) + GET_SSE( 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS) + GET_SSE( 5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS) + GET_SSE( 6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS) + GET_SSE( 7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS) + GET_SSE( 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS) + GET_SSE( 9 * BPS, 4 + 9 * BPS, 8 + 9 * BPS, 12 + 9 * BPS) + GET_SSE(10 * BPS, 4 + 10 * BPS, 8 + 10 * BPS, 12 + 10 * BPS) + GET_SSE(11 * BPS, 4 + 11 * BPS, 8 + 11 * BPS, 12 + 11 * BPS) + GET_SSE(12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS) + GET_SSE(13 * BPS, 4 + 13 * BPS, 8 + 13 * BPS, 12 + 13 * BPS) + GET_SSE(14 * BPS, 4 + 14 * BPS, 8 + 14 * BPS, 12 + 14 * BPS) + GET_SSE(15 * BPS, 4 + 15 * BPS, 8 + 15 * BPS, 12 + 15 * BPS) + + "mflo %[count] \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count) + : [a]"r"(a), [b]"r"(b) + : "memory", "hi", "lo" + ); + return count; +} + +static int SSE16x8_MIPS32(const uint8_t* a, const uint8_t* b) { + int count; + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + + __asm__ volatile( + "mult $zero, $zero \n\t" + + GET_SSE( 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS) + GET_SSE( 1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS) + GET_SSE( 2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS) + GET_SSE( 3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS) + GET_SSE( 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS) + GET_SSE( 5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS) + GET_SSE( 6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS) + GET_SSE( 7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS) + + "mflo %[count] \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count) + : [a]"r"(a), [b]"r"(b) + : "memory", "hi", "lo" + ); + return count; +} + +static int SSE8x8_MIPS32(const uint8_t* a, const uint8_t* b) { + int count; + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + + __asm__ volatile( + "mult $zero, $zero \n\t" + + GET_SSE(0 * BPS, 4 + 0 * BPS, 1 * BPS, 4 + 1 * BPS) + GET_SSE(2 * BPS, 4 + 2 * BPS, 3 * BPS, 4 + 3 * BPS) + GET_SSE(4 * BPS, 4 + 4 * BPS, 5 * BPS, 4 + 5 * BPS) + GET_SSE(6 * BPS, 4 + 6 * BPS, 7 * BPS, 4 + 7 * BPS) + + "mflo %[count] \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count) + : [a]"r"(a), [b]"r"(b) + : "memory", "hi", "lo" + ); + return count; +} + +static int SSE4x4_MIPS32(const uint8_t* a, const uint8_t* b) { + int count; + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + + __asm__ volatile( + "mult $zero, $zero \n\t" + + GET_SSE(0 * BPS, 1 * BPS, 2 * BPS, 3 * BPS) + + "mflo %[count] \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count) + : [a]"r"(a), [b]"r"(b) + : "memory", "hi", "lo" + ); + return count; +} + +#undef GET_SSE +#undef GET_SSE_INNER + +#endif // !WORK_AROUND_GCC + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8EncDspInitMIPS32(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitMIPS32(void) { + VP8ITransform = ITransform_MIPS32; + VP8FTransform = FTransform_MIPS32; + + VP8EncQuantizeBlock = QuantizeBlock_MIPS32; + VP8EncQuantize2Blocks = Quantize2Blocks_MIPS32; + + VP8TDisto4x4 = Disto4x4_MIPS32; + VP8TDisto16x16 = Disto16x16_MIPS32; + +#if !defined(WORK_AROUND_GCC) + VP8SSE16x16 = SSE16x16_MIPS32; + VP8SSE8x8 = SSE8x8_MIPS32; + VP8SSE16x8 = SSE16x8_MIPS32; + VP8SSE4x4 = SSE4x4_MIPS32; +#endif +} + +#else // !WEBP_USE_MIPS32 + +WEBP_DSP_INIT_STUB(VP8EncDspInitMIPS32) + +#endif // WEBP_USE_MIPS32 diff --git a/third-party/webp/libwebp/src/dsp/enc_mips_dsp_r2.c b/third-party/webp/libwebp/src/dsp/enc_mips_dsp_r2.c new file mode 100644 index 0000000000..9ddd895086 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/enc_mips_dsp_r2.c @@ -0,0 +1,1517 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MIPS version of speed-critical encoding functions. +// +// Author(s): Darko Laus (darko.laus@imgtec.com) +// Mirko Raus (mirko.raus@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MIPS_DSP_R2) + +#include "src/dsp/mips_macro.h" +#include "src/enc/cost_enc.h" +#include "src/enc/vp8i_enc.h" + +static const int kC1 = 20091 + (1 << 16); +static const int kC2 = 35468; + +// O - output +// I - input (macro doesn't change it) +#define ADD_SUB_HALVES_X4(O0, O1, O2, O3, O4, O5, O6, O7, \ + I0, I1, I2, I3, I4, I5, I6, I7) \ + "addq.ph %[" #O0 "], %[" #I0 "], %[" #I1 "] \n\t" \ + "subq.ph %[" #O1 "], %[" #I0 "], %[" #I1 "] \n\t" \ + "addq.ph %[" #O2 "], %[" #I2 "], %[" #I3 "] \n\t" \ + "subq.ph %[" #O3 "], %[" #I2 "], %[" #I3 "] \n\t" \ + "addq.ph %[" #O4 "], %[" #I4 "], %[" #I5 "] \n\t" \ + "subq.ph %[" #O5 "], %[" #I4 "], %[" #I5 "] \n\t" \ + "addq.ph %[" #O6 "], %[" #I6 "], %[" #I7 "] \n\t" \ + "subq.ph %[" #O7 "], %[" #I6 "], %[" #I7 "] \n\t" + +// IO - input/output +#define ABS_X8(IO0, IO1, IO2, IO3, IO4, IO5, IO6, IO7) \ + "absq_s.ph %[" #IO0 "], %[" #IO0 "] \n\t" \ + "absq_s.ph %[" #IO1 "], %[" #IO1 "] \n\t" \ + "absq_s.ph %[" #IO2 "], %[" #IO2 "] \n\t" \ + "absq_s.ph %[" #IO3 "], %[" #IO3 "] \n\t" \ + "absq_s.ph %[" #IO4 "], %[" #IO4 "] \n\t" \ + "absq_s.ph %[" #IO5 "], %[" #IO5 "] \n\t" \ + "absq_s.ph %[" #IO6 "], %[" #IO6 "] \n\t" \ + "absq_s.ph %[" #IO7 "], %[" #IO7 "] \n\t" + +// dpa.w.ph $ac0 temp0 ,temp1 +// $ac += temp0[31..16] * temp1[31..16] + temp0[15..0] * temp1[15..0] +// dpax.w.ph $ac0 temp0 ,temp1 +// $ac += temp0[31..16] * temp1[15..0] + temp0[15..0] * temp1[31..16] +// O - output +// I - input (macro doesn't change it) +#define MUL_HALF(O0, I0, I1, I2, I3, I4, I5, I6, I7, \ + I8, I9, I10, I11, I12, I13, I14, I15) \ + "mult $ac0, $zero, $zero \n\t" \ + "dpa.w.ph $ac0, %[" #I2 "], %[" #I0 "] \n\t" \ + "dpax.w.ph $ac0, %[" #I5 "], %[" #I6 "] \n\t" \ + "dpa.w.ph $ac0, %[" #I8 "], %[" #I9 "] \n\t" \ + "dpax.w.ph $ac0, %[" #I11 "], %[" #I4 "] \n\t" \ + "dpa.w.ph $ac0, %[" #I12 "], %[" #I7 "] \n\t" \ + "dpax.w.ph $ac0, %[" #I13 "], %[" #I1 "] \n\t" \ + "dpa.w.ph $ac0, %[" #I14 "], %[" #I3 "] \n\t" \ + "dpax.w.ph $ac0, %[" #I15 "], %[" #I10 "] \n\t" \ + "mflo %[" #O0 "], $ac0 \n\t" + +#define OUTPUT_EARLY_CLOBBER_REGS_17() \ + OUTPUT_EARLY_CLOBBER_REGS_10(), \ + [temp11]"=&r"(temp11), [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), \ + [temp14]"=&r"(temp14), [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), \ + [temp17]"=&r"(temp17) + +// macro for one horizontal pass in FTransform +// temp0..temp15 holds tmp[0]..tmp[15] +// A - offset in bytes to load from src and ref buffers +// TEMP0..TEMP3 - registers for corresponding tmp elements +#define HORIZONTAL_PASS(A, TEMP0, TEMP1, TEMP2, TEMP3) \ + "lw %[" #TEMP0 "], 0(%[args]) \n\t" \ + "lw %[" #TEMP1 "], 4(%[args]) \n\t" \ + "lw %[" #TEMP2 "], " XSTR(BPS) "*" #A "(%[" #TEMP0 "]) \n\t" \ + "lw %[" #TEMP3 "], " XSTR(BPS) "*" #A "(%[" #TEMP1 "]) \n\t" \ + "preceu.ph.qbl %[" #TEMP0 "], %[" #TEMP2 "] \n\t" \ + "preceu.ph.qbl %[" #TEMP1 "], %[" #TEMP3 "] \n\t" \ + "preceu.ph.qbr %[" #TEMP2 "], %[" #TEMP2 "] \n\t" \ + "preceu.ph.qbr %[" #TEMP3 "], %[" #TEMP3 "] \n\t" \ + "subq.ph %[" #TEMP0 "], %[" #TEMP0 "], %[" #TEMP1 "] \n\t" \ + "subq.ph %[" #TEMP2 "], %[" #TEMP2 "], %[" #TEMP3 "] \n\t" \ + "rotr %[" #TEMP0 "], %[" #TEMP0 "], 16 \n\t" \ + "addq.ph %[" #TEMP1 "], %[" #TEMP2 "], %[" #TEMP0 "] \n\t" \ + "subq.ph %[" #TEMP3 "], %[" #TEMP2 "], %[" #TEMP0 "] \n\t" \ + "seh %[" #TEMP0 "], %[" #TEMP1 "] \n\t" \ + "sra %[temp16], %[" #TEMP1 "], 16 \n\t" \ + "seh %[temp19], %[" #TEMP3 "] \n\t" \ + "sra %[" #TEMP3 "], %[" #TEMP3 "], 16 \n\t" \ + "subu %[" #TEMP2 "], %[" #TEMP0 "], %[temp16] \n\t" \ + "addu %[" #TEMP0 "], %[" #TEMP0 "], %[temp16] \n\t" \ + "mul %[temp17], %[temp19], %[c2217] \n\t" \ + "mul %[temp18], %[" #TEMP3 "], %[c5352] \n\t" \ + "mul %[" #TEMP1 "], %[temp19], %[c5352] \n\t" \ + "mul %[temp16], %[" #TEMP3 "], %[c2217] \n\t" \ + "sll %[" #TEMP2 "], %[" #TEMP2 "], 3 \n\t" \ + "sll %[" #TEMP0 "], %[" #TEMP0 "], 3 \n\t" \ + "subu %[" #TEMP3 "], %[temp17], %[temp18] \n\t" \ + "addu %[" #TEMP1 "], %[temp16], %[" #TEMP1 "] \n\t" \ + "addiu %[" #TEMP3 "], %[" #TEMP3 "], 937 \n\t" \ + "addiu %[" #TEMP1 "], %[" #TEMP1 "], 1812 \n\t" \ + "sra %[" #TEMP3 "], %[" #TEMP3 "], 9 \n\t" \ + "sra %[" #TEMP1 "], %[" #TEMP1 "], 9 \n\t" + +// macro for one vertical pass in FTransform +// temp0..temp15 holds tmp[0]..tmp[15] +// A..D - offsets in bytes to store to out buffer +// TEMP0, TEMP4, TEMP8 and TEMP12 - registers for corresponding tmp elements +#define VERTICAL_PASS(A, B, C, D, TEMP0, TEMP4, TEMP8, TEMP12) \ + "addu %[temp16], %[" #TEMP0 "], %[" #TEMP12 "] \n\t" \ + "subu %[temp19], %[" #TEMP0 "], %[" #TEMP12 "] \n\t" \ + "addu %[temp17], %[" #TEMP4 "], %[" #TEMP8 "] \n\t" \ + "subu %[temp18], %[" #TEMP4 "], %[" #TEMP8 "] \n\t" \ + "mul %[" #TEMP8 "], %[temp19], %[c2217] \n\t" \ + "mul %[" #TEMP12 "], %[temp18], %[c2217] \n\t" \ + "mul %[" #TEMP4 "], %[temp19], %[c5352] \n\t" \ + "mul %[temp18], %[temp18], %[c5352] \n\t" \ + "addiu %[temp16], %[temp16], 7 \n\t" \ + "addu %[" #TEMP0 "], %[temp16], %[temp17] \n\t" \ + "sra %[" #TEMP0 "], %[" #TEMP0 "], 4 \n\t" \ + "addu %[" #TEMP12 "], %[" #TEMP12 "], %[" #TEMP4 "] \n\t" \ + "subu %[" #TEMP4 "], %[temp16], %[temp17] \n\t" \ + "sra %[" #TEMP4 "], %[" #TEMP4 "], 4 \n\t" \ + "addiu %[" #TEMP8 "], %[" #TEMP8 "], 30000 \n\t" \ + "addiu %[" #TEMP12 "], %[" #TEMP12 "], 12000 \n\t" \ + "addiu %[" #TEMP8 "], %[" #TEMP8 "], 21000 \n\t" \ + "subu %[" #TEMP8 "], %[" #TEMP8 "], %[temp18] \n\t" \ + "sra %[" #TEMP12 "], %[" #TEMP12 "], 16 \n\t" \ + "sra %[" #TEMP8 "], %[" #TEMP8 "], 16 \n\t" \ + "addiu %[temp16], %[" #TEMP12 "], 1 \n\t" \ + "movn %[" #TEMP12 "], %[temp16], %[temp19] \n\t" \ + "sh %[" #TEMP0 "], " #A "(%[temp20]) \n\t" \ + "sh %[" #TEMP4 "], " #C "(%[temp20]) \n\t" \ + "sh %[" #TEMP8 "], " #D "(%[temp20]) \n\t" \ + "sh %[" #TEMP12 "], " #B "(%[temp20]) \n\t" + +static void FTransform_MIPSdspR2(const uint8_t* src, const uint8_t* ref, + int16_t* out) { + const int c2217 = 2217; + const int c5352 = 5352; + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8; + int temp9, temp10, temp11, temp12, temp13, temp14, temp15, temp16; + int temp17, temp18, temp19, temp20; + const int* const args[3] = + { (const int*)src, (const int*)ref, (const int*)out }; + + __asm__ volatile ( + HORIZONTAL_PASS(0, temp0, temp1, temp2, temp3) + HORIZONTAL_PASS(1, temp4, temp5, temp6, temp7) + HORIZONTAL_PASS(2, temp8, temp9, temp10, temp11) + HORIZONTAL_PASS(3, temp12, temp13, temp14, temp15) + "lw %[temp20], 8(%[args]) \n\t" + VERTICAL_PASS(0, 8, 16, 24, temp0, temp4, temp8, temp12) + VERTICAL_PASS(2, 10, 18, 26, temp1, temp5, temp9, temp13) + VERTICAL_PASS(4, 12, 20, 28, temp2, temp6, temp10, temp14) + VERTICAL_PASS(6, 14, 22, 30, temp3, temp7, temp11, temp15) + OUTPUT_EARLY_CLOBBER_REGS_18(), + [temp0]"=&r"(temp0), [temp19]"=&r"(temp19), [temp20]"=&r"(temp20) + : [args]"r"(args), [c2217]"r"(c2217), [c5352]"r"(c5352) + : "memory", "hi", "lo" + ); +} + +#undef VERTICAL_PASS +#undef HORIZONTAL_PASS + +static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in, + uint8_t* dst) { + int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9; + int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17, temp18; + + __asm__ volatile ( + "ulw %[temp1], 0(%[in]) \n\t" + "ulw %[temp2], 16(%[in]) \n\t" + LOAD_IN_X2(temp5, temp6, 24, 26) + ADD_SUB_HALVES(temp3, temp4, temp1, temp2) + LOAD_IN_X2(temp1, temp2, 8, 10) + MUL_SHIFT_SUM(temp7, temp8, temp9, temp10, temp11, temp12, temp13, temp14, + temp10, temp8, temp9, temp7, temp1, temp2, temp5, temp6, + temp13, temp11, temp14, temp12) + INSERT_HALF_X2(temp8, temp7, temp10, temp9) + "ulw %[temp17], 4(%[in]) \n\t" + "ulw %[temp18], 20(%[in]) \n\t" + ADD_SUB_HALVES(temp1, temp2, temp3, temp8) + ADD_SUB_HALVES(temp5, temp6, temp4, temp7) + ADD_SUB_HALVES(temp7, temp8, temp17, temp18) + LOAD_IN_X2(temp17, temp18, 12, 14) + LOAD_IN_X2(temp9, temp10, 28, 30) + MUL_SHIFT_SUM(temp11, temp12, temp13, temp14, temp15, temp16, temp4, temp17, + temp12, temp14, temp11, temp13, temp17, temp18, temp9, temp10, + temp15, temp4, temp16, temp17) + INSERT_HALF_X2(temp11, temp12, temp13, temp14) + ADD_SUB_HALVES(temp17, temp8, temp8, temp11) + ADD_SUB_HALVES(temp3, temp4, temp7, temp12) + + // horizontal + SRA_16(temp9, temp10, temp11, temp12, temp1, temp2, temp5, temp6) + INSERT_HALF_X2(temp1, temp6, temp5, temp2) + SRA_16(temp13, temp14, temp15, temp16, temp3, temp4, temp17, temp8) + "repl.ph %[temp2], 0x4 \n\t" + INSERT_HALF_X2(temp3, temp8, temp17, temp4) + "addq.ph %[temp1], %[temp1], %[temp2] \n\t" + "addq.ph %[temp6], %[temp6], %[temp2] \n\t" + ADD_SUB_HALVES(temp2, temp4, temp1, temp3) + ADD_SUB_HALVES(temp5, temp7, temp6, temp8) + MUL_SHIFT_SUM(temp1, temp3, temp6, temp8, temp9, temp13, temp17, temp18, + temp3, temp13, temp1, temp9, temp9, temp13, temp11, temp15, + temp6, temp17, temp8, temp18) + MUL_SHIFT_SUM(temp6, temp8, temp18, temp17, temp11, temp15, temp12, temp16, + temp8, temp15, temp6, temp11, temp12, temp16, temp10, temp14, + temp18, temp12, temp17, temp16) + INSERT_HALF_X2(temp1, temp3, temp9, temp13) + INSERT_HALF_X2(temp6, temp8, temp11, temp15) + SHIFT_R_SUM_X2(temp9, temp10, temp11, temp12, temp13, temp14, temp15, + temp16, temp2, temp4, temp5, temp7, temp3, temp1, temp8, + temp6) + PACK_2_HALVES_TO_WORD(temp1, temp2, temp3, temp4, temp9, temp12, temp13, + temp16, temp11, temp10, temp15, temp14) + LOAD_WITH_OFFSET_X4(temp10, temp11, temp14, temp15, ref, + 0, 0, 0, 0, + 0, 1, 2, 3, + BPS) + CONVERT_2_BYTES_TO_HALF(temp5, temp6, temp7, temp8, temp17, temp18, temp10, + temp11, temp10, temp11, temp14, temp15) + STORE_SAT_SUM_X2(temp5, temp6, temp7, temp8, temp17, temp18, temp10, temp11, + temp9, temp12, temp1, temp2, temp13, temp16, temp3, temp4, + dst, 0, 1, 2, 3, BPS) + + OUTPUT_EARLY_CLOBBER_REGS_18() + : [dst]"r"(dst), [in]"r"(in), [kC1]"r"(kC1), [kC2]"r"(kC2), [ref]"r"(ref) + : "memory", "hi", "lo" + ); +} + +static void ITransform_MIPSdspR2(const uint8_t* ref, const int16_t* in, + uint8_t* dst, int do_two) { + ITransformOne(ref, in, dst); + if (do_two) { + ITransformOne(ref + 4, in + 16, dst + 4); + } +} + +static int Disto4x4_MIPSdspR2(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9; + int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17; + + __asm__ volatile ( + LOAD_WITH_OFFSET_X4(temp1, temp2, temp3, temp4, a, + 0, 0, 0, 0, + 0, 1, 2, 3, + BPS) + CONVERT_2_BYTES_TO_HALF(temp5, temp6, temp7, temp8, temp9,temp10, temp11, + temp12, temp1, temp2, temp3, temp4) + ADD_SUB_HALVES_X4(temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, + temp5, temp6, temp7, temp8, temp9, temp10, temp11, temp12) + PACK_2_HALVES_TO_WORD(temp9, temp10, temp11, temp12, temp1, temp3, temp5, + temp7, temp2, temp4, temp6, temp8) + ADD_SUB_HALVES_X4(temp2, temp4, temp6, temp8, temp9, temp1, temp3, temp10, + temp1, temp9, temp3, temp10, temp5, temp11, temp7, temp12) + ADD_SUB_HALVES_X4(temp5, temp11, temp7, temp2, temp9, temp3, temp6, temp12, + temp2, temp9, temp6, temp3, temp4, temp1, temp8, temp10) + ADD_SUB_HALVES_X4(temp1, temp4, temp10, temp8, temp7, temp11, temp5, temp2, + temp5, temp7, temp11, temp2, temp9, temp6, temp3, temp12) + ABS_X8(temp1, temp4, temp10, temp8, temp7, temp11, temp5, temp2) + LOAD_WITH_OFFSET_X4(temp3, temp6, temp9, temp12, w, + 0, 4, 8, 12, + 0, 0, 0, 0, + 0) + LOAD_WITH_OFFSET_X4(temp13, temp14, temp15, temp16, w, + 0, 4, 8, 12, + 1, 1, 1, 1, + 16) + MUL_HALF(temp17, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, + temp9, temp10, temp11, temp12, temp13, temp14, temp15, temp16) + LOAD_WITH_OFFSET_X4(temp1, temp2, temp3, temp4, b, + 0, 0, 0, 0, + 0, 1, 2, 3, + BPS) + CONVERT_2_BYTES_TO_HALF(temp5,temp6, temp7, temp8, temp9,temp10, temp11, + temp12, temp1, temp2, temp3, temp4) + ADD_SUB_HALVES_X4(temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, + temp5, temp6, temp7, temp8, temp9, temp10, temp11, temp12) + PACK_2_HALVES_TO_WORD(temp9, temp10, temp11, temp12, temp1, temp3, temp5, + temp7, temp2, temp4, temp6, temp8) + ADD_SUB_HALVES_X4(temp2, temp4, temp6, temp8, temp9, temp1, temp3, temp10, + temp1, temp9, temp3, temp10, temp5, temp11, temp7, temp12) + ADD_SUB_HALVES_X4(temp5, temp11, temp7, temp2, temp9, temp3, temp6, temp12, + temp2, temp9, temp6, temp3, temp4, temp1, temp8, temp10) + ADD_SUB_HALVES_X4(temp1, temp4, temp10, temp8, temp7, temp11, temp5, temp2, + temp5, temp7, temp11, temp2, temp9, temp6, temp3, temp12) + ABS_X8(temp1, temp4, temp10, temp8, temp7, temp11, temp5, temp2) + LOAD_WITH_OFFSET_X4(temp3, temp6, temp9, temp12, w, + 0, 4, 8, 12, + 0, 0, 0, 0, + 0) + LOAD_WITH_OFFSET_X4(temp13, temp14, temp15, temp16, w, + 0, 4, 8, 12, + 1, 1, 1, 1, + 16) + MUL_HALF(temp3, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, + temp9, temp10, temp11, temp12, temp13, temp14, temp15, temp16) + OUTPUT_EARLY_CLOBBER_REGS_17() + : [a]"r"(a), [b]"r"(b), [w]"r"(w) + : "memory", "hi", "lo" + ); + return abs(temp3 - temp17) >> 5; +} + +static int Disto16x16_MIPSdspR2(const uint8_t* const a, + const uint8_t* const b, + const uint16_t* const w) { + int D = 0; + int x, y; + for (y = 0; y < 16 * BPS; y += 4 * BPS) { + for (x = 0; x < 16; x += 4) { + D += Disto4x4_MIPSdspR2(a + x + y, b + x + y, w); + } + } + return D; +} + +//------------------------------------------------------------------------------ +// Intra predictions + +#define FILL_PART(J, SIZE) \ + "usw %[value], 0+" #J "*" XSTR(BPS) "(%[dst]) \n\t" \ + "usw %[value], 4+" #J "*" XSTR(BPS) "(%[dst]) \n\t" \ + ".if " #SIZE " == 16 \n\t" \ + "usw %[value], 8+" #J "*" XSTR(BPS) "(%[dst]) \n\t" \ + "usw %[value], 12+" #J "*" XSTR(BPS) "(%[dst]) \n\t" \ + ".endif \n\t" + +#define FILL_8_OR_16(DST, VALUE, SIZE) do { \ + int value = (VALUE); \ + __asm__ volatile ( \ + "replv.qb %[value], %[value] \n\t" \ + FILL_PART( 0, SIZE) \ + FILL_PART( 1, SIZE) \ + FILL_PART( 2, SIZE) \ + FILL_PART( 3, SIZE) \ + FILL_PART( 4, SIZE) \ + FILL_PART( 5, SIZE) \ + FILL_PART( 6, SIZE) \ + FILL_PART( 7, SIZE) \ + ".if " #SIZE " == 16 \n\t" \ + FILL_PART( 8, 16) \ + FILL_PART( 9, 16) \ + FILL_PART(10, 16) \ + FILL_PART(11, 16) \ + FILL_PART(12, 16) \ + FILL_PART(13, 16) \ + FILL_PART(14, 16) \ + FILL_PART(15, 16) \ + ".endif \n\t" \ + : [value]"+&r"(value) \ + : [dst]"r"((DST)) \ + : "memory" \ + ); \ +} while (0) + +#define VERTICAL_PRED(DST, TOP, SIZE) \ +static WEBP_INLINE void VerticalPred##SIZE(uint8_t* (DST), \ + const uint8_t* (TOP)) { \ + int j; \ + if ((TOP)) { \ + for (j = 0; j < (SIZE); ++j) memcpy((DST) + j * BPS, (TOP), (SIZE)); \ + } else { \ + FILL_8_OR_16((DST), 127, (SIZE)); \ + } \ +} + +VERTICAL_PRED(dst, top, 8) +VERTICAL_PRED(dst, top, 16) + +#undef VERTICAL_PRED + +#define HORIZONTAL_PRED(DST, LEFT, SIZE) \ +static WEBP_INLINE void HorizontalPred##SIZE(uint8_t* (DST), \ + const uint8_t* (LEFT)) { \ + if (LEFT) { \ + int j; \ + for (j = 0; j < (SIZE); ++j) { \ + memset((DST) + j * BPS, (LEFT)[j], (SIZE)); \ + } \ + } else { \ + FILL_8_OR_16((DST), 129, (SIZE)); \ + } \ +} + +HORIZONTAL_PRED(dst, left, 8) +HORIZONTAL_PRED(dst, left, 16) + +#undef HORIZONTAL_PRED + +#define CLIPPING() \ + "preceu.ph.qbl %[temp2], %[temp0] \n\t" \ + "preceu.ph.qbr %[temp0], %[temp0] \n\t" \ + "preceu.ph.qbl %[temp3], %[temp1] \n\t" \ + "preceu.ph.qbr %[temp1], %[temp1] \n\t" \ + "addu.ph %[temp2], %[temp2], %[leftY_1] \n\t" \ + "addu.ph %[temp0], %[temp0], %[leftY_1] \n\t" \ + "addu.ph %[temp3], %[temp3], %[leftY_1] \n\t" \ + "addu.ph %[temp1], %[temp1], %[leftY_1] \n\t" \ + "shll_s.ph %[temp2], %[temp2], 7 \n\t" \ + "shll_s.ph %[temp0], %[temp0], 7 \n\t" \ + "shll_s.ph %[temp3], %[temp3], 7 \n\t" \ + "shll_s.ph %[temp1], %[temp1], 7 \n\t" \ + "precrqu_s.qb.ph %[temp0], %[temp2], %[temp0] \n\t" \ + "precrqu_s.qb.ph %[temp1], %[temp3], %[temp1] \n\t" + +#define CLIP_8B_TO_DST(DST, LEFT, TOP, SIZE) do { \ + int leftY_1 = ((int)(LEFT)[y] << 16) + (LEFT)[y]; \ + int temp0, temp1, temp2, temp3; \ + __asm__ volatile ( \ + "replv.ph %[leftY_1], %[leftY_1] \n\t" \ + "ulw %[temp0], 0(%[top]) \n\t" \ + "ulw %[temp1], 4(%[top]) \n\t" \ + "subu.ph %[leftY_1], %[leftY_1], %[left_1] \n\t" \ + CLIPPING() \ + "usw %[temp0], 0(%[dst]) \n\t" \ + "usw %[temp1], 4(%[dst]) \n\t" \ + ".if " #SIZE " == 16 \n\t" \ + "ulw %[temp0], 8(%[top]) \n\t" \ + "ulw %[temp1], 12(%[top]) \n\t" \ + CLIPPING() \ + "usw %[temp0], 8(%[dst]) \n\t" \ + "usw %[temp1], 12(%[dst]) \n\t" \ + ".endif \n\t" \ + : [leftY_1]"+&r"(leftY_1), [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), \ + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3) \ + : [left_1]"r"(left_1), [top]"r"((TOP)), [dst]"r"((DST)) \ + : "memory" \ + ); \ +} while (0) + +#define CLIP_TO_DST(DST, LEFT, TOP, SIZE) do { \ + int y; \ + const int left_1 = ((int)(LEFT)[-1] << 16) + (LEFT)[-1]; \ + for (y = 0; y < (SIZE); ++y) { \ + CLIP_8B_TO_DST((DST), (LEFT), (TOP), (SIZE)); \ + (DST) += BPS; \ + } \ +} while (0) + +#define TRUE_MOTION(DST, LEFT, TOP, SIZE) \ +static WEBP_INLINE void TrueMotion##SIZE(uint8_t* (DST), const uint8_t* (LEFT),\ + const uint8_t* (TOP)) { \ + if ((LEFT) != NULL) { \ + if ((TOP) != NULL) { \ + CLIP_TO_DST((DST), (LEFT), (TOP), (SIZE)); \ + } else { \ + HorizontalPred##SIZE((DST), (LEFT)); \ + } \ + } else { \ + /* true motion without left samples (hence: with default 129 value) */ \ + /* is equivalent to VE prediction where you just copy the top samples. */ \ + /* Note that if top samples are not available, the default value is */ \ + /* then 129, and not 127 as in the VerticalPred case. */ \ + if ((TOP) != NULL) { \ + VerticalPred##SIZE((DST), (TOP)); \ + } else { \ + FILL_8_OR_16((DST), 129, (SIZE)); \ + } \ + } \ +} + +TRUE_MOTION(dst, left, top, 8) +TRUE_MOTION(dst, left, top, 16) + +#undef TRUE_MOTION +#undef CLIP_TO_DST +#undef CLIP_8B_TO_DST +#undef CLIPPING + +static WEBP_INLINE void DCMode16(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { + int DC, DC1; + int temp0, temp1, temp2, temp3; + + __asm__ volatile( + "beqz %[top], 2f \n\t" + LOAD_WITH_OFFSET_X4(temp0, temp1, temp2, temp3, top, + 0, 4, 8, 12, + 0, 0, 0, 0, + 0) + "raddu.w.qb %[temp0], %[temp0] \n\t" + "raddu.w.qb %[temp1], %[temp1] \n\t" + "raddu.w.qb %[temp2], %[temp2] \n\t" + "raddu.w.qb %[temp3], %[temp3] \n\t" + "addu %[temp0], %[temp0], %[temp1] \n\t" + "addu %[temp2], %[temp2], %[temp3] \n\t" + "addu %[DC], %[temp0], %[temp2] \n\t" + "move %[DC1], %[DC] \n\t" + "beqz %[left], 1f \n\t" + LOAD_WITH_OFFSET_X4(temp0, temp1, temp2, temp3, left, + 0, 4, 8, 12, + 0, 0, 0, 0, + 0) + "raddu.w.qb %[temp0], %[temp0] \n\t" + "raddu.w.qb %[temp1], %[temp1] \n\t" + "raddu.w.qb %[temp2], %[temp2] \n\t" + "raddu.w.qb %[temp3], %[temp3] \n\t" + "addu %[temp0], %[temp0], %[temp1] \n\t" + "addu %[temp2], %[temp2], %[temp3] \n\t" + "addu %[DC1], %[temp0], %[temp2] \n\t" + "1: \n\t" + "addu %[DC], %[DC], %[DC1] \n\t" + "j 3f \n\t" + "2: \n\t" + "beqz %[left], 4f \n\t" + LOAD_WITH_OFFSET_X4(temp0, temp1, temp2, temp3, left, + 0, 4, 8, 12, + 0, 0, 0, 0, + 0) + "raddu.w.qb %[temp0], %[temp0] \n\t" + "raddu.w.qb %[temp1], %[temp1] \n\t" + "raddu.w.qb %[temp2], %[temp2] \n\t" + "raddu.w.qb %[temp3], %[temp3] \n\t" + "addu %[temp0], %[temp0], %[temp1] \n\t" + "addu %[temp2], %[temp2], %[temp3] \n\t" + "addu %[DC], %[temp0], %[temp2] \n\t" + "addu %[DC], %[DC], %[DC] \n\t" + "3: \n\t" + "shra_r.w %[DC], %[DC], 5 \n\t" + "j 5f \n\t" + "4: \n\t" + "li %[DC], 0x80 \n\t" + "5: \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [DC]"=&r"(DC), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [DC1]"=&r"(DC1) + : [left]"r"(left), [top]"r"(top) + : "memory" + ); + + FILL_8_OR_16(dst, DC, 16); +} + +static WEBP_INLINE void DCMode8(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { + int DC, DC1; + int temp0, temp1, temp2, temp3; + + __asm__ volatile( + "beqz %[top], 2f \n\t" + "ulw %[temp0], 0(%[top]) \n\t" + "ulw %[temp1], 4(%[top]) \n\t" + "raddu.w.qb %[temp0], %[temp0] \n\t" + "raddu.w.qb %[temp1], %[temp1] \n\t" + "addu %[DC], %[temp0], %[temp1] \n\t" + "move %[DC1], %[DC] \n\t" + "beqz %[left], 1f \n\t" + "ulw %[temp2], 0(%[left]) \n\t" + "ulw %[temp3], 4(%[left]) \n\t" + "raddu.w.qb %[temp2], %[temp2] \n\t" + "raddu.w.qb %[temp3], %[temp3] \n\t" + "addu %[DC1], %[temp2], %[temp3] \n\t" + "1: \n\t" + "addu %[DC], %[DC], %[DC1] \n\t" + "j 3f \n\t" + "2: \n\t" + "beqz %[left], 4f \n\t" + "ulw %[temp2], 0(%[left]) \n\t" + "ulw %[temp3], 4(%[left]) \n\t" + "raddu.w.qb %[temp2], %[temp2] \n\t" + "raddu.w.qb %[temp3], %[temp3] \n\t" + "addu %[DC], %[temp2], %[temp3] \n\t" + "addu %[DC], %[DC], %[DC] \n\t" + "3: \n\t" + "shra_r.w %[DC], %[DC], 4 \n\t" + "j 5f \n\t" + "4: \n\t" + "li %[DC], 0x80 \n\t" + "5: \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [DC]"=&r"(DC), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [DC1]"=&r"(DC1) + : [left]"r"(left), [top]"r"(top) + : "memory" + ); + + FILL_8_OR_16(dst, DC, 8); +} + +static void DC4(uint8_t* dst, const uint8_t* top) { + int temp0, temp1; + __asm__ volatile( + "ulw %[temp0], 0(%[top]) \n\t" + "ulw %[temp1], -5(%[top]) \n\t" + "raddu.w.qb %[temp0], %[temp0] \n\t" + "raddu.w.qb %[temp1], %[temp1] \n\t" + "addu %[temp0], %[temp0], %[temp1] \n\t" + "addiu %[temp0], %[temp0], 4 \n\t" + "srl %[temp0], %[temp0], 3 \n\t" + "replv.qb %[temp0], %[temp0] \n\t" + "usw %[temp0], 0*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp0], 1*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp0], 2*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp0], 3*" XSTR(BPS) "(%[dst]) \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1) + : [top]"r"(top), [dst]"r"(dst) + : "memory" + ); +} + +static void TM4(uint8_t* dst, const uint8_t* top) { + int a10, a32, temp0, temp1, temp2, temp3, temp4, temp5; + const int c35 = 0xff00ff; + __asm__ volatile ( + "lbu %[temp1], 0(%[top]) \n\t" + "lbu %[a10], 1(%[top]) \n\t" + "lbu %[temp2], 2(%[top]) \n\t" + "lbu %[a32], 3(%[top]) \n\t" + "ulw %[temp0], -5(%[top]) \n\t" + "lbu %[temp4], -1(%[top]) \n\t" + "append %[a10], %[temp1], 16 \n\t" + "append %[a32], %[temp2], 16 \n\t" + "replv.ph %[temp4], %[temp4] \n\t" + "shrl.ph %[temp1], %[temp0], 8 \n\t" + "and %[temp0], %[temp0], %[c35] \n\t" + "subu.ph %[temp1], %[temp1], %[temp4] \n\t" + "subu.ph %[temp0], %[temp0], %[temp4] \n\t" + "srl %[temp2], %[temp1], 16 \n\t" + "srl %[temp3], %[temp0], 16 \n\t" + "replv.ph %[temp2], %[temp2] \n\t" + "replv.ph %[temp3], %[temp3] \n\t" + "replv.ph %[temp4], %[temp1] \n\t" + "replv.ph %[temp5], %[temp0] \n\t" + "addu.ph %[temp0], %[temp3], %[a10] \n\t" + "addu.ph %[temp1], %[temp3], %[a32] \n\t" + "addu.ph %[temp3], %[temp2], %[a10] \n\t" + "addu.ph %[temp2], %[temp2], %[a32] \n\t" + "shll_s.ph %[temp0], %[temp0], 7 \n\t" + "shll_s.ph %[temp1], %[temp1], 7 \n\t" + "shll_s.ph %[temp3], %[temp3], 7 \n\t" + "shll_s.ph %[temp2], %[temp2], 7 \n\t" + "precrqu_s.qb.ph %[temp0], %[temp1], %[temp0] \n\t" + "precrqu_s.qb.ph %[temp1], %[temp2], %[temp3] \n\t" + "addu.ph %[temp2], %[temp5], %[a10] \n\t" + "addu.ph %[temp3], %[temp5], %[a32] \n\t" + "addu.ph %[temp5], %[temp4], %[a10] \n\t" + "addu.ph %[temp4], %[temp4], %[a32] \n\t" + "shll_s.ph %[temp2], %[temp2], 7 \n\t" + "shll_s.ph %[temp3], %[temp3], 7 \n\t" + "shll_s.ph %[temp4], %[temp4], 7 \n\t" + "shll_s.ph %[temp5], %[temp5], 7 \n\t" + "precrqu_s.qb.ph %[temp2], %[temp3], %[temp2] \n\t" + "precrqu_s.qb.ph %[temp3], %[temp4], %[temp5] \n\t" + "usw %[temp1], 0*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp0], 1*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp3], 2*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp2], 3*" XSTR(BPS) "(%[dst]) \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [a10]"=&r"(a10), [a32]"=&r"(a32) + : [c35]"r"(c35), [top]"r"(top), [dst]"r"(dst) + : "memory" + ); +} + +static void VE4(uint8_t* dst, const uint8_t* top) { + int temp0, temp1, temp2, temp3, temp4, temp5, temp6; + __asm__ volatile( + "ulw %[temp0], -1(%[top]) \n\t" + "ulh %[temp1], 3(%[top]) \n\t" + "preceu.ph.qbr %[temp2], %[temp0] \n\t" + "preceu.ph.qbl %[temp3], %[temp0] \n\t" + "preceu.ph.qbr %[temp4], %[temp1] \n\t" + "packrl.ph %[temp5], %[temp3], %[temp2] \n\t" + "packrl.ph %[temp6], %[temp4], %[temp3] \n\t" + "shll.ph %[temp5], %[temp5], 1 \n\t" + "shll.ph %[temp6], %[temp6], 1 \n\t" + "addq.ph %[temp2], %[temp5], %[temp2] \n\t" + "addq.ph %[temp6], %[temp6], %[temp4] \n\t" + "addq.ph %[temp2], %[temp2], %[temp3] \n\t" + "addq.ph %[temp6], %[temp6], %[temp3] \n\t" + "shra_r.ph %[temp2], %[temp2], 2 \n\t" + "shra_r.ph %[temp6], %[temp6], 2 \n\t" + "precr.qb.ph %[temp4], %[temp6], %[temp2] \n\t" + "usw %[temp4], 0*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp4], 1*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp4], 2*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp4], 3*" XSTR(BPS) "(%[dst]) \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6) + : [top]"r"(top), [dst]"r"(dst) + : "memory" + ); +} + +static void HE4(uint8_t* dst, const uint8_t* top) { + int temp0, temp1, temp2, temp3, temp4, temp5, temp6; + __asm__ volatile( + "ulw %[temp0], -4(%[top]) \n\t" + "lbu %[temp1], -5(%[top]) \n\t" + "preceu.ph.qbr %[temp2], %[temp0] \n\t" + "preceu.ph.qbl %[temp3], %[temp0] \n\t" + "replv.ph %[temp4], %[temp1] \n\t" + "packrl.ph %[temp5], %[temp3], %[temp2] \n\t" + "packrl.ph %[temp6], %[temp2], %[temp4] \n\t" + "shll.ph %[temp5], %[temp5], 1 \n\t" + "shll.ph %[temp6], %[temp6], 1 \n\t" + "addq.ph %[temp3], %[temp3], %[temp5] \n\t" + "addq.ph %[temp3], %[temp3], %[temp2] \n\t" + "addq.ph %[temp2], %[temp2], %[temp6] \n\t" + "addq.ph %[temp2], %[temp2], %[temp4] \n\t" + "shra_r.ph %[temp3], %[temp3], 2 \n\t" + "shra_r.ph %[temp2], %[temp2], 2 \n\t" + "replv.qb %[temp0], %[temp3] \n\t" + "replv.qb %[temp1], %[temp2] \n\t" + "srl %[temp3], %[temp3], 16 \n\t" + "srl %[temp2], %[temp2], 16 \n\t" + "replv.qb %[temp3], %[temp3] \n\t" + "replv.qb %[temp2], %[temp2] \n\t" + "usw %[temp3], 0*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp0], 1*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp2], 2*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp1], 3*" XSTR(BPS) "(%[dst]) \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6) + : [top]"r"(top), [dst]"r"(dst) + : "memory" + ); +} + +static void RD4(uint8_t* dst, const uint8_t* top) { + int temp0, temp1, temp2, temp3, temp4, temp5; + int temp6, temp7, temp8, temp9, temp10, temp11; + __asm__ volatile( + "ulw %[temp0], -5(%[top]) \n\t" + "ulw %[temp1], -1(%[top]) \n\t" + "preceu.ph.qbl %[temp2], %[temp0] \n\t" + "preceu.ph.qbr %[temp3], %[temp0] \n\t" + "preceu.ph.qbr %[temp4], %[temp1] \n\t" + "preceu.ph.qbl %[temp5], %[temp1] \n\t" + "packrl.ph %[temp6], %[temp2], %[temp3] \n\t" + "packrl.ph %[temp7], %[temp4], %[temp2] \n\t" + "packrl.ph %[temp8], %[temp5], %[temp4] \n\t" + "shll.ph %[temp6], %[temp6], 1 \n\t" + "addq.ph %[temp9], %[temp2], %[temp6] \n\t" + "shll.ph %[temp7], %[temp7], 1 \n\t" + "addq.ph %[temp9], %[temp9], %[temp3] \n\t" + "shll.ph %[temp8], %[temp8], 1 \n\t" + "shra_r.ph %[temp9], %[temp9], 2 \n\t" + "addq.ph %[temp10], %[temp4], %[temp7] \n\t" + "addq.ph %[temp11], %[temp5], %[temp8] \n\t" + "addq.ph %[temp10], %[temp10], %[temp2] \n\t" + "addq.ph %[temp11], %[temp11], %[temp4] \n\t" + "shra_r.ph %[temp10], %[temp10], 2 \n\t" + "shra_r.ph %[temp11], %[temp11], 2 \n\t" + "lbu %[temp0], 3(%[top]) \n\t" + "lbu %[temp1], 2(%[top]) \n\t" + "lbu %[temp2], 1(%[top]) \n\t" + "sll %[temp1], %[temp1], 1 \n\t" + "addu %[temp0], %[temp0], %[temp1] \n\t" + "addu %[temp0], %[temp0], %[temp2] \n\t" + "precr.qb.ph %[temp9], %[temp10], %[temp9] \n\t" + "shra_r.w %[temp0], %[temp0], 2 \n\t" + "precr.qb.ph %[temp10], %[temp11], %[temp10] \n\t" + "usw %[temp9], 3*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp10], 1*" XSTR(BPS) "(%[dst]) \n\t" + "prepend %[temp9], %[temp11], 8 \n\t" + "prepend %[temp10], %[temp0], 8 \n\t" + "usw %[temp9], 2*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp10], 0*" XSTR(BPS) "(%[dst]) \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), + [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11) + : [top]"r"(top), [dst]"r"(dst) + : "memory" + ); +} + +static void VR4(uint8_t* dst, const uint8_t* top) { + int temp0, temp1, temp2, temp3, temp4; + int temp5, temp6, temp7, temp8, temp9; + __asm__ volatile ( + "ulw %[temp0], -4(%[top]) \n\t" + "ulw %[temp1], 0(%[top]) \n\t" + "preceu.ph.qbl %[temp2], %[temp0] \n\t" + "preceu.ph.qbr %[temp0], %[temp0] \n\t" + "preceu.ph.qbla %[temp3], %[temp1] \n\t" + "preceu.ph.qbra %[temp1], %[temp1] \n\t" + "packrl.ph %[temp7], %[temp3], %[temp2] \n\t" + "addqh_r.ph %[temp4], %[temp1], %[temp3] \n\t" + "move %[temp6], %[temp1] \n\t" + "append %[temp1], %[temp2], 16 \n\t" + "shll.ph %[temp9], %[temp6], 1 \n\t" + "addqh_r.ph %[temp5], %[temp7], %[temp6] \n\t" + "shll.ph %[temp8], %[temp7], 1 \n\t" + "addu.ph %[temp3], %[temp7], %[temp3] \n\t" + "addu.ph %[temp1], %[temp1], %[temp6] \n\t" + "packrl.ph %[temp7], %[temp2], %[temp0] \n\t" + "addu.ph %[temp6], %[temp0], %[temp2] \n\t" + "addu.ph %[temp3], %[temp3], %[temp9] \n\t" + "addu.ph %[temp1], %[temp1], %[temp8] \n\t" + "shll.ph %[temp7], %[temp7], 1 \n\t" + "shra_r.ph %[temp3], %[temp3], 2 \n\t" + "shra_r.ph %[temp1], %[temp1], 2 \n\t" + "addu.ph %[temp6], %[temp6], %[temp7] \n\t" + "shra_r.ph %[temp6], %[temp6], 2 \n\t" + "precrq.ph.w %[temp8], %[temp4], %[temp5] \n\t" + "append %[temp4], %[temp5], 16 \n\t" + "precrq.ph.w %[temp2], %[temp3], %[temp1] \n\t" + "append %[temp3], %[temp1], 16 \n\t" + "precr.qb.ph %[temp8], %[temp8], %[temp4] \n\t" + "precr.qb.ph %[temp3], %[temp2], %[temp3] \n\t" + "usw %[temp8], 0*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp3], 1*" XSTR(BPS) "(%[dst]) \n\t" + "append %[temp3], %[temp6], 8 \n\t" + "srl %[temp6], %[temp6], 16 \n\t" + "append %[temp8], %[temp6], 8 \n\t" + "usw %[temp3], 3*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp8], 2*" XSTR(BPS) "(%[dst]) \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), + [temp9]"=&r"(temp9) + : [top]"r"(top), [dst]"r"(dst) + : "memory" + ); +} + +static void LD4(uint8_t* dst, const uint8_t* top) { + int temp0, temp1, temp2, temp3, temp4, temp5; + int temp6, temp7, temp8, temp9, temp10, temp11; + __asm__ volatile( + "ulw %[temp0], 0(%[top]) \n\t" + "ulw %[temp1], 4(%[top]) \n\t" + "preceu.ph.qbl %[temp2], %[temp0] \n\t" + "preceu.ph.qbr %[temp3], %[temp0] \n\t" + "preceu.ph.qbr %[temp4], %[temp1] \n\t" + "preceu.ph.qbl %[temp5], %[temp1] \n\t" + "packrl.ph %[temp6], %[temp2], %[temp3] \n\t" + "packrl.ph %[temp7], %[temp4], %[temp2] \n\t" + "packrl.ph %[temp8], %[temp5], %[temp4] \n\t" + "shll.ph %[temp6], %[temp6], 1 \n\t" + "addq.ph %[temp9], %[temp2], %[temp6] \n\t" + "shll.ph %[temp7], %[temp7], 1 \n\t" + "addq.ph %[temp9], %[temp9], %[temp3] \n\t" + "shll.ph %[temp8], %[temp8], 1 \n\t" + "shra_r.ph %[temp9], %[temp9], 2 \n\t" + "addq.ph %[temp10], %[temp4], %[temp7] \n\t" + "addq.ph %[temp11], %[temp5], %[temp8] \n\t" + "addq.ph %[temp10], %[temp10], %[temp2] \n\t" + "addq.ph %[temp11], %[temp11], %[temp4] \n\t" + "shra_r.ph %[temp10], %[temp10], 2 \n\t" + "shra_r.ph %[temp11], %[temp11], 2 \n\t" + "srl %[temp1], %[temp1], 24 \n\t" + "sll %[temp1], %[temp1], 1 \n\t" + "raddu.w.qb %[temp5], %[temp5] \n\t" + "precr.qb.ph %[temp9], %[temp10], %[temp9] \n\t" + "precr.qb.ph %[temp10], %[temp11], %[temp10] \n\t" + "addu %[temp1], %[temp1], %[temp5] \n\t" + "shra_r.w %[temp1], %[temp1], 2 \n\t" + "usw %[temp9], 0*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp10], 2*" XSTR(BPS) "(%[dst]) \n\t" + "prepend %[temp9], %[temp11], 8 \n\t" + "prepend %[temp10], %[temp1], 8 \n\t" + "usw %[temp9], 1*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp10], 3*" XSTR(BPS) "(%[dst]) \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), + [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11) + : [top]"r"(top), [dst]"r"(dst) + : "memory" + ); +} + +static void VL4(uint8_t* dst, const uint8_t* top) { + int temp0, temp1, temp2, temp3, temp4; + int temp5, temp6, temp7, temp8, temp9; + __asm__ volatile ( + "ulw %[temp0], 0(%[top]) \n\t" + "ulw %[temp1], 4(%[top]) \n\t" + "preceu.ph.qbla %[temp2], %[temp0] \n\t" + "preceu.ph.qbra %[temp0], %[temp0] \n\t" + "preceu.ph.qbl %[temp3], %[temp1] \n\t" + "preceu.ph.qbr %[temp1], %[temp1] \n\t" + "addqh_r.ph %[temp4], %[temp0], %[temp2] \n\t" + "packrl.ph %[temp7], %[temp1], %[temp0] \n\t" + "precrq.ph.w %[temp6], %[temp1], %[temp2] \n\t" + "shll.ph %[temp9], %[temp2], 1 \n\t" + "addqh_r.ph %[temp5], %[temp7], %[temp2] \n\t" + "shll.ph %[temp8], %[temp7], 1 \n\t" + "addu.ph %[temp2], %[temp2], %[temp6] \n\t" + "addu.ph %[temp0], %[temp0], %[temp7] \n\t" + "packrl.ph %[temp7], %[temp3], %[temp1] \n\t" + "addu.ph %[temp6], %[temp1], %[temp3] \n\t" + "addu.ph %[temp2], %[temp2], %[temp8] \n\t" + "addu.ph %[temp0], %[temp0], %[temp9] \n\t" + "shll.ph %[temp7], %[temp7], 1 \n\t" + "shra_r.ph %[temp2], %[temp2], 2 \n\t" + "shra_r.ph %[temp0], %[temp0], 2 \n\t" + "addu.ph %[temp6], %[temp6], %[temp7] \n\t" + "shra_r.ph %[temp6], %[temp6], 2 \n\t" + "precrq.ph.w %[temp8], %[temp5], %[temp4] \n\t" + "append %[temp5], %[temp4], 16 \n\t" + "precrq.ph.w %[temp3], %[temp2], %[temp0] \n\t" + "append %[temp2], %[temp0], 16 \n\t" + "precr.qb.ph %[temp8], %[temp8], %[temp5] \n\t" + "precr.qb.ph %[temp3], %[temp3], %[temp2] \n\t" + "usw %[temp8], 0*" XSTR(BPS) "(%[dst]) \n\t" + "prepend %[temp8], %[temp6], 8 \n\t" + "usw %[temp3], 1*" XSTR(BPS) "(%[dst]) \n\t" + "srl %[temp6], %[temp6], 16 \n\t" + "prepend %[temp3], %[temp6], 8 \n\t" + "usw %[temp8], 2*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp3], 3*" XSTR(BPS) "(%[dst]) \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), + [temp9]"=&r"(temp9) + : [top]"r"(top), [dst]"r"(dst) + : "memory" + ); +} + +static void HD4(uint8_t* dst, const uint8_t* top) { + int temp0, temp1, temp2, temp3, temp4; + int temp5, temp6, temp7, temp8, temp9; + __asm__ volatile ( + "ulw %[temp0], -5(%[top]) \n\t" + "ulw %[temp1], -1(%[top]) \n\t" + "preceu.ph.qbla %[temp2], %[temp0] \n\t" + "preceu.ph.qbra %[temp0], %[temp0] \n\t" + "preceu.ph.qbl %[temp3], %[temp1] \n\t" + "preceu.ph.qbr %[temp1], %[temp1] \n\t" + "addqh_r.ph %[temp4], %[temp0], %[temp2] \n\t" + "packrl.ph %[temp7], %[temp1], %[temp0] \n\t" + "precrq.ph.w %[temp6], %[temp1], %[temp2] \n\t" + "shll.ph %[temp9], %[temp2], 1 \n\t" + "addqh_r.ph %[temp5], %[temp7], %[temp2] \n\t" + "shll.ph %[temp8], %[temp7], 1 \n\t" + "addu.ph %[temp2], %[temp2], %[temp6] \n\t" + "addu.ph %[temp0], %[temp0], %[temp7] \n\t" + "packrl.ph %[temp7], %[temp3], %[temp1] \n\t" + "addu.ph %[temp6], %[temp1], %[temp3] \n\t" + "addu.ph %[temp2], %[temp2], %[temp8] \n\t" + "addu.ph %[temp0], %[temp0], %[temp9] \n\t" + "shll.ph %[temp7], %[temp7], 1 \n\t" + "shra_r.ph %[temp2], %[temp2], 2 \n\t" + "shra_r.ph %[temp0], %[temp0], 2 \n\t" + "addu.ph %[temp6], %[temp6], %[temp7] \n\t" + "shra_r.ph %[temp6], %[temp6], 2 \n\t" + "precrq.ph.w %[temp1], %[temp2], %[temp5] \n\t" + "precrq.ph.w %[temp3], %[temp0], %[temp4] \n\t" + "precr.qb.ph %[temp7], %[temp6], %[temp1] \n\t" + "precr.qb.ph %[temp6], %[temp1], %[temp3] \n\t" + "usw %[temp7], 0*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp6], 1*" XSTR(BPS) "(%[dst]) \n\t" + "append %[temp2], %[temp5], 16 \n\t" + "append %[temp0], %[temp4], 16 \n\t" + "precr.qb.ph %[temp5], %[temp3], %[temp2] \n\t" + "precr.qb.ph %[temp4], %[temp2], %[temp0] \n\t" + "usw %[temp5], 2*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp4], 3*" XSTR(BPS) "(%[dst]) \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), + [temp9]"=&r"(temp9) + : [top]"r"(top), [dst]"r"(dst) + : "memory" + ); +} + +static void HU4(uint8_t* dst, const uint8_t* top) { + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + __asm__ volatile ( + "ulw %[temp0], -5(%[top]) \n\t" + "preceu.ph.qbl %[temp1], %[temp0] \n\t" + "preceu.ph.qbr %[temp2], %[temp0] \n\t" + "packrl.ph %[temp3], %[temp1], %[temp2] \n\t" + "replv.qb %[temp7], %[temp2] \n\t" + "addqh_r.ph %[temp4], %[temp1], %[temp3] \n\t" + "addqh_r.ph %[temp5], %[temp3], %[temp2] \n\t" + "shll.ph %[temp6], %[temp3], 1 \n\t" + "addu.ph %[temp3], %[temp2], %[temp3] \n\t" + "addu.ph %[temp6], %[temp1], %[temp6] \n\t" + "shll.ph %[temp0], %[temp2], 1 \n\t" + "addu.ph %[temp6], %[temp6], %[temp2] \n\t" + "addu.ph %[temp0], %[temp3], %[temp0] \n\t" + "shra_r.ph %[temp6], %[temp6], 2 \n\t" + "shra_r.ph %[temp0], %[temp0], 2 \n\t" + "packrl.ph %[temp3], %[temp6], %[temp5] \n\t" + "precrq.ph.w %[temp2], %[temp6], %[temp4] \n\t" + "append %[temp0], %[temp5], 16 \n\t" + "precr.qb.ph %[temp3], %[temp3], %[temp2] \n\t" + "usw %[temp3], 0*" XSTR(BPS) "(%[dst]) \n\t" + "precr.qb.ph %[temp1], %[temp7], %[temp0] \n\t" + "usw %[temp7], 3*" XSTR(BPS) "(%[dst]) \n\t" + "packrl.ph %[temp2], %[temp1], %[temp3] \n\t" + "usw %[temp1], 2*" XSTR(BPS) "(%[dst]) \n\t" + "usw %[temp2], 1*" XSTR(BPS) "(%[dst]) \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7) + : [top]"r"(top), [dst]"r"(dst) + : "memory" + ); +} + +//------------------------------------------------------------------------------ +// Chroma 8x8 prediction (paragraph 12.2) + +static void IntraChromaPreds_MIPSdspR2(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { + // U block + DCMode8(C8DC8 + dst, left, top); + VerticalPred8(C8VE8 + dst, top); + HorizontalPred8(C8HE8 + dst, left); + TrueMotion8(C8TM8 + dst, left, top); + // V block + dst += 8; + if (top) top += 8; + if (left) left += 16; + DCMode8(C8DC8 + dst, left, top); + VerticalPred8(C8VE8 + dst, top); + HorizontalPred8(C8HE8 + dst, left); + TrueMotion8(C8TM8 + dst, left, top); +} + +//------------------------------------------------------------------------------ +// luma 16x16 prediction (paragraph 12.3) + +static void Intra16Preds_MIPSdspR2(uint8_t* dst, + const uint8_t* left, const uint8_t* top) { + DCMode16(I16DC16 + dst, left, top); + VerticalPred16(I16VE16 + dst, top); + HorizontalPred16(I16HE16 + dst, left); + TrueMotion16(I16TM16 + dst, left, top); +} + +// Left samples are top[-5 .. -2], top_left is top[-1], top are +// located at top[0..3], and top right is top[4..7] +static void Intra4Preds_MIPSdspR2(uint8_t* dst, const uint8_t* top) { + DC4(I4DC4 + dst, top); + TM4(I4TM4 + dst, top); + VE4(I4VE4 + dst, top); + HE4(I4HE4 + dst, top); + RD4(I4RD4 + dst, top); + VR4(I4VR4 + dst, top); + LD4(I4LD4 + dst, top); + VL4(I4VL4 + dst, top); + HD4(I4HD4 + dst, top); + HU4(I4HU4 + dst, top); +} + +//------------------------------------------------------------------------------ +// Metric + +#if !defined(WORK_AROUND_GCC) + +#define GET_SSE_INNER(A) \ + "lw %[temp0], " #A "(%[a]) \n\t" \ + "lw %[temp1], " #A "(%[b]) \n\t" \ + "preceu.ph.qbr %[temp2], %[temp0] \n\t" \ + "preceu.ph.qbl %[temp0], %[temp0] \n\t" \ + "preceu.ph.qbr %[temp3], %[temp1] \n\t" \ + "preceu.ph.qbl %[temp1], %[temp1] \n\t" \ + "subq.ph %[temp2], %[temp2], %[temp3] \n\t" \ + "subq.ph %[temp0], %[temp0], %[temp1] \n\t" \ + "dpa.w.ph $ac0, %[temp2], %[temp2] \n\t" \ + "dpa.w.ph $ac0, %[temp0], %[temp0] \n\t" + +#define GET_SSE(A, B, C, D) \ + GET_SSE_INNER(A) \ + GET_SSE_INNER(B) \ + GET_SSE_INNER(C) \ + GET_SSE_INNER(D) + +static int SSE16x16_MIPSdspR2(const uint8_t* a, const uint8_t* b) { + int count; + int temp0, temp1, temp2, temp3; + __asm__ volatile ( + "mult $zero, $zero \n\t" + GET_SSE( 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS) + GET_SSE( 1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS) + GET_SSE( 2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS) + GET_SSE( 3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS) + GET_SSE( 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS) + GET_SSE( 5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS) + GET_SSE( 6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS) + GET_SSE( 7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS) + GET_SSE( 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS) + GET_SSE( 9 * BPS, 4 + 9 * BPS, 8 + 9 * BPS, 12 + 9 * BPS) + GET_SSE(10 * BPS, 4 + 10 * BPS, 8 + 10 * BPS, 12 + 10 * BPS) + GET_SSE(11 * BPS, 4 + 11 * BPS, 8 + 11 * BPS, 12 + 11 * BPS) + GET_SSE(12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS) + GET_SSE(13 * BPS, 4 + 13 * BPS, 8 + 13 * BPS, 12 + 13 * BPS) + GET_SSE(14 * BPS, 4 + 14 * BPS, 8 + 14 * BPS, 12 + 14 * BPS) + GET_SSE(15 * BPS, 4 + 15 * BPS, 8 + 15 * BPS, 12 + 15 * BPS) + "mflo %[count] \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [count]"=&r"(count) + : [a]"r"(a), [b]"r"(b) + : "memory", "hi", "lo" + ); + return count; +} + +static int SSE16x8_MIPSdspR2(const uint8_t* a, const uint8_t* b) { + int count; + int temp0, temp1, temp2, temp3; + __asm__ volatile ( + "mult $zero, $zero \n\t" + GET_SSE( 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS) + GET_SSE( 1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS) + GET_SSE( 2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS) + GET_SSE( 3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS) + GET_SSE( 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS) + GET_SSE( 5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS) + GET_SSE( 6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS) + GET_SSE( 7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS) + "mflo %[count] \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [count]"=&r"(count) + : [a]"r"(a), [b]"r"(b) + : "memory", "hi", "lo" + ); + return count; +} + +static int SSE8x8_MIPSdspR2(const uint8_t* a, const uint8_t* b) { + int count; + int temp0, temp1, temp2, temp3; + __asm__ volatile ( + "mult $zero, $zero \n\t" + GET_SSE(0 * BPS, 4 + 0 * BPS, 1 * BPS, 4 + 1 * BPS) + GET_SSE(2 * BPS, 4 + 2 * BPS, 3 * BPS, 4 + 3 * BPS) + GET_SSE(4 * BPS, 4 + 4 * BPS, 5 * BPS, 4 + 5 * BPS) + GET_SSE(6 * BPS, 4 + 6 * BPS, 7 * BPS, 4 + 7 * BPS) + "mflo %[count] \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [count]"=&r"(count) + : [a]"r"(a), [b]"r"(b) + : "memory", "hi", "lo" + ); + return count; +} + +static int SSE4x4_MIPSdspR2(const uint8_t* a, const uint8_t* b) { + int count; + int temp0, temp1, temp2, temp3; + __asm__ volatile ( + "mult $zero, $zero \n\t" + GET_SSE(0 * BPS, 1 * BPS, 2 * BPS, 3 * BPS) + "mflo %[count] \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [count]"=&r"(count) + : [a]"r"(a), [b]"r"(b) + : "memory", "hi", "lo" + ); + return count; +} + +#undef GET_SSE +#undef GET_SSE_INNER + +#endif // !WORK_AROUND_GCC + +#undef FILL_8_OR_16 +#undef FILL_PART +#undef OUTPUT_EARLY_CLOBBER_REGS_17 +#undef MUL_HALF +#undef ABS_X8 +#undef ADD_SUB_HALVES_X4 + +//------------------------------------------------------------------------------ +// Quantization +// + +// macro for one pass through for loop in QuantizeBlock reading 2 values at time +// QUANTDIV macro inlined +// J - offset in bytes (kZigzag[n] * 2) +// K - offset in bytes (kZigzag[n] * 4) +// N - offset in bytes (n * 2) +// N1 - offset in bytes ((n + 1) * 2) +#define QUANTIZE_ONE(J, K, N, N1) \ + "ulw %[temp1], " #J "(%[ppin]) \n\t" \ + "ulw %[temp2], " #J "(%[ppsharpen]) \n\t" \ + "lhu %[temp3], " #K "(%[ppzthresh]) \n\t" \ + "lhu %[temp6], " #K "+4(%[ppzthresh]) \n\t" \ + "absq_s.ph %[temp4], %[temp1] \n\t" \ + "ins %[temp3], %[temp6], 16, 16 \n\t" \ + "addu.ph %[coeff], %[temp4], %[temp2] \n\t" \ + "shra.ph %[sign], %[temp1], 15 \n\t" \ + "li %[level], 0x10001 \n\t" \ + "cmp.lt.ph %[temp3], %[coeff] \n\t" \ + "lhu %[temp1], " #J "(%[ppiq]) \n\t" \ + "pick.ph %[temp5], %[level], $0 \n\t" \ + "lw %[temp2], " #K "(%[ppbias]) \n\t" \ + "beqz %[temp5], 0f \n\t" \ + "lhu %[temp3], " #J "(%[ppq]) \n\t" \ + "beq %[temp5], %[level], 1f \n\t" \ + "andi %[temp5], %[temp5], 0x1 \n\t" \ + "andi %[temp4], %[coeff], 0xffff \n\t" \ + "beqz %[temp5], 2f \n\t" \ + "mul %[level], %[temp4], %[temp1] \n\t" \ + "sh $0, " #J "+2(%[ppin]) \n\t" \ + "sh $0, " #N1 "(%[pout]) \n\t" \ + "addu %[level], %[level], %[temp2] \n\t" \ + "sra %[level], %[level], 17 \n\t" \ + "slt %[temp4], %[max_level], %[level] \n\t" \ + "movn %[level], %[max_level], %[temp4] \n\t" \ + "andi %[temp6], %[sign], 0xffff \n\t" \ + "xor %[level], %[level], %[temp6] \n\t" \ + "subu %[level], %[level], %[temp6] \n\t" \ + "mul %[temp5], %[level], %[temp3] \n\t" \ + "or %[ret], %[ret], %[level] \n\t" \ + "sh %[level], " #N "(%[pout]) \n\t" \ + "sh %[temp5], " #J "(%[ppin]) \n\t" \ + "j 3f \n\t" \ +"2: \n\t" \ + "lhu %[temp1], " #J "+2(%[ppiq]) \n\t" \ + "srl %[temp5], %[coeff], 16 \n\t" \ + "mul %[level], %[temp5], %[temp1] \n\t" \ + "lw %[temp2], " #K "+4(%[ppbias]) \n\t" \ + "lhu %[temp3], " #J "+2(%[ppq]) \n\t" \ + "addu %[level], %[level], %[temp2] \n\t" \ + "sra %[level], %[level], 17 \n\t" \ + "srl %[temp6], %[sign], 16 \n\t" \ + "slt %[temp4], %[max_level], %[level] \n\t" \ + "movn %[level], %[max_level], %[temp4] \n\t" \ + "xor %[level], %[level], %[temp6] \n\t" \ + "subu %[level], %[level], %[temp6] \n\t" \ + "mul %[temp5], %[level], %[temp3] \n\t" \ + "sh $0, " #J "(%[ppin]) \n\t" \ + "sh $0, " #N "(%[pout]) \n\t" \ + "or %[ret], %[ret], %[level] \n\t" \ + "sh %[temp5], " #J "+2(%[ppin]) \n\t" \ + "sh %[level], " #N1 "(%[pout]) \n\t" \ + "j 3f \n\t" \ +"1: \n\t" \ + "lhu %[temp1], " #J "(%[ppiq]) \n\t" \ + "lw %[temp2], " #K "(%[ppbias]) \n\t" \ + "ulw %[temp3], " #J "(%[ppq]) \n\t" \ + "andi %[temp5], %[coeff], 0xffff \n\t" \ + "srl %[temp0], %[coeff], 16 \n\t" \ + "lhu %[temp6], " #J "+2(%[ppiq]) \n\t" \ + "lw %[coeff], " #K "+4(%[ppbias]) \n\t" \ + "mul %[level], %[temp5], %[temp1] \n\t" \ + "mul %[temp4], %[temp0], %[temp6] \n\t" \ + "addu %[level], %[level], %[temp2] \n\t" \ + "addu %[temp4], %[temp4], %[coeff] \n\t" \ + "precrq.ph.w %[level], %[temp4], %[level] \n\t" \ + "shra.ph %[level], %[level], 1 \n\t" \ + "cmp.lt.ph %[max_level1],%[level] \n\t" \ + "pick.ph %[level], %[max_level], %[level] \n\t" \ + "xor %[level], %[level], %[sign] \n\t" \ + "subu.ph %[level], %[level], %[sign] \n\t" \ + "mul.ph %[temp3], %[level], %[temp3] \n\t" \ + "or %[ret], %[ret], %[level] \n\t" \ + "sh %[level], " #N "(%[pout]) \n\t" \ + "srl %[level], %[level], 16 \n\t" \ + "sh %[level], " #N1 "(%[pout]) \n\t" \ + "usw %[temp3], " #J "(%[ppin]) \n\t" \ + "j 3f \n\t" \ +"0: \n\t" \ + "sh $0, " #N "(%[pout]) \n\t" \ + "sh $0, " #N1 "(%[pout]) \n\t" \ + "usw $0, " #J "(%[ppin]) \n\t" \ +"3: \n\t" + +static int QuantizeBlock_MIPSdspR2(int16_t in[16], int16_t out[16], + const VP8Matrix* const mtx) { + int temp0, temp1, temp2, temp3, temp4, temp5,temp6; + int sign, coeff, level; + int max_level = MAX_LEVEL; + int max_level1 = max_level << 16 | max_level; + int ret = 0; + + int16_t* ppin = &in[0]; + int16_t* pout = &out[0]; + const uint16_t* ppsharpen = &mtx->sharpen_[0]; + const uint32_t* ppzthresh = &mtx->zthresh_[0]; + const uint16_t* ppq = &mtx->q_[0]; + const uint16_t* ppiq = &mtx->iq_[0]; + const uint32_t* ppbias = &mtx->bias_[0]; + + __asm__ volatile ( + QUANTIZE_ONE( 0, 0, 0, 2) + QUANTIZE_ONE( 4, 8, 10, 12) + QUANTIZE_ONE( 8, 16, 4, 8) + QUANTIZE_ONE(12, 24, 14, 24) + QUANTIZE_ONE(16, 32, 6, 16) + QUANTIZE_ONE(20, 40, 22, 26) + QUANTIZE_ONE(24, 48, 18, 20) + QUANTIZE_ONE(28, 56, 28, 30) + + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [sign]"=&r"(sign), [coeff]"=&r"(coeff), + [level]"=&r"(level), [temp6]"=&r"(temp6), [ret]"+&r"(ret) + : [ppin]"r"(ppin), [pout]"r"(pout), [max_level1]"r"(max_level1), + [ppiq]"r"(ppiq), [max_level]"r"(max_level), + [ppbias]"r"(ppbias), [ppzthresh]"r"(ppzthresh), + [ppsharpen]"r"(ppsharpen), [ppq]"r"(ppq) + : "memory", "hi", "lo" + ); + + return (ret != 0); +} + +static int Quantize2Blocks_MIPSdspR2(int16_t in[32], int16_t out[32], + const VP8Matrix* const mtx) { + int nz; + nz = QuantizeBlock_MIPSdspR2(in + 0 * 16, out + 0 * 16, mtx) << 0; + nz |= QuantizeBlock_MIPSdspR2(in + 1 * 16, out + 1 * 16, mtx) << 1; + return nz; +} + +#undef QUANTIZE_ONE + +// macro for one horizontal pass in FTransformWHT +// temp0..temp7 holds tmp[0]..tmp[15] +// A, B, C, D - offset in bytes to load from in buffer +// TEMP0, TEMP1 - registers for corresponding tmp elements +#define HORIZONTAL_PASS_WHT(A, B, C, D, TEMP0, TEMP1) \ + "lh %[" #TEMP0 "], " #A "(%[in]) \n\t" \ + "lh %[" #TEMP1 "], " #B "(%[in]) \n\t" \ + "lh %[temp8], " #C "(%[in]) \n\t" \ + "lh %[temp9], " #D "(%[in]) \n\t" \ + "ins %[" #TEMP1 "], %[" #TEMP0 "], 16, 16 \n\t" \ + "ins %[temp9], %[temp8], 16, 16 \n\t" \ + "subq.ph %[temp8], %[" #TEMP1 "], %[temp9] \n\t" \ + "addq.ph %[temp9], %[" #TEMP1 "], %[temp9] \n\t" \ + "precrq.ph.w %[" #TEMP0 "], %[temp8], %[temp9] \n\t" \ + "append %[temp8], %[temp9], 16 \n\t" \ + "subq.ph %[" #TEMP1 "], %[" #TEMP0 "], %[temp8] \n\t" \ + "addq.ph %[" #TEMP0 "], %[" #TEMP0 "], %[temp8] \n\t" \ + "rotr %[" #TEMP1 "], %[" #TEMP1 "], 16 \n\t" + +// macro for one vertical pass in FTransformWHT +// temp0..temp7 holds tmp[0]..tmp[15] +// A, B, C, D - offsets in bytes to store to out buffer +// TEMP0, TEMP2, TEMP4 and TEMP6 - registers for corresponding tmp elements +#define VERTICAL_PASS_WHT(A, B, C, D, TEMP0, TEMP2, TEMP4, TEMP6) \ + "addq.ph %[temp8], %[" #TEMP0 "], %[" #TEMP4 "] \n\t" \ + "addq.ph %[temp9], %[" #TEMP2 "], %[" #TEMP6 "] \n\t" \ + "subq.ph %[" #TEMP2 "], %[" #TEMP2 "], %[" #TEMP6 "] \n\t" \ + "subq.ph %[" #TEMP6 "], %[" #TEMP0 "], %[" #TEMP4 "] \n\t" \ + "addqh.ph %[" #TEMP0 "], %[temp8], %[temp9] \n\t" \ + "subqh.ph %[" #TEMP4 "], %[" #TEMP6 "], %[" #TEMP2 "] \n\t" \ + "addqh.ph %[" #TEMP2 "], %[" #TEMP2 "], %[" #TEMP6 "] \n\t" \ + "subqh.ph %[" #TEMP6 "], %[temp8], %[temp9] \n\t" \ + "usw %[" #TEMP0 "], " #A "(%[out]) \n\t" \ + "usw %[" #TEMP2 "], " #B "(%[out]) \n\t" \ + "usw %[" #TEMP4 "], " #C "(%[out]) \n\t" \ + "usw %[" #TEMP6 "], " #D "(%[out]) \n\t" + +static void FTransformWHT_MIPSdspR2(const int16_t* in, int16_t* out) { + int temp0, temp1, temp2, temp3, temp4; + int temp5, temp6, temp7, temp8, temp9; + + __asm__ volatile ( + HORIZONTAL_PASS_WHT( 0, 32, 64, 96, temp0, temp1) + HORIZONTAL_PASS_WHT(128, 160, 192, 224, temp2, temp3) + HORIZONTAL_PASS_WHT(256, 288, 320, 352, temp4, temp5) + HORIZONTAL_PASS_WHT(384, 416, 448, 480, temp6, temp7) + VERTICAL_PASS_WHT(0, 8, 16, 24, temp0, temp2, temp4, temp6) + VERTICAL_PASS_WHT(4, 12, 20, 28, temp1, temp3, temp5, temp7) + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), + [temp9]"=&r"(temp9) + : [in]"r"(in), [out]"r"(out) + : "memory" + ); +} + +#undef VERTICAL_PASS_WHT +#undef HORIZONTAL_PASS_WHT + +// macro for converting coefficients to bin +// convert 8 coeffs at time +// A, B, C, D - offsets in bytes to load from out buffer +#define CONVERT_COEFFS_TO_BIN(A, B, C, D) \ + "ulw %[temp0], " #A "(%[out]) \n\t" \ + "ulw %[temp1], " #B "(%[out]) \n\t" \ + "ulw %[temp2], " #C "(%[out]) \n\t" \ + "ulw %[temp3], " #D "(%[out]) \n\t" \ + "absq_s.ph %[temp0], %[temp0] \n\t" \ + "absq_s.ph %[temp1], %[temp1] \n\t" \ + "absq_s.ph %[temp2], %[temp2] \n\t" \ + "absq_s.ph %[temp3], %[temp3] \n\t" \ + "shra.ph %[temp0], %[temp0], 3 \n\t" \ + "shra.ph %[temp1], %[temp1], 3 \n\t" \ + "shra.ph %[temp2], %[temp2], 3 \n\t" \ + "shra.ph %[temp3], %[temp3], 3 \n\t" \ + "shll_s.ph %[temp0], %[temp0], 10 \n\t" \ + "shll_s.ph %[temp1], %[temp1], 10 \n\t" \ + "shll_s.ph %[temp2], %[temp2], 10 \n\t" \ + "shll_s.ph %[temp3], %[temp3], 10 \n\t" \ + "shrl.ph %[temp0], %[temp0], 10 \n\t" \ + "shrl.ph %[temp1], %[temp1], 10 \n\t" \ + "shrl.ph %[temp2], %[temp2], 10 \n\t" \ + "shrl.ph %[temp3], %[temp3], 10 \n\t" \ + "shll.ph %[temp0], %[temp0], 2 \n\t" \ + "shll.ph %[temp1], %[temp1], 2 \n\t" \ + "shll.ph %[temp2], %[temp2], 2 \n\t" \ + "shll.ph %[temp3], %[temp3], 2 \n\t" \ + "ext %[temp4], %[temp0], 0, 16 \n\t" \ + "ext %[temp0], %[temp0], 16, 16 \n\t" \ + "addu %[temp4], %[temp4], %[dist] \n\t" \ + "addu %[temp0], %[temp0], %[dist] \n\t" \ + "ext %[temp5], %[temp1], 0, 16 \n\t" \ + "lw %[temp8], 0(%[temp4]) \n\t" \ + "ext %[temp1], %[temp1], 16, 16 \n\t" \ + "addu %[temp5], %[temp5], %[dist] \n\t" \ + "addiu %[temp8], %[temp8], 1 \n\t" \ + "sw %[temp8], 0(%[temp4]) \n\t" \ + "lw %[temp8], 0(%[temp0]) \n\t" \ + "addu %[temp1], %[temp1], %[dist] \n\t" \ + "ext %[temp6], %[temp2], 0, 16 \n\t" \ + "addiu %[temp8], %[temp8], 1 \n\t" \ + "sw %[temp8], 0(%[temp0]) \n\t" \ + "lw %[temp8], 0(%[temp5]) \n\t" \ + "ext %[temp2], %[temp2], 16, 16 \n\t" \ + "addu %[temp6], %[temp6], %[dist] \n\t" \ + "addiu %[temp8], %[temp8], 1 \n\t" \ + "sw %[temp8], 0(%[temp5]) \n\t" \ + "lw %[temp8], 0(%[temp1]) \n\t" \ + "addu %[temp2], %[temp2], %[dist] \n\t" \ + "ext %[temp7], %[temp3], 0, 16 \n\t" \ + "addiu %[temp8], %[temp8], 1 \n\t" \ + "sw %[temp8], 0(%[temp1]) \n\t" \ + "lw %[temp8], 0(%[temp6]) \n\t" \ + "ext %[temp3], %[temp3], 16, 16 \n\t" \ + "addu %[temp7], %[temp7], %[dist] \n\t" \ + "addiu %[temp8], %[temp8], 1 \n\t" \ + "sw %[temp8], 0(%[temp6]) \n\t" \ + "lw %[temp8], 0(%[temp2]) \n\t" \ + "addu %[temp3], %[temp3], %[dist] \n\t" \ + "addiu %[temp8], %[temp8], 1 \n\t" \ + "sw %[temp8], 0(%[temp2]) \n\t" \ + "lw %[temp8], 0(%[temp7]) \n\t" \ + "addiu %[temp8], %[temp8], 1 \n\t" \ + "sw %[temp8], 0(%[temp7]) \n\t" \ + "lw %[temp8], 0(%[temp3]) \n\t" \ + "addiu %[temp8], %[temp8], 1 \n\t" \ + "sw %[temp8], 0(%[temp3]) \n\t" + +static void CollectHistogram_MIPSdspR2(const uint8_t* ref, const uint8_t* pred, + int start_block, int end_block, + VP8Histogram* const histo) { + int j; + int distribution[MAX_COEFF_THRESH + 1] = { 0 }; + const int max_coeff = (MAX_COEFF_THRESH << 16) + MAX_COEFF_THRESH; + for (j = start_block; j < end_block; ++j) { + int16_t out[16]; + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8; + + VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out); + + // Convert coefficients to bin. + __asm__ volatile ( + CONVERT_COEFFS_TO_BIN( 0, 4, 8, 12) + CONVERT_COEFFS_TO_BIN(16, 20, 24, 28) + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8) + : [dist]"r"(distribution), [out]"r"(out), [max_coeff]"r"(max_coeff) + : "memory" + ); + } + VP8SetHistogramData(distribution, histo); +} + +#undef CONVERT_COEFFS_TO_BIN + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8EncDspInitMIPSdspR2(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitMIPSdspR2(void) { + VP8FTransform = FTransform_MIPSdspR2; + VP8FTransformWHT = FTransformWHT_MIPSdspR2; + VP8ITransform = ITransform_MIPSdspR2; + + VP8TDisto4x4 = Disto4x4_MIPSdspR2; + VP8TDisto16x16 = Disto16x16_MIPSdspR2; + + VP8EncPredLuma16 = Intra16Preds_MIPSdspR2; + VP8EncPredChroma8 = IntraChromaPreds_MIPSdspR2; + VP8EncPredLuma4 = Intra4Preds_MIPSdspR2; + +#if !defined(WORK_AROUND_GCC) + VP8SSE16x16 = SSE16x16_MIPSdspR2; + VP8SSE8x8 = SSE8x8_MIPSdspR2; + VP8SSE16x8 = SSE16x8_MIPSdspR2; + VP8SSE4x4 = SSE4x4_MIPSdspR2; +#endif + + VP8EncQuantizeBlock = QuantizeBlock_MIPSdspR2; + VP8EncQuantize2Blocks = Quantize2Blocks_MIPSdspR2; + + VP8CollectHistogram = CollectHistogram_MIPSdspR2; +} + +#else // !WEBP_USE_MIPS_DSP_R2 + +WEBP_DSP_INIT_STUB(VP8EncDspInitMIPSdspR2) + +#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/third-party/webp/libwebp/src/dsp/enc_msa.c b/third-party/webp/libwebp/src/dsp/enc_msa.c new file mode 100644 index 0000000000..6f85add4bb --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/enc_msa.c @@ -0,0 +1,896 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MSA version of encoder dsp functions. +// +// Author: Prashant Patil (prashant.patil@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MSA) + +#include +#include "src/dsp/msa_macro.h" +#include "src/enc/vp8i_enc.h" + +//------------------------------------------------------------------------------ +// Transforms + +#define IDCT_1D_W(in0, in1, in2, in3, out0, out1, out2, out3) do { \ + v4i32 a1_m, b1_m, c1_m, d1_m; \ + const v4i32 cospi8sqrt2minus1 = __msa_fill_w(20091); \ + const v4i32 sinpi8sqrt2 = __msa_fill_w(35468); \ + v4i32 c_tmp1_m = in1 * sinpi8sqrt2; \ + v4i32 c_tmp2_m = in3 * cospi8sqrt2minus1; \ + v4i32 d_tmp1_m = in1 * cospi8sqrt2minus1; \ + v4i32 d_tmp2_m = in3 * sinpi8sqrt2; \ + \ + ADDSUB2(in0, in2, a1_m, b1_m); \ + SRAI_W2_SW(c_tmp1_m, c_tmp2_m, 16); \ + c_tmp2_m = c_tmp2_m + in3; \ + c1_m = c_tmp1_m - c_tmp2_m; \ + SRAI_W2_SW(d_tmp1_m, d_tmp2_m, 16); \ + d_tmp1_m = d_tmp1_m + in1; \ + d1_m = d_tmp1_m + d_tmp2_m; \ + BUTTERFLY_4(a1_m, b1_m, c1_m, d1_m, out0, out1, out2, out3); \ +} while (0) + +static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in, + uint8_t* dst) { + v8i16 input0, input1; + v4i32 in0, in1, in2, in3, hz0, hz1, hz2, hz3, vt0, vt1, vt2, vt3; + v4i32 res0, res1, res2, res3; + v16i8 dest0, dest1, dest2, dest3; + const v16i8 zero = { 0 }; + + LD_SH2(in, 8, input0, input1); + UNPCK_SH_SW(input0, in0, in1); + UNPCK_SH_SW(input1, in2, in3); + IDCT_1D_W(in0, in1, in2, in3, hz0, hz1, hz2, hz3); + TRANSPOSE4x4_SW_SW(hz0, hz1, hz2, hz3, hz0, hz1, hz2, hz3); + IDCT_1D_W(hz0, hz1, hz2, hz3, vt0, vt1, vt2, vt3); + SRARI_W4_SW(vt0, vt1, vt2, vt3, 3); + TRANSPOSE4x4_SW_SW(vt0, vt1, vt2, vt3, vt0, vt1, vt2, vt3); + LD_SB4(ref, BPS, dest0, dest1, dest2, dest3); + ILVR_B4_SW(zero, dest0, zero, dest1, zero, dest2, zero, dest3, + res0, res1, res2, res3); + ILVR_H4_SW(zero, res0, zero, res1, zero, res2, zero, res3, + res0, res1, res2, res3); + ADD4(res0, vt0, res1, vt1, res2, vt2, res3, vt3, res0, res1, res2, res3); + CLIP_SW4_0_255(res0, res1, res2, res3); + PCKEV_B2_SW(res0, res1, res2, res3, vt0, vt1); + res0 = (v4i32)__msa_pckev_b((v16i8)vt0, (v16i8)vt1); + ST4x4_UB(res0, res0, 3, 2, 1, 0, dst, BPS); +} + +static void ITransform_MSA(const uint8_t* ref, const int16_t* in, uint8_t* dst, + int do_two) { + ITransformOne(ref, in, dst); + if (do_two) { + ITransformOne(ref + 4, in + 16, dst + 4); + } +} + +static void FTransform_MSA(const uint8_t* src, const uint8_t* ref, + int16_t* out) { + uint64_t out0, out1, out2, out3; + uint32_t in0, in1, in2, in3; + v4i32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + v8i16 t0, t1, t2, t3; + v16u8 srcl0, srcl1, src0 = { 0 }, src1 = { 0 }; + const v8i16 mask0 = { 0, 4, 8, 12, 1, 5, 9, 13 }; + const v8i16 mask1 = { 3, 7, 11, 15, 2, 6, 10, 14 }; + const v8i16 mask2 = { 4, 0, 5, 1, 6, 2, 7, 3 }; + const v8i16 mask3 = { 0, 4, 1, 5, 2, 6, 3, 7 }; + const v8i16 cnst0 = { 2217, -5352, 2217, -5352, 2217, -5352, 2217, -5352 }; + const v8i16 cnst1 = { 5352, 2217, 5352, 2217, 5352, 2217, 5352, 2217 }; + + LW4(src, BPS, in0, in1, in2, in3); + INSERT_W4_UB(in0, in1, in2, in3, src0); + LW4(ref, BPS, in0, in1, in2, in3); + INSERT_W4_UB(in0, in1, in2, in3, src1); + ILVRL_B2_UB(src0, src1, srcl0, srcl1); + HSUB_UB2_SH(srcl0, srcl1, t0, t1); + VSHF_H2_SH(t0, t1, t0, t1, mask0, mask1, t2, t3); + ADDSUB2(t2, t3, t0, t1); + t0 = SRLI_H(t0, 3); + VSHF_H2_SH(t0, t0, t1, t1, mask2, mask3, t3, t2); + tmp0 = __msa_hadd_s_w(t3, t3); + tmp2 = __msa_hsub_s_w(t3, t3); + FILL_W2_SW(1812, 937, tmp1, tmp3); + DPADD_SH2_SW(t2, t2, cnst0, cnst1, tmp3, tmp1); + SRAI_W2_SW(tmp1, tmp3, 9); + PCKEV_H2_SH(tmp1, tmp0, tmp3, tmp2, t0, t1); + VSHF_H2_SH(t0, t1, t0, t1, mask0, mask1, t2, t3); + ADDSUB2(t2, t3, t0, t1); + VSHF_H2_SH(t0, t0, t1, t1, mask2, mask3, t3, t2); + tmp0 = __msa_hadd_s_w(t3, t3); + tmp2 = __msa_hsub_s_w(t3, t3); + ADDVI_W2_SW(tmp0, 7, tmp2, 7, tmp0, tmp2); + SRAI_W2_SW(tmp0, tmp2, 4); + FILL_W2_SW(12000, 51000, tmp1, tmp3); + DPADD_SH2_SW(t2, t2, cnst0, cnst1, tmp3, tmp1); + SRAI_W2_SW(tmp1, tmp3, 16); + UNPCK_R_SH_SW(t1, tmp4); + tmp5 = __msa_ceqi_w(tmp4, 0); + tmp4 = (v4i32)__msa_nor_v((v16u8)tmp5, (v16u8)tmp5); + tmp5 = __msa_fill_w(1); + tmp5 = (v4i32)__msa_and_v((v16u8)tmp5, (v16u8)tmp4); + tmp1 += tmp5; + PCKEV_H2_SH(tmp1, tmp0, tmp3, tmp2, t0, t1); + out0 = __msa_copy_s_d((v2i64)t0, 0); + out1 = __msa_copy_s_d((v2i64)t0, 1); + out2 = __msa_copy_s_d((v2i64)t1, 0); + out3 = __msa_copy_s_d((v2i64)t1, 1); + SD4(out0, out1, out2, out3, out, 8); +} + +static void FTransformWHT_MSA(const int16_t* in, int16_t* out) { + v8i16 in0 = { 0 }; + v8i16 in1 = { 0 }; + v8i16 tmp0, tmp1, tmp2, tmp3; + v8i16 out0, out1; + const v8i16 mask0 = { 0, 1, 2, 3, 8, 9, 10, 11 }; + const v8i16 mask1 = { 4, 5, 6, 7, 12, 13, 14, 15 }; + const v8i16 mask2 = { 0, 4, 8, 12, 1, 5, 9, 13 }; + const v8i16 mask3 = { 3, 7, 11, 15, 2, 6, 10, 14 }; + + in0 = __msa_insert_h(in0, 0, in[ 0]); + in0 = __msa_insert_h(in0, 1, in[ 64]); + in0 = __msa_insert_h(in0, 2, in[128]); + in0 = __msa_insert_h(in0, 3, in[192]); + in0 = __msa_insert_h(in0, 4, in[ 16]); + in0 = __msa_insert_h(in0, 5, in[ 80]); + in0 = __msa_insert_h(in0, 6, in[144]); + in0 = __msa_insert_h(in0, 7, in[208]); + in1 = __msa_insert_h(in1, 0, in[ 48]); + in1 = __msa_insert_h(in1, 1, in[112]); + in1 = __msa_insert_h(in1, 2, in[176]); + in1 = __msa_insert_h(in1, 3, in[240]); + in1 = __msa_insert_h(in1, 4, in[ 32]); + in1 = __msa_insert_h(in1, 5, in[ 96]); + in1 = __msa_insert_h(in1, 6, in[160]); + in1 = __msa_insert_h(in1, 7, in[224]); + ADDSUB2(in0, in1, tmp0, tmp1); + VSHF_H2_SH(tmp0, tmp1, tmp0, tmp1, mask0, mask1, tmp2, tmp3); + ADDSUB2(tmp2, tmp3, tmp0, tmp1); + VSHF_H2_SH(tmp0, tmp1, tmp0, tmp1, mask2, mask3, in0, in1); + ADDSUB2(in0, in1, tmp0, tmp1); + VSHF_H2_SH(tmp0, tmp1, tmp0, tmp1, mask0, mask1, tmp2, tmp3); + ADDSUB2(tmp2, tmp3, out0, out1); + SRAI_H2_SH(out0, out1, 1); + ST_SH2(out0, out1, out, 8); +} + +static int TTransform_MSA(const uint8_t* in, const uint16_t* w) { + int sum; + uint32_t in0_m, in1_m, in2_m, in3_m; + v16i8 src0 = { 0 }; + v8i16 in0, in1, tmp0, tmp1, tmp2, tmp3; + v4i32 dst0, dst1; + const v16i8 zero = { 0 }; + const v8i16 mask0 = { 0, 1, 2, 3, 8, 9, 10, 11 }; + const v8i16 mask1 = { 4, 5, 6, 7, 12, 13, 14, 15 }; + const v8i16 mask2 = { 0, 4, 8, 12, 1, 5, 9, 13 }; + const v8i16 mask3 = { 3, 7, 11, 15, 2, 6, 10, 14 }; + + LW4(in, BPS, in0_m, in1_m, in2_m, in3_m); + INSERT_W4_SB(in0_m, in1_m, in2_m, in3_m, src0); + ILVRL_B2_SH(zero, src0, tmp0, tmp1); + VSHF_H2_SH(tmp0, tmp1, tmp0, tmp1, mask2, mask3, in0, in1); + ADDSUB2(in0, in1, tmp0, tmp1); + VSHF_H2_SH(tmp0, tmp1, tmp0, tmp1, mask0, mask1, tmp2, tmp3); + ADDSUB2(tmp2, tmp3, tmp0, tmp1); + VSHF_H2_SH(tmp0, tmp1, tmp0, tmp1, mask2, mask3, in0, in1); + ADDSUB2(in0, in1, tmp0, tmp1); + VSHF_H2_SH(tmp0, tmp1, tmp0, tmp1, mask0, mask1, tmp2, tmp3); + ADDSUB2(tmp2, tmp3, tmp0, tmp1); + tmp0 = __msa_add_a_h(tmp0, (v8i16)zero); + tmp1 = __msa_add_a_h(tmp1, (v8i16)zero); + LD_SH2(w, 8, tmp2, tmp3); + DOTP_SH2_SW(tmp0, tmp1, tmp2, tmp3, dst0, dst1); + dst0 = dst0 + dst1; + sum = HADD_SW_S32(dst0); + return sum; +} + +static int Disto4x4_MSA(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + const int sum1 = TTransform_MSA(a, w); + const int sum2 = TTransform_MSA(b, w); + return abs(sum2 - sum1) >> 5; +} + +static int Disto16x16_MSA(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + int D = 0; + int x, y; + for (y = 0; y < 16 * BPS; y += 4 * BPS) { + for (x = 0; x < 16; x += 4) { + D += Disto4x4_MSA(a + x + y, b + x + y, w); + } + } + return D; +} + +//------------------------------------------------------------------------------ +// Histogram + +static void CollectHistogram_MSA(const uint8_t* ref, const uint8_t* pred, + int start_block, int end_block, + VP8Histogram* const histo) { + int j; + int distribution[MAX_COEFF_THRESH + 1] = { 0 }; + for (j = start_block; j < end_block; ++j) { + int16_t out[16]; + VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out); + { + int k; + v8i16 coeff0, coeff1; + const v8i16 zero = { 0 }; + const v8i16 max_coeff_thr = __msa_ldi_h(MAX_COEFF_THRESH); + LD_SH2(&out[0], 8, coeff0, coeff1); + coeff0 = __msa_add_a_h(coeff0, zero); + coeff1 = __msa_add_a_h(coeff1, zero); + SRAI_H2_SH(coeff0, coeff1, 3); + coeff0 = __msa_min_s_h(coeff0, max_coeff_thr); + coeff1 = __msa_min_s_h(coeff1, max_coeff_thr); + ST_SH2(coeff0, coeff1, &out[0], 8); + for (k = 0; k < 16; ++k) { + ++distribution[out[k]]; + } + } + } + VP8SetHistogramData(distribution, histo); +} + +//------------------------------------------------------------------------------ +// Intra predictions + +// luma 4x4 prediction + +#define DST(x, y) dst[(x) + (y) * BPS] +#define AVG3(a, b, c) (((a) + 2 * (b) + (c) + 2) >> 2) +#define AVG2(a, b) (((a) + (b) + 1) >> 1) + +static WEBP_INLINE void VE4(uint8_t* dst, const uint8_t* top) { // vertical + const v16u8 A1 = { 0 }; + const uint64_t val_m = LD(top - 1); + const v16u8 A = (v16u8)__msa_insert_d((v2i64)A1, 0, val_m); + const v16u8 B = SLDI_UB(A, A, 1); + const v16u8 C = SLDI_UB(A, A, 2); + const v16u8 AC = __msa_ave_u_b(A, C); + const v16u8 B2 = __msa_ave_u_b(B, B); + const v16u8 R = __msa_aver_u_b(AC, B2); + const uint32_t out = __msa_copy_s_w((v4i32)R, 0); + SW4(out, out, out, out, dst, BPS); +} + +static WEBP_INLINE void HE4(uint8_t* dst, const uint8_t* top) { // horizontal + const int X = top[-1]; + const int I = top[-2]; + const int J = top[-3]; + const int K = top[-4]; + const int L = top[-5]; + WebPUint32ToMem(dst + 0 * BPS, 0x01010101U * AVG3(X, I, J)); + WebPUint32ToMem(dst + 1 * BPS, 0x01010101U * AVG3(I, J, K)); + WebPUint32ToMem(dst + 2 * BPS, 0x01010101U * AVG3(J, K, L)); + WebPUint32ToMem(dst + 3 * BPS, 0x01010101U * AVG3(K, L, L)); +} + +static WEBP_INLINE void DC4(uint8_t* dst, const uint8_t* top) { + uint32_t dc = 4; + int i; + for (i = 0; i < 4; ++i) dc += top[i] + top[-5 + i]; + dc >>= 3; + dc = dc | (dc << 8) | (dc << 16) | (dc << 24); + SW4(dc, dc, dc, dc, dst, BPS); +} + +static WEBP_INLINE void RD4(uint8_t* dst, const uint8_t* top) { + const v16u8 A2 = { 0 }; + const uint64_t val_m = LD(top - 5); + const v16u8 A1 = (v16u8)__msa_insert_d((v2i64)A2, 0, val_m); + const v16u8 A = (v16u8)__msa_insert_b((v16i8)A1, 8, top[3]); + const v16u8 B = SLDI_UB(A, A, 1); + const v16u8 C = SLDI_UB(A, A, 2); + const v16u8 AC = __msa_ave_u_b(A, C); + const v16u8 B2 = __msa_ave_u_b(B, B); + const v16u8 R0 = __msa_aver_u_b(AC, B2); + const v16u8 R1 = SLDI_UB(R0, R0, 1); + const v16u8 R2 = SLDI_UB(R1, R1, 1); + const v16u8 R3 = SLDI_UB(R2, R2, 1); + const uint32_t val0 = __msa_copy_s_w((v4i32)R0, 0); + const uint32_t val1 = __msa_copy_s_w((v4i32)R1, 0); + const uint32_t val2 = __msa_copy_s_w((v4i32)R2, 0); + const uint32_t val3 = __msa_copy_s_w((v4i32)R3, 0); + SW4(val3, val2, val1, val0, dst, BPS); +} + +static WEBP_INLINE void LD4(uint8_t* dst, const uint8_t* top) { + const v16u8 A1 = { 0 }; + const uint64_t val_m = LD(top); + const v16u8 A = (v16u8)__msa_insert_d((v2i64)A1, 0, val_m); + const v16u8 B = SLDI_UB(A, A, 1); + const v16u8 C1 = SLDI_UB(A, A, 2); + const v16u8 C = (v16u8)__msa_insert_b((v16i8)C1, 6, top[7]); + const v16u8 AC = __msa_ave_u_b(A, C); + const v16u8 B2 = __msa_ave_u_b(B, B); + const v16u8 R0 = __msa_aver_u_b(AC, B2); + const v16u8 R1 = SLDI_UB(R0, R0, 1); + const v16u8 R2 = SLDI_UB(R1, R1, 1); + const v16u8 R3 = SLDI_UB(R2, R2, 1); + const uint32_t val0 = __msa_copy_s_w((v4i32)R0, 0); + const uint32_t val1 = __msa_copy_s_w((v4i32)R1, 0); + const uint32_t val2 = __msa_copy_s_w((v4i32)R2, 0); + const uint32_t val3 = __msa_copy_s_w((v4i32)R3, 0); + SW4(val0, val1, val2, val3, dst, BPS); +} + +static WEBP_INLINE void VR4(uint8_t* dst, const uint8_t* top) { + const int X = top[-1]; + const int I = top[-2]; + const int J = top[-3]; + const int K = top[-4]; + const int A = top[0]; + const int B = top[1]; + const int C = top[2]; + const int D = top[3]; + DST(0, 0) = DST(1, 2) = AVG2(X, A); + DST(1, 0) = DST(2, 2) = AVG2(A, B); + DST(2, 0) = DST(3, 2) = AVG2(B, C); + DST(3, 0) = AVG2(C, D); + DST(0, 3) = AVG3(K, J, I); + DST(0, 2) = AVG3(J, I, X); + DST(0, 1) = DST(1, 3) = AVG3(I, X, A); + DST(1, 1) = DST(2, 3) = AVG3(X, A, B); + DST(2, 1) = DST(3, 3) = AVG3(A, B, C); + DST(3, 1) = AVG3(B, C, D); +} + +static WEBP_INLINE void VL4(uint8_t* dst, const uint8_t* top) { + const int A = top[0]; + const int B = top[1]; + const int C = top[2]; + const int D = top[3]; + const int E = top[4]; + const int F = top[5]; + const int G = top[6]; + const int H = top[7]; + DST(0, 0) = AVG2(A, B); + DST(1, 0) = DST(0, 2) = AVG2(B, C); + DST(2, 0) = DST(1, 2) = AVG2(C, D); + DST(3, 0) = DST(2, 2) = AVG2(D, E); + DST(0, 1) = AVG3(A, B, C); + DST(1, 1) = DST(0, 3) = AVG3(B, C, D); + DST(2, 1) = DST(1, 3) = AVG3(C, D, E); + DST(3, 1) = DST(2, 3) = AVG3(D, E, F); + DST(3, 2) = AVG3(E, F, G); + DST(3, 3) = AVG3(F, G, H); +} + +static WEBP_INLINE void HU4(uint8_t* dst, const uint8_t* top) { + const int I = top[-2]; + const int J = top[-3]; + const int K = top[-4]; + const int L = top[-5]; + DST(0, 0) = AVG2(I, J); + DST(2, 0) = DST(0, 1) = AVG2(J, K); + DST(2, 1) = DST(0, 2) = AVG2(K, L); + DST(1, 0) = AVG3(I, J, K); + DST(3, 0) = DST(1, 1) = AVG3(J, K, L); + DST(3, 1) = DST(1, 2) = AVG3(K, L, L); + DST(3, 2) = DST(2, 2) = + DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L; +} + +static WEBP_INLINE void HD4(uint8_t* dst, const uint8_t* top) { + const int X = top[-1]; + const int I = top[-2]; + const int J = top[-3]; + const int K = top[-4]; + const int L = top[-5]; + const int A = top[0]; + const int B = top[1]; + const int C = top[2]; + DST(0, 0) = DST(2, 1) = AVG2(I, X); + DST(0, 1) = DST(2, 2) = AVG2(J, I); + DST(0, 2) = DST(2, 3) = AVG2(K, J); + DST(0, 3) = AVG2(L, K); + DST(3, 0) = AVG3(A, B, C); + DST(2, 0) = AVG3(X, A, B); + DST(1, 0) = DST(3, 1) = AVG3(I, X, A); + DST(1, 1) = DST(3, 2) = AVG3(J, I, X); + DST(1, 2) = DST(3, 3) = AVG3(K, J, I); + DST(1, 3) = AVG3(L, K, J); +} + +static WEBP_INLINE void TM4(uint8_t* dst, const uint8_t* top) { + const v16i8 zero = { 0 }; + const v8i16 TL = (v8i16)__msa_fill_h(top[-1]); + const v8i16 L0 = (v8i16)__msa_fill_h(top[-2]); + const v8i16 L1 = (v8i16)__msa_fill_h(top[-3]); + const v8i16 L2 = (v8i16)__msa_fill_h(top[-4]); + const v8i16 L3 = (v8i16)__msa_fill_h(top[-5]); + const v16u8 T1 = LD_UB(top); + const v8i16 T = (v8i16)__msa_ilvr_b(zero, (v16i8)T1); + const v8i16 d = T - TL; + v8i16 r0, r1, r2, r3; + ADD4(d, L0, d, L1, d, L2, d, L3, r0, r1, r2, r3); + CLIP_SH4_0_255(r0, r1, r2, r3); + PCKEV_ST4x4_UB(r0, r1, r2, r3, dst, BPS); +} + +#undef DST +#undef AVG3 +#undef AVG2 + +static void Intra4Preds_MSA(uint8_t* dst, const uint8_t* top) { + DC4(I4DC4 + dst, top); + TM4(I4TM4 + dst, top); + VE4(I4VE4 + dst, top); + HE4(I4HE4 + dst, top); + RD4(I4RD4 + dst, top); + VR4(I4VR4 + dst, top); + LD4(I4LD4 + dst, top); + VL4(I4VL4 + dst, top); + HD4(I4HD4 + dst, top); + HU4(I4HU4 + dst, top); +} + +// luma 16x16 prediction + +#define STORE16x16(out, dst) do { \ + ST_UB8(out, out, out, out, out, out, out, out, dst + 0 * BPS, BPS); \ + ST_UB8(out, out, out, out, out, out, out, out, dst + 8 * BPS, BPS); \ +} while (0) + +static WEBP_INLINE void VerticalPred16x16(uint8_t* dst, const uint8_t* top) { + if (top != NULL) { + const v16u8 out = LD_UB(top); + STORE16x16(out, dst); + } else { + const v16u8 out = (v16u8)__msa_fill_b(0x7f); + STORE16x16(out, dst); + } +} + +static WEBP_INLINE void HorizontalPred16x16(uint8_t* dst, + const uint8_t* left) { + if (left != NULL) { + int j; + for (j = 0; j < 16; j += 4) { + const v16u8 L0 = (v16u8)__msa_fill_b(left[0]); + const v16u8 L1 = (v16u8)__msa_fill_b(left[1]); + const v16u8 L2 = (v16u8)__msa_fill_b(left[2]); + const v16u8 L3 = (v16u8)__msa_fill_b(left[3]); + ST_UB4(L0, L1, L2, L3, dst, BPS); + dst += 4 * BPS; + left += 4; + } + } else { + const v16u8 out = (v16u8)__msa_fill_b(0x81); + STORE16x16(out, dst); + } +} + +static WEBP_INLINE void TrueMotion16x16(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { + if (left != NULL) { + if (top != NULL) { + int j; + v8i16 d1, d2; + const v16i8 zero = { 0 }; + const v8i16 TL = (v8i16)__msa_fill_h(left[-1]); + const v16u8 T = LD_UB(top); + ILVRL_B2_SH(zero, T, d1, d2); + SUB2(d1, TL, d2, TL, d1, d2); + for (j = 0; j < 16; j += 4) { + v16i8 t0, t1, t2, t3; + v8i16 r0, r1, r2, r3, r4, r5, r6, r7; + const v8i16 L0 = (v8i16)__msa_fill_h(left[j + 0]); + const v8i16 L1 = (v8i16)__msa_fill_h(left[j + 1]); + const v8i16 L2 = (v8i16)__msa_fill_h(left[j + 2]); + const v8i16 L3 = (v8i16)__msa_fill_h(left[j + 3]); + ADD4(d1, L0, d1, L1, d1, L2, d1, L3, r0, r1, r2, r3); + ADD4(d2, L0, d2, L1, d2, L2, d2, L3, r4, r5, r6, r7); + CLIP_SH4_0_255(r0, r1, r2, r3); + CLIP_SH4_0_255(r4, r5, r6, r7); + PCKEV_B4_SB(r4, r0, r5, r1, r6, r2, r7, r3, t0, t1, t2, t3); + ST_SB4(t0, t1, t2, t3, dst, BPS); + dst += 4 * BPS; + } + } else { + HorizontalPred16x16(dst, left); + } + } else { + if (top != NULL) { + VerticalPred16x16(dst, top); + } else { + const v16u8 out = (v16u8)__msa_fill_b(0x81); + STORE16x16(out, dst); + } + } +} + +static WEBP_INLINE void DCMode16x16(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { + int DC; + v16u8 out; + if (top != NULL && left != NULL) { + const v16u8 rtop = LD_UB(top); + const v8u16 dctop = __msa_hadd_u_h(rtop, rtop); + const v16u8 rleft = LD_UB(left); + const v8u16 dcleft = __msa_hadd_u_h(rleft, rleft); + const v8u16 dctemp = dctop + dcleft; + DC = HADD_UH_U32(dctemp); + DC = (DC + 16) >> 5; + } else if (left != NULL) { // left but no top + const v16u8 rleft = LD_UB(left); + const v8u16 dcleft = __msa_hadd_u_h(rleft, rleft); + DC = HADD_UH_U32(dcleft); + DC = (DC + DC + 16) >> 5; + } else if (top != NULL) { // top but no left + const v16u8 rtop = LD_UB(top); + const v8u16 dctop = __msa_hadd_u_h(rtop, rtop); + DC = HADD_UH_U32(dctop); + DC = (DC + DC + 16) >> 5; + } else { // no top, no left, nothing. + DC = 0x80; + } + out = (v16u8)__msa_fill_b(DC); + STORE16x16(out, dst); +} + +static void Intra16Preds_MSA(uint8_t* dst, + const uint8_t* left, const uint8_t* top) { + DCMode16x16(I16DC16 + dst, left, top); + VerticalPred16x16(I16VE16 + dst, top); + HorizontalPred16x16(I16HE16 + dst, left); + TrueMotion16x16(I16TM16 + dst, left, top); +} + +// Chroma 8x8 prediction + +#define CALC_DC8(in, out) do { \ + const v8u16 temp0 = __msa_hadd_u_h(in, in); \ + const v4u32 temp1 = __msa_hadd_u_w(temp0, temp0); \ + const v2i64 temp2 = (v2i64)__msa_hadd_u_d(temp1, temp1); \ + const v2i64 temp3 = __msa_splati_d(temp2, 1); \ + const v2i64 temp4 = temp3 + temp2; \ + const v16i8 temp5 = (v16i8)__msa_srari_d(temp4, 4); \ + const v2i64 temp6 = (v2i64)__msa_splati_b(temp5, 0); \ + out = __msa_copy_s_d(temp6, 0); \ +} while (0) + +#define STORE8x8(out, dst) do { \ + SD4(out, out, out, out, dst + 0 * BPS, BPS); \ + SD4(out, out, out, out, dst + 4 * BPS, BPS); \ +} while (0) + +static WEBP_INLINE void VerticalPred8x8(uint8_t* dst, const uint8_t* top) { + if (top != NULL) { + const uint64_t out = LD(top); + STORE8x8(out, dst); + } else { + const uint64_t out = 0x7f7f7f7f7f7f7f7fULL; + STORE8x8(out, dst); + } +} + +static WEBP_INLINE void HorizontalPred8x8(uint8_t* dst, const uint8_t* left) { + if (left != NULL) { + int j; + for (j = 0; j < 8; j += 4) { + const v16u8 L0 = (v16u8)__msa_fill_b(left[0]); + const v16u8 L1 = (v16u8)__msa_fill_b(left[1]); + const v16u8 L2 = (v16u8)__msa_fill_b(left[2]); + const v16u8 L3 = (v16u8)__msa_fill_b(left[3]); + const uint64_t out0 = __msa_copy_s_d((v2i64)L0, 0); + const uint64_t out1 = __msa_copy_s_d((v2i64)L1, 0); + const uint64_t out2 = __msa_copy_s_d((v2i64)L2, 0); + const uint64_t out3 = __msa_copy_s_d((v2i64)L3, 0); + SD4(out0, out1, out2, out3, dst, BPS); + dst += 4 * BPS; + left += 4; + } + } else { + const uint64_t out = 0x8181818181818181ULL; + STORE8x8(out, dst); + } +} + +static WEBP_INLINE void TrueMotion8x8(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { + if (left != NULL) { + if (top != NULL) { + int j; + const v8i16 TL = (v8i16)__msa_fill_h(left[-1]); + const v16u8 T1 = LD_UB(top); + const v16i8 zero = { 0 }; + const v8i16 T = (v8i16)__msa_ilvr_b(zero, (v16i8)T1); + const v8i16 d = T - TL; + for (j = 0; j < 8; j += 4) { + uint64_t out0, out1, out2, out3; + v16i8 t0, t1; + v8i16 r0 = (v8i16)__msa_fill_h(left[j + 0]); + v8i16 r1 = (v8i16)__msa_fill_h(left[j + 1]); + v8i16 r2 = (v8i16)__msa_fill_h(left[j + 2]); + v8i16 r3 = (v8i16)__msa_fill_h(left[j + 3]); + ADD4(d, r0, d, r1, d, r2, d, r3, r0, r1, r2, r3); + CLIP_SH4_0_255(r0, r1, r2, r3); + PCKEV_B2_SB(r1, r0, r3, r2, t0, t1); + out0 = __msa_copy_s_d((v2i64)t0, 0); + out1 = __msa_copy_s_d((v2i64)t0, 1); + out2 = __msa_copy_s_d((v2i64)t1, 0); + out3 = __msa_copy_s_d((v2i64)t1, 1); + SD4(out0, out1, out2, out3, dst, BPS); + dst += 4 * BPS; + } + } else { + HorizontalPred8x8(dst, left); + } + } else { + if (top != NULL) { + VerticalPred8x8(dst, top); + } else { + const uint64_t out = 0x8181818181818181ULL; + STORE8x8(out, dst); + } + } +} + +static WEBP_INLINE void DCMode8x8(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { + uint64_t out; + v16u8 src = { 0 }; + if (top != NULL && left != NULL) { + const uint64_t left_m = LD(left); + const uint64_t top_m = LD(top); + INSERT_D2_UB(left_m, top_m, src); + CALC_DC8(src, out); + } else if (left != NULL) { // left but no top + const uint64_t left_m = LD(left); + INSERT_D2_UB(left_m, left_m, src); + CALC_DC8(src, out); + } else if (top != NULL) { // top but no left + const uint64_t top_m = LD(top); + INSERT_D2_UB(top_m, top_m, src); + CALC_DC8(src, out); + } else { // no top, no left, nothing. + src = (v16u8)__msa_fill_b(0x80); + out = __msa_copy_s_d((v2i64)src, 0); + } + STORE8x8(out, dst); +} + +static void IntraChromaPreds_MSA(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { + // U block + DCMode8x8(C8DC8 + dst, left, top); + VerticalPred8x8(C8VE8 + dst, top); + HorizontalPred8x8(C8HE8 + dst, left); + TrueMotion8x8(C8TM8 + dst, left, top); + // V block + dst += 8; + if (top != NULL) top += 8; + if (left != NULL) left += 16; + DCMode8x8(C8DC8 + dst, left, top); + VerticalPred8x8(C8VE8 + dst, top); + HorizontalPred8x8(C8HE8 + dst, left); + TrueMotion8x8(C8TM8 + dst, left, top); +} + +//------------------------------------------------------------------------------ +// Metric + +#define PACK_DOTP_UB4_SW(in0, in1, in2, in3, out0, out1, out2, out3) do { \ + v16u8 tmp0, tmp1; \ + v8i16 tmp2, tmp3; \ + ILVRL_B2_UB(in0, in1, tmp0, tmp1); \ + HSUB_UB2_SH(tmp0, tmp1, tmp2, tmp3); \ + DOTP_SH2_SW(tmp2, tmp3, tmp2, tmp3, out0, out1); \ + ILVRL_B2_UB(in2, in3, tmp0, tmp1); \ + HSUB_UB2_SH(tmp0, tmp1, tmp2, tmp3); \ + DOTP_SH2_SW(tmp2, tmp3, tmp2, tmp3, out2, out3); \ +} while (0) + +#define PACK_DPADD_UB4_SW(in0, in1, in2, in3, out0, out1, out2, out3) do { \ + v16u8 tmp0, tmp1; \ + v8i16 tmp2, tmp3; \ + ILVRL_B2_UB(in0, in1, tmp0, tmp1); \ + HSUB_UB2_SH(tmp0, tmp1, tmp2, tmp3); \ + DPADD_SH2_SW(tmp2, tmp3, tmp2, tmp3, out0, out1); \ + ILVRL_B2_UB(in2, in3, tmp0, tmp1); \ + HSUB_UB2_SH(tmp0, tmp1, tmp2, tmp3); \ + DPADD_SH2_SW(tmp2, tmp3, tmp2, tmp3, out2, out3); \ +} while (0) + +static int SSE16x16_MSA(const uint8_t* a, const uint8_t* b) { + uint32_t sum; + v16u8 src0, src1, src2, src3, src4, src5, src6, src7; + v16u8 ref0, ref1, ref2, ref3, ref4, ref5, ref6, ref7; + v4i32 out0, out1, out2, out3; + + LD_UB8(a, BPS, src0, src1, src2, src3, src4, src5, src6, src7); + LD_UB8(b, BPS, ref0, ref1, ref2, ref3, ref4, ref5, ref6, ref7); + PACK_DOTP_UB4_SW(src0, ref0, src1, ref1, out0, out1, out2, out3); + PACK_DPADD_UB4_SW(src2, ref2, src3, ref3, out0, out1, out2, out3); + PACK_DPADD_UB4_SW(src4, ref4, src5, ref5, out0, out1, out2, out3); + PACK_DPADD_UB4_SW(src6, ref6, src7, ref7, out0, out1, out2, out3); + a += 8 * BPS; + b += 8 * BPS; + LD_UB8(a, BPS, src0, src1, src2, src3, src4, src5, src6, src7); + LD_UB8(b, BPS, ref0, ref1, ref2, ref3, ref4, ref5, ref6, ref7); + PACK_DPADD_UB4_SW(src0, ref0, src1, ref1, out0, out1, out2, out3); + PACK_DPADD_UB4_SW(src2, ref2, src3, ref3, out0, out1, out2, out3); + PACK_DPADD_UB4_SW(src4, ref4, src5, ref5, out0, out1, out2, out3); + PACK_DPADD_UB4_SW(src6, ref6, src7, ref7, out0, out1, out2, out3); + out0 += out1; + out2 += out3; + out0 += out2; + sum = HADD_SW_S32(out0); + return sum; +} + +static int SSE16x8_MSA(const uint8_t* a, const uint8_t* b) { + uint32_t sum; + v16u8 src0, src1, src2, src3, src4, src5, src6, src7; + v16u8 ref0, ref1, ref2, ref3, ref4, ref5, ref6, ref7; + v4i32 out0, out1, out2, out3; + + LD_UB8(a, BPS, src0, src1, src2, src3, src4, src5, src6, src7); + LD_UB8(b, BPS, ref0, ref1, ref2, ref3, ref4, ref5, ref6, ref7); + PACK_DOTP_UB4_SW(src0, ref0, src1, ref1, out0, out1, out2, out3); + PACK_DPADD_UB4_SW(src2, ref2, src3, ref3, out0, out1, out2, out3); + PACK_DPADD_UB4_SW(src4, ref4, src5, ref5, out0, out1, out2, out3); + PACK_DPADD_UB4_SW(src6, ref6, src7, ref7, out0, out1, out2, out3); + out0 += out1; + out2 += out3; + out0 += out2; + sum = HADD_SW_S32(out0); + return sum; +} + +static int SSE8x8_MSA(const uint8_t* a, const uint8_t* b) { + uint32_t sum; + v16u8 src0, src1, src2, src3, src4, src5, src6, src7; + v16u8 ref0, ref1, ref2, ref3, ref4, ref5, ref6, ref7; + v16u8 t0, t1, t2, t3; + v4i32 out0, out1, out2, out3; + + LD_UB8(a, BPS, src0, src1, src2, src3, src4, src5, src6, src7); + LD_UB8(b, BPS, ref0, ref1, ref2, ref3, ref4, ref5, ref6, ref7); + ILVR_B4_UB(src0, src1, src2, src3, ref0, ref1, ref2, ref3, t0, t1, t2, t3); + PACK_DOTP_UB4_SW(t0, t2, t1, t3, out0, out1, out2, out3); + ILVR_B4_UB(src4, src5, src6, src7, ref4, ref5, ref6, ref7, t0, t1, t2, t3); + PACK_DPADD_UB4_SW(t0, t2, t1, t3, out0, out1, out2, out3); + out0 += out1; + out2 += out3; + out0 += out2; + sum = HADD_SW_S32(out0); + return sum; +} + +static int SSE4x4_MSA(const uint8_t* a, const uint8_t* b) { + uint32_t sum = 0; + uint32_t src0, src1, src2, src3, ref0, ref1, ref2, ref3; + v16u8 src = { 0 }, ref = { 0 }, tmp0, tmp1; + v8i16 diff0, diff1; + v4i32 out0, out1; + + LW4(a, BPS, src0, src1, src2, src3); + LW4(b, BPS, ref0, ref1, ref2, ref3); + INSERT_W4_UB(src0, src1, src2, src3, src); + INSERT_W4_UB(ref0, ref1, ref2, ref3, ref); + ILVRL_B2_UB(src, ref, tmp0, tmp1); + HSUB_UB2_SH(tmp0, tmp1, diff0, diff1); + DOTP_SH2_SW(diff0, diff1, diff0, diff1, out0, out1); + out0 += out1; + sum = HADD_SW_S32(out0); + return sum; +} + +//------------------------------------------------------------------------------ +// Quantization + +static int QuantizeBlock_MSA(int16_t in[16], int16_t out[16], + const VP8Matrix* const mtx) { + int sum; + v8i16 in0, in1, sh0, sh1, out0, out1; + v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, sign0, sign1; + v4i32 s0, s1, s2, s3, b0, b1, b2, b3, t0, t1, t2, t3; + const v8i16 zero = { 0 }; + const v8i16 zigzag0 = { 0, 1, 4, 8, 5, 2, 3, 6 }; + const v8i16 zigzag1 = { 9, 12, 13, 10, 7, 11, 14, 15 }; + const v8i16 maxlevel = __msa_fill_h(MAX_LEVEL); + + LD_SH2(&in[0], 8, in0, in1); + LD_SH2(&mtx->sharpen_[0], 8, sh0, sh1); + tmp4 = __msa_add_a_h(in0, zero); + tmp5 = __msa_add_a_h(in1, zero); + ILVRL_H2_SH(sh0, tmp4, tmp0, tmp1); + ILVRL_H2_SH(sh1, tmp5, tmp2, tmp3); + HADD_SH4_SW(tmp0, tmp1, tmp2, tmp3, s0, s1, s2, s3); + sign0 = (in0 < zero); + sign1 = (in1 < zero); // sign + LD_SH2(&mtx->iq_[0], 8, tmp0, tmp1); // iq + ILVRL_H2_SW(zero, tmp0, t0, t1); + ILVRL_H2_SW(zero, tmp1, t2, t3); + LD_SW4(&mtx->bias_[0], 4, b0, b1, b2, b3); // bias + MUL4(t0, s0, t1, s1, t2, s2, t3, s3, t0, t1, t2, t3); + ADD4(b0, t0, b1, t1, b2, t2, b3, t3, b0, b1, b2, b3); + SRAI_W4_SW(b0, b1, b2, b3, 17); + PCKEV_H2_SH(b1, b0, b3, b2, tmp2, tmp3); + tmp0 = (tmp2 > maxlevel); + tmp1 = (tmp3 > maxlevel); + tmp2 = (v8i16)__msa_bmnz_v((v16u8)tmp2, (v16u8)maxlevel, (v16u8)tmp0); + tmp3 = (v8i16)__msa_bmnz_v((v16u8)tmp3, (v16u8)maxlevel, (v16u8)tmp1); + SUB2(zero, tmp2, zero, tmp3, tmp0, tmp1); + tmp2 = (v8i16)__msa_bmnz_v((v16u8)tmp2, (v16u8)tmp0, (v16u8)sign0); + tmp3 = (v8i16)__msa_bmnz_v((v16u8)tmp3, (v16u8)tmp1, (v16u8)sign1); + LD_SW4(&mtx->zthresh_[0], 4, t0, t1, t2, t3); // zthresh + t0 = (s0 > t0); + t1 = (s1 > t1); + t2 = (s2 > t2); + t3 = (s3 > t3); + PCKEV_H2_SH(t1, t0, t3, t2, tmp0, tmp1); + tmp4 = (v8i16)__msa_bmnz_v((v16u8)zero, (v16u8)tmp2, (v16u8)tmp0); + tmp5 = (v8i16)__msa_bmnz_v((v16u8)zero, (v16u8)tmp3, (v16u8)tmp1); + LD_SH2(&mtx->q_[0], 8, tmp0, tmp1); + MUL2(tmp4, tmp0, tmp5, tmp1, in0, in1); + VSHF_H2_SH(tmp4, tmp5, tmp4, tmp5, zigzag0, zigzag1, out0, out1); + ST_SH2(in0, in1, &in[0], 8); + ST_SH2(out0, out1, &out[0], 8); + out0 = __msa_add_a_h(out0, out1); + sum = HADD_SH_S32(out0); + return (sum > 0); +} + +static int Quantize2Blocks_MSA(int16_t in[32], int16_t out[32], + const VP8Matrix* const mtx) { + int nz; + nz = VP8EncQuantizeBlock(in + 0 * 16, out + 0 * 16, mtx) << 0; + nz |= VP8EncQuantizeBlock(in + 1 * 16, out + 1 * 16, mtx) << 1; + return nz; +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8EncDspInitMSA(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitMSA(void) { + VP8ITransform = ITransform_MSA; + VP8FTransform = FTransform_MSA; + VP8FTransformWHT = FTransformWHT_MSA; + + VP8TDisto4x4 = Disto4x4_MSA; + VP8TDisto16x16 = Disto16x16_MSA; + VP8CollectHistogram = CollectHistogram_MSA; + + VP8EncPredLuma4 = Intra4Preds_MSA; + VP8EncPredLuma16 = Intra16Preds_MSA; + VP8EncPredChroma8 = IntraChromaPreds_MSA; + + VP8SSE16x16 = SSE16x16_MSA; + VP8SSE16x8 = SSE16x8_MSA; + VP8SSE8x8 = SSE8x8_MSA; + VP8SSE4x4 = SSE4x4_MSA; + + VP8EncQuantizeBlock = QuantizeBlock_MSA; + VP8EncQuantize2Blocks = Quantize2Blocks_MSA; + VP8EncQuantizeBlockWHT = QuantizeBlock_MSA; +} + +#else // !WEBP_USE_MSA + +WEBP_DSP_INIT_STUB(VP8EncDspInitMSA) + +#endif // WEBP_USE_MSA diff --git a/third-party/webp/libwebp/src/dsp/enc_neon.c b/third-party/webp/libwebp/src/dsp/enc_neon.c new file mode 100644 index 0000000000..714800367b --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/enc_neon.c @@ -0,0 +1,943 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// ARM NEON version of speed-critical encoding functions. +// +// adapted from libvpx (https://www.webmproject.org/code/) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_NEON) + +#include + +#include "src/dsp/neon.h" +#include "src/enc/vp8i_enc.h" + +//------------------------------------------------------------------------------ +// Transforms (Paragraph 14.4) + +// Inverse transform. +// This code is pretty much the same as TransformOne in the dec_neon.c, except +// for subtraction to *ref. See the comments there for algorithmic explanations. + +static const int16_t kC1 = 20091; +static const int16_t kC2 = 17734; // half of kC2, actually. See comment above. + +// This code works but is *slower* than the inlined-asm version below +// (with gcc-4.6). So we disable it for now. Later, it'll be conditional to +// WEBP_USE_INTRINSICS define. +// With gcc-4.8, it's a little faster speed than inlined-assembly. +#if defined(WEBP_USE_INTRINSICS) + +// Treats 'v' as an uint8x8_t and zero extends to an int16x8_t. +static WEBP_INLINE int16x8_t ConvertU8ToS16_NEON(uint32x2_t v) { + return vreinterpretq_s16_u16(vmovl_u8(vreinterpret_u8_u32(v))); +} + +// Performs unsigned 8b saturation on 'dst01' and 'dst23' storing the result +// to the corresponding rows of 'dst'. +static WEBP_INLINE void SaturateAndStore4x4_NEON(uint8_t* const dst, + const int16x8_t dst01, + const int16x8_t dst23) { + // Unsigned saturate to 8b. + const uint8x8_t dst01_u8 = vqmovun_s16(dst01); + const uint8x8_t dst23_u8 = vqmovun_s16(dst23); + + // Store the results. + vst1_lane_u32((uint32_t*)(dst + 0 * BPS), vreinterpret_u32_u8(dst01_u8), 0); + vst1_lane_u32((uint32_t*)(dst + 1 * BPS), vreinterpret_u32_u8(dst01_u8), 1); + vst1_lane_u32((uint32_t*)(dst + 2 * BPS), vreinterpret_u32_u8(dst23_u8), 0); + vst1_lane_u32((uint32_t*)(dst + 3 * BPS), vreinterpret_u32_u8(dst23_u8), 1); +} + +static WEBP_INLINE void Add4x4_NEON(const int16x8_t row01, + const int16x8_t row23, + const uint8_t* const ref, + uint8_t* const dst) { + uint32x2_t dst01 = vdup_n_u32(0); + uint32x2_t dst23 = vdup_n_u32(0); + + // Load the source pixels. + dst01 = vld1_lane_u32((uint32_t*)(ref + 0 * BPS), dst01, 0); + dst23 = vld1_lane_u32((uint32_t*)(ref + 2 * BPS), dst23, 0); + dst01 = vld1_lane_u32((uint32_t*)(ref + 1 * BPS), dst01, 1); + dst23 = vld1_lane_u32((uint32_t*)(ref + 3 * BPS), dst23, 1); + + { + // Convert to 16b. + const int16x8_t dst01_s16 = ConvertU8ToS16_NEON(dst01); + const int16x8_t dst23_s16 = ConvertU8ToS16_NEON(dst23); + + // Descale with rounding. + const int16x8_t out01 = vrsraq_n_s16(dst01_s16, row01, 3); + const int16x8_t out23 = vrsraq_n_s16(dst23_s16, row23, 3); + // Add the inverse transform. + SaturateAndStore4x4_NEON(dst, out01, out23); + } +} + +static WEBP_INLINE void Transpose8x2_NEON(const int16x8_t in0, + const int16x8_t in1, + int16x8x2_t* const out) { + // a0 a1 a2 a3 | b0 b1 b2 b3 => a0 b0 c0 d0 | a1 b1 c1 d1 + // c0 c1 c2 c3 | d0 d1 d2 d3 a2 b2 c2 d2 | a3 b3 c3 d3 + const int16x8x2_t tmp0 = vzipq_s16(in0, in1); // a0 c0 a1 c1 a2 c2 ... + // b0 d0 b1 d1 b2 d2 ... + *out = vzipq_s16(tmp0.val[0], tmp0.val[1]); +} + +static WEBP_INLINE void TransformPass_NEON(int16x8x2_t* const rows) { + // {rows} = in0 | in4 + // in8 | in12 + // B1 = in4 | in12 + const int16x8_t B1 = + vcombine_s16(vget_high_s16(rows->val[0]), vget_high_s16(rows->val[1])); + // C0 = kC1 * in4 | kC1 * in12 + // C1 = kC2 * in4 | kC2 * in12 + const int16x8_t C0 = vsraq_n_s16(B1, vqdmulhq_n_s16(B1, kC1), 1); + const int16x8_t C1 = vqdmulhq_n_s16(B1, kC2); + const int16x4_t a = vqadd_s16(vget_low_s16(rows->val[0]), + vget_low_s16(rows->val[1])); // in0 + in8 + const int16x4_t b = vqsub_s16(vget_low_s16(rows->val[0]), + vget_low_s16(rows->val[1])); // in0 - in8 + // c = kC2 * in4 - kC1 * in12 + // d = kC1 * in4 + kC2 * in12 + const int16x4_t c = vqsub_s16(vget_low_s16(C1), vget_high_s16(C0)); + const int16x4_t d = vqadd_s16(vget_low_s16(C0), vget_high_s16(C1)); + const int16x8_t D0 = vcombine_s16(a, b); // D0 = a | b + const int16x8_t D1 = vcombine_s16(d, c); // D1 = d | c + const int16x8_t E0 = vqaddq_s16(D0, D1); // a+d | b+c + const int16x8_t E_tmp = vqsubq_s16(D0, D1); // a-d | b-c + const int16x8_t E1 = vcombine_s16(vget_high_s16(E_tmp), vget_low_s16(E_tmp)); + Transpose8x2_NEON(E0, E1, rows); +} + +static void ITransformOne_NEON(const uint8_t* ref, + const int16_t* in, uint8_t* dst) { + int16x8x2_t rows; + INIT_VECTOR2(rows, vld1q_s16(in + 0), vld1q_s16(in + 8)); + TransformPass_NEON(&rows); + TransformPass_NEON(&rows); + Add4x4_NEON(rows.val[0], rows.val[1], ref, dst); +} + +#else + +static void ITransformOne_NEON(const uint8_t* ref, + const int16_t* in, uint8_t* dst) { + const int kBPS = BPS; + const int16_t kC1C2[] = { kC1, kC2, 0, 0 }; + + __asm__ volatile ( + "vld1.16 {q1, q2}, [%[in]] \n" + "vld1.16 {d0}, [%[kC1C2]] \n" + + // d2: in[0] + // d3: in[8] + // d4: in[4] + // d5: in[12] + "vswp d3, d4 \n" + + // q8 = {in[4], in[12]} * kC1 * 2 >> 16 + // q9 = {in[4], in[12]} * kC2 >> 16 + "vqdmulh.s16 q8, q2, d0[0] \n" + "vqdmulh.s16 q9, q2, d0[1] \n" + + // d22 = a = in[0] + in[8] + // d23 = b = in[0] - in[8] + "vqadd.s16 d22, d2, d3 \n" + "vqsub.s16 d23, d2, d3 \n" + + // q8 = in[4]/[12] * kC1 >> 16 + "vshr.s16 q8, q8, #1 \n" + + // Add {in[4], in[12]} back after the multiplication. + "vqadd.s16 q8, q2, q8 \n" + + // d20 = c = in[4]*kC2 - in[12]*kC1 + // d21 = d = in[4]*kC1 + in[12]*kC2 + "vqsub.s16 d20, d18, d17 \n" + "vqadd.s16 d21, d19, d16 \n" + + // d2 = tmp[0] = a + d + // d3 = tmp[1] = b + c + // d4 = tmp[2] = b - c + // d5 = tmp[3] = a - d + "vqadd.s16 d2, d22, d21 \n" + "vqadd.s16 d3, d23, d20 \n" + "vqsub.s16 d4, d23, d20 \n" + "vqsub.s16 d5, d22, d21 \n" + + "vzip.16 q1, q2 \n" + "vzip.16 q1, q2 \n" + + "vswp d3, d4 \n" + + // q8 = {tmp[4], tmp[12]} * kC1 * 2 >> 16 + // q9 = {tmp[4], tmp[12]} * kC2 >> 16 + "vqdmulh.s16 q8, q2, d0[0] \n" + "vqdmulh.s16 q9, q2, d0[1] \n" + + // d22 = a = tmp[0] + tmp[8] + // d23 = b = tmp[0] - tmp[8] + "vqadd.s16 d22, d2, d3 \n" + "vqsub.s16 d23, d2, d3 \n" + + "vshr.s16 q8, q8, #1 \n" + "vqadd.s16 q8, q2, q8 \n" + + // d20 = c = in[4]*kC2 - in[12]*kC1 + // d21 = d = in[4]*kC1 + in[12]*kC2 + "vqsub.s16 d20, d18, d17 \n" + "vqadd.s16 d21, d19, d16 \n" + + // d2 = tmp[0] = a + d + // d3 = tmp[1] = b + c + // d4 = tmp[2] = b - c + // d5 = tmp[3] = a - d + "vqadd.s16 d2, d22, d21 \n" + "vqadd.s16 d3, d23, d20 \n" + "vqsub.s16 d4, d23, d20 \n" + "vqsub.s16 d5, d22, d21 \n" + + "vld1.32 d6[0], [%[ref]], %[kBPS] \n" + "vld1.32 d6[1], [%[ref]], %[kBPS] \n" + "vld1.32 d7[0], [%[ref]], %[kBPS] \n" + "vld1.32 d7[1], [%[ref]], %[kBPS] \n" + + "sub %[ref], %[ref], %[kBPS], lsl #2 \n" + + // (val) + 4 >> 3 + "vrshr.s16 d2, d2, #3 \n" + "vrshr.s16 d3, d3, #3 \n" + "vrshr.s16 d4, d4, #3 \n" + "vrshr.s16 d5, d5, #3 \n" + + "vzip.16 q1, q2 \n" + "vzip.16 q1, q2 \n" + + // Must accumulate before saturating + "vmovl.u8 q8, d6 \n" + "vmovl.u8 q9, d7 \n" + + "vqadd.s16 q1, q1, q8 \n" + "vqadd.s16 q2, q2, q9 \n" + + "vqmovun.s16 d0, q1 \n" + "vqmovun.s16 d1, q2 \n" + + "vst1.32 d0[0], [%[dst]], %[kBPS] \n" + "vst1.32 d0[1], [%[dst]], %[kBPS] \n" + "vst1.32 d1[0], [%[dst]], %[kBPS] \n" + "vst1.32 d1[1], [%[dst]] \n" + + : [in] "+r"(in), [dst] "+r"(dst) // modified registers + : [kBPS] "r"(kBPS), [kC1C2] "r"(kC1C2), [ref] "r"(ref) // constants + : "memory", "q0", "q1", "q2", "q8", "q9", "q10", "q11" // clobbered + ); +} + +#endif // WEBP_USE_INTRINSICS + +static void ITransform_NEON(const uint8_t* ref, + const int16_t* in, uint8_t* dst, int do_two) { + ITransformOne_NEON(ref, in, dst); + if (do_two) { + ITransformOne_NEON(ref + 4, in + 16, dst + 4); + } +} + +// Load all 4x4 pixels into a single uint8x16_t variable. +static uint8x16_t Load4x4_NEON(const uint8_t* src) { + uint32x4_t out = vdupq_n_u32(0); + out = vld1q_lane_u32((const uint32_t*)(src + 0 * BPS), out, 0); + out = vld1q_lane_u32((const uint32_t*)(src + 1 * BPS), out, 1); + out = vld1q_lane_u32((const uint32_t*)(src + 2 * BPS), out, 2); + out = vld1q_lane_u32((const uint32_t*)(src + 3 * BPS), out, 3); + return vreinterpretq_u8_u32(out); +} + +// Forward transform. + +#if defined(WEBP_USE_INTRINSICS) + +static WEBP_INLINE void Transpose4x4_S16_NEON(const int16x4_t A, + const int16x4_t B, + const int16x4_t C, + const int16x4_t D, + int16x8_t* const out01, + int16x8_t* const out32) { + const int16x4x2_t AB = vtrn_s16(A, B); + const int16x4x2_t CD = vtrn_s16(C, D); + const int32x2x2_t tmp02 = vtrn_s32(vreinterpret_s32_s16(AB.val[0]), + vreinterpret_s32_s16(CD.val[0])); + const int32x2x2_t tmp13 = vtrn_s32(vreinterpret_s32_s16(AB.val[1]), + vreinterpret_s32_s16(CD.val[1])); + *out01 = vreinterpretq_s16_s64( + vcombine_s64(vreinterpret_s64_s32(tmp02.val[0]), + vreinterpret_s64_s32(tmp13.val[0]))); + *out32 = vreinterpretq_s16_s64( + vcombine_s64(vreinterpret_s64_s32(tmp13.val[1]), + vreinterpret_s64_s32(tmp02.val[1]))); +} + +static WEBP_INLINE int16x8_t DiffU8ToS16_NEON(const uint8x8_t a, + const uint8x8_t b) { + return vreinterpretq_s16_u16(vsubl_u8(a, b)); +} + +static void FTransform_NEON(const uint8_t* src, const uint8_t* ref, + int16_t* out) { + int16x8_t d0d1, d3d2; // working 4x4 int16 variables + { + const uint8x16_t S0 = Load4x4_NEON(src); + const uint8x16_t R0 = Load4x4_NEON(ref); + const int16x8_t D0D1 = DiffU8ToS16_NEON(vget_low_u8(S0), vget_low_u8(R0)); + const int16x8_t D2D3 = DiffU8ToS16_NEON(vget_high_u8(S0), vget_high_u8(R0)); + const int16x4_t D0 = vget_low_s16(D0D1); + const int16x4_t D1 = vget_high_s16(D0D1); + const int16x4_t D2 = vget_low_s16(D2D3); + const int16x4_t D3 = vget_high_s16(D2D3); + Transpose4x4_S16_NEON(D0, D1, D2, D3, &d0d1, &d3d2); + } + { // 1rst pass + const int32x4_t kCst937 = vdupq_n_s32(937); + const int32x4_t kCst1812 = vdupq_n_s32(1812); + const int16x8_t a0a1 = vaddq_s16(d0d1, d3d2); // d0+d3 | d1+d2 (=a0|a1) + const int16x8_t a3a2 = vsubq_s16(d0d1, d3d2); // d0-d3 | d1-d2 (=a3|a2) + const int16x8_t a0a1_2 = vshlq_n_s16(a0a1, 3); + const int16x4_t tmp0 = vadd_s16(vget_low_s16(a0a1_2), + vget_high_s16(a0a1_2)); + const int16x4_t tmp2 = vsub_s16(vget_low_s16(a0a1_2), + vget_high_s16(a0a1_2)); + const int32x4_t a3_2217 = vmull_n_s16(vget_low_s16(a3a2), 2217); + const int32x4_t a2_2217 = vmull_n_s16(vget_high_s16(a3a2), 2217); + const int32x4_t a2_p_a3 = vmlal_n_s16(a2_2217, vget_low_s16(a3a2), 5352); + const int32x4_t a3_m_a2 = vmlsl_n_s16(a3_2217, vget_high_s16(a3a2), 5352); + const int16x4_t tmp1 = vshrn_n_s32(vaddq_s32(a2_p_a3, kCst1812), 9); + const int16x4_t tmp3 = vshrn_n_s32(vaddq_s32(a3_m_a2, kCst937), 9); + Transpose4x4_S16_NEON(tmp0, tmp1, tmp2, tmp3, &d0d1, &d3d2); + } + { // 2nd pass + // the (1<<16) addition is for the replacement: a3!=0 <-> 1-(a3==0) + const int32x4_t kCst12000 = vdupq_n_s32(12000 + (1 << 16)); + const int32x4_t kCst51000 = vdupq_n_s32(51000); + const int16x8_t a0a1 = vaddq_s16(d0d1, d3d2); // d0+d3 | d1+d2 (=a0|a1) + const int16x8_t a3a2 = vsubq_s16(d0d1, d3d2); // d0-d3 | d1-d2 (=a3|a2) + const int16x4_t a0_k7 = vadd_s16(vget_low_s16(a0a1), vdup_n_s16(7)); + const int16x4_t out0 = vshr_n_s16(vadd_s16(a0_k7, vget_high_s16(a0a1)), 4); + const int16x4_t out2 = vshr_n_s16(vsub_s16(a0_k7, vget_high_s16(a0a1)), 4); + const int32x4_t a3_2217 = vmull_n_s16(vget_low_s16(a3a2), 2217); + const int32x4_t a2_2217 = vmull_n_s16(vget_high_s16(a3a2), 2217); + const int32x4_t a2_p_a3 = vmlal_n_s16(a2_2217, vget_low_s16(a3a2), 5352); + const int32x4_t a3_m_a2 = vmlsl_n_s16(a3_2217, vget_high_s16(a3a2), 5352); + const int16x4_t tmp1 = vaddhn_s32(a2_p_a3, kCst12000); + const int16x4_t out3 = vaddhn_s32(a3_m_a2, kCst51000); + const int16x4_t a3_eq_0 = + vreinterpret_s16_u16(vceq_s16(vget_low_s16(a3a2), vdup_n_s16(0))); + const int16x4_t out1 = vadd_s16(tmp1, a3_eq_0); + vst1_s16(out + 0, out0); + vst1_s16(out + 4, out1); + vst1_s16(out + 8, out2); + vst1_s16(out + 12, out3); + } +} + +#else + +// adapted from vp8/encoder/arm/neon/shortfdct_neon.asm +static const int16_t kCoeff16[] = { + 5352, 5352, 5352, 5352, 2217, 2217, 2217, 2217 +}; +static const int32_t kCoeff32[] = { + 1812, 1812, 1812, 1812, + 937, 937, 937, 937, + 12000, 12000, 12000, 12000, + 51000, 51000, 51000, 51000 +}; + +static void FTransform_NEON(const uint8_t* src, const uint8_t* ref, + int16_t* out) { + const int kBPS = BPS; + const uint8_t* src_ptr = src; + const uint8_t* ref_ptr = ref; + const int16_t* coeff16 = kCoeff16; + const int32_t* coeff32 = kCoeff32; + + __asm__ volatile ( + // load src into q4, q5 in high half + "vld1.8 {d8}, [%[src_ptr]], %[kBPS] \n" + "vld1.8 {d10}, [%[src_ptr]], %[kBPS] \n" + "vld1.8 {d9}, [%[src_ptr]], %[kBPS] \n" + "vld1.8 {d11}, [%[src_ptr]] \n" + + // load ref into q6, q7 in high half + "vld1.8 {d12}, [%[ref_ptr]], %[kBPS] \n" + "vld1.8 {d14}, [%[ref_ptr]], %[kBPS] \n" + "vld1.8 {d13}, [%[ref_ptr]], %[kBPS] \n" + "vld1.8 {d15}, [%[ref_ptr]] \n" + + // Pack the high values in to q4 and q6 + "vtrn.32 q4, q5 \n" + "vtrn.32 q6, q7 \n" + + // d[0-3] = src - ref + "vsubl.u8 q0, d8, d12 \n" + "vsubl.u8 q1, d9, d13 \n" + + // load coeff16 into q8(d16=5352, d17=2217) + "vld1.16 {q8}, [%[coeff16]] \n" + + // load coeff32 high half into q9 = 1812, q10 = 937 + "vld1.32 {q9, q10}, [%[coeff32]]! \n" + + // load coeff32 low half into q11=12000, q12=51000 + "vld1.32 {q11,q12}, [%[coeff32]] \n" + + // part 1 + // Transpose. Register dN is the same as dN in C + "vtrn.32 d0, d2 \n" + "vtrn.32 d1, d3 \n" + "vtrn.16 d0, d1 \n" + "vtrn.16 d2, d3 \n" + + "vadd.s16 d4, d0, d3 \n" // a0 = d0 + d3 + "vadd.s16 d5, d1, d2 \n" // a1 = d1 + d2 + "vsub.s16 d6, d1, d2 \n" // a2 = d1 - d2 + "vsub.s16 d7, d0, d3 \n" // a3 = d0 - d3 + + "vadd.s16 d0, d4, d5 \n" // a0 + a1 + "vshl.s16 d0, d0, #3 \n" // temp[0+i*4] = (a0+a1) << 3 + "vsub.s16 d2, d4, d5 \n" // a0 - a1 + "vshl.s16 d2, d2, #3 \n" // (temp[2+i*4] = (a0-a1) << 3 + + "vmlal.s16 q9, d7, d16 \n" // a3*5352 + 1812 + "vmlal.s16 q10, d7, d17 \n" // a3*2217 + 937 + "vmlal.s16 q9, d6, d17 \n" // a2*2217 + a3*5352 + 1812 + "vmlsl.s16 q10, d6, d16 \n" // a3*2217 + 937 - a2*5352 + + // temp[1+i*4] = (d2*2217 + d3*5352 + 1812) >> 9 + // temp[3+i*4] = (d3*2217 + 937 - d2*5352) >> 9 + "vshrn.s32 d1, q9, #9 \n" + "vshrn.s32 d3, q10, #9 \n" + + // part 2 + // transpose d0=ip[0], d1=ip[4], d2=ip[8], d3=ip[12] + "vtrn.32 d0, d2 \n" + "vtrn.32 d1, d3 \n" + "vtrn.16 d0, d1 \n" + "vtrn.16 d2, d3 \n" + + "vmov.s16 d26, #7 \n" + + "vadd.s16 d4, d0, d3 \n" // a1 = ip[0] + ip[12] + "vadd.s16 d5, d1, d2 \n" // b1 = ip[4] + ip[8] + "vsub.s16 d6, d1, d2 \n" // c1 = ip[4] - ip[8] + "vadd.s16 d4, d4, d26 \n" // a1 + 7 + "vsub.s16 d7, d0, d3 \n" // d1 = ip[0] - ip[12] + + "vadd.s16 d0, d4, d5 \n" // op[0] = a1 + b1 + 7 + "vsub.s16 d2, d4, d5 \n" // op[8] = a1 - b1 + 7 + + "vmlal.s16 q11, d7, d16 \n" // d1*5352 + 12000 + "vmlal.s16 q12, d7, d17 \n" // d1*2217 + 51000 + + "vceq.s16 d4, d7, #0 \n" + + "vshr.s16 d0, d0, #4 \n" + "vshr.s16 d2, d2, #4 \n" + + "vmlal.s16 q11, d6, d17 \n" // c1*2217 + d1*5352 + 12000 + "vmlsl.s16 q12, d6, d16 \n" // d1*2217 - c1*5352 + 51000 + + "vmvn d4, d4 \n" // !(d1 == 0) + // op[4] = (c1*2217 + d1*5352 + 12000)>>16 + "vshrn.s32 d1, q11, #16 \n" + // op[4] += (d1!=0) + "vsub.s16 d1, d1, d4 \n" + // op[12]= (d1*2217 - c1*5352 + 51000)>>16 + "vshrn.s32 d3, q12, #16 \n" + + // set result to out array + "vst1.16 {q0, q1}, [%[out]] \n" + : [src_ptr] "+r"(src_ptr), [ref_ptr] "+r"(ref_ptr), + [coeff32] "+r"(coeff32) // modified registers + : [kBPS] "r"(kBPS), [coeff16] "r"(coeff16), + [out] "r"(out) // constants + : "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", + "q10", "q11", "q12", "q13" // clobbered + ); +} + +#endif + +#define LOAD_LANE_16b(VALUE, LANE) do { \ + (VALUE) = vld1_lane_s16(src, (VALUE), (LANE)); \ + src += stride; \ +} while (0) + +static void FTransformWHT_NEON(const int16_t* src, int16_t* out) { + const int stride = 16; + const int16x4_t zero = vdup_n_s16(0); + int32x4x4_t tmp0; + int16x4x4_t in; + INIT_VECTOR4(in, zero, zero, zero, zero); + LOAD_LANE_16b(in.val[0], 0); + LOAD_LANE_16b(in.val[1], 0); + LOAD_LANE_16b(in.val[2], 0); + LOAD_LANE_16b(in.val[3], 0); + LOAD_LANE_16b(in.val[0], 1); + LOAD_LANE_16b(in.val[1], 1); + LOAD_LANE_16b(in.val[2], 1); + LOAD_LANE_16b(in.val[3], 1); + LOAD_LANE_16b(in.val[0], 2); + LOAD_LANE_16b(in.val[1], 2); + LOAD_LANE_16b(in.val[2], 2); + LOAD_LANE_16b(in.val[3], 2); + LOAD_LANE_16b(in.val[0], 3); + LOAD_LANE_16b(in.val[1], 3); + LOAD_LANE_16b(in.val[2], 3); + LOAD_LANE_16b(in.val[3], 3); + + { + // a0 = in[0 * 16] + in[2 * 16] + // a1 = in[1 * 16] + in[3 * 16] + // a2 = in[1 * 16] - in[3 * 16] + // a3 = in[0 * 16] - in[2 * 16] + const int32x4_t a0 = vaddl_s16(in.val[0], in.val[2]); + const int32x4_t a1 = vaddl_s16(in.val[1], in.val[3]); + const int32x4_t a2 = vsubl_s16(in.val[1], in.val[3]); + const int32x4_t a3 = vsubl_s16(in.val[0], in.val[2]); + tmp0.val[0] = vaddq_s32(a0, a1); + tmp0.val[1] = vaddq_s32(a3, a2); + tmp0.val[2] = vsubq_s32(a3, a2); + tmp0.val[3] = vsubq_s32(a0, a1); + } + { + const int32x4x4_t tmp1 = Transpose4x4_NEON(tmp0); + // a0 = tmp[0 + i] + tmp[ 8 + i] + // a1 = tmp[4 + i] + tmp[12 + i] + // a2 = tmp[4 + i] - tmp[12 + i] + // a3 = tmp[0 + i] - tmp[ 8 + i] + const int32x4_t a0 = vaddq_s32(tmp1.val[0], tmp1.val[2]); + const int32x4_t a1 = vaddq_s32(tmp1.val[1], tmp1.val[3]); + const int32x4_t a2 = vsubq_s32(tmp1.val[1], tmp1.val[3]); + const int32x4_t a3 = vsubq_s32(tmp1.val[0], tmp1.val[2]); + const int32x4_t b0 = vhaddq_s32(a0, a1); // (a0 + a1) >> 1 + const int32x4_t b1 = vhaddq_s32(a3, a2); // (a3 + a2) >> 1 + const int32x4_t b2 = vhsubq_s32(a3, a2); // (a3 - a2) >> 1 + const int32x4_t b3 = vhsubq_s32(a0, a1); // (a0 - a1) >> 1 + const int16x4_t out0 = vmovn_s32(b0); + const int16x4_t out1 = vmovn_s32(b1); + const int16x4_t out2 = vmovn_s32(b2); + const int16x4_t out3 = vmovn_s32(b3); + + vst1_s16(out + 0, out0); + vst1_s16(out + 4, out1); + vst1_s16(out + 8, out2); + vst1_s16(out + 12, out3); + } +} +#undef LOAD_LANE_16b + +//------------------------------------------------------------------------------ +// Texture distortion +// +// We try to match the spectral content (weighted) between source and +// reconstructed samples. + +// a 0123, b 0123 +// a 4567, b 4567 +// a 89ab, b 89ab +// a cdef, b cdef +// +// transpose +// +// a 048c, b 048c +// a 159d, b 159d +// a 26ae, b 26ae +// a 37bf, b 37bf +// +static WEBP_INLINE int16x8x4_t DistoTranspose4x4S16_NEON(int16x8x4_t q4_in) { + const int16x8x2_t q2_tmp0 = vtrnq_s16(q4_in.val[0], q4_in.val[1]); + const int16x8x2_t q2_tmp1 = vtrnq_s16(q4_in.val[2], q4_in.val[3]); + const int32x4x2_t q2_tmp2 = vtrnq_s32(vreinterpretq_s32_s16(q2_tmp0.val[0]), + vreinterpretq_s32_s16(q2_tmp1.val[0])); + const int32x4x2_t q2_tmp3 = vtrnq_s32(vreinterpretq_s32_s16(q2_tmp0.val[1]), + vreinterpretq_s32_s16(q2_tmp1.val[1])); + q4_in.val[0] = vreinterpretq_s16_s32(q2_tmp2.val[0]); + q4_in.val[2] = vreinterpretq_s16_s32(q2_tmp2.val[1]); + q4_in.val[1] = vreinterpretq_s16_s32(q2_tmp3.val[0]); + q4_in.val[3] = vreinterpretq_s16_s32(q2_tmp3.val[1]); + return q4_in; +} + +static WEBP_INLINE int16x8x4_t DistoHorizontalPass_NEON( + const int16x8x4_t q4_in) { + // {a0, a1} = {in[0] + in[2], in[1] + in[3]} + // {a3, a2} = {in[0] - in[2], in[1] - in[3]} + const int16x8_t q_a0 = vaddq_s16(q4_in.val[0], q4_in.val[2]); + const int16x8_t q_a1 = vaddq_s16(q4_in.val[1], q4_in.val[3]); + const int16x8_t q_a3 = vsubq_s16(q4_in.val[0], q4_in.val[2]); + const int16x8_t q_a2 = vsubq_s16(q4_in.val[1], q4_in.val[3]); + int16x8x4_t q4_out; + // tmp[0] = a0 + a1 + // tmp[1] = a3 + a2 + // tmp[2] = a3 - a2 + // tmp[3] = a0 - a1 + INIT_VECTOR4(q4_out, + vabsq_s16(vaddq_s16(q_a0, q_a1)), + vabsq_s16(vaddq_s16(q_a3, q_a2)), + vabdq_s16(q_a3, q_a2), vabdq_s16(q_a0, q_a1)); + return q4_out; +} + +static WEBP_INLINE int16x8x4_t DistoVerticalPass_NEON(const uint8x8x4_t q4_in) { + const int16x8_t q_a0 = vreinterpretq_s16_u16(vaddl_u8(q4_in.val[0], + q4_in.val[2])); + const int16x8_t q_a1 = vreinterpretq_s16_u16(vaddl_u8(q4_in.val[1], + q4_in.val[3])); + const int16x8_t q_a2 = vreinterpretq_s16_u16(vsubl_u8(q4_in.val[1], + q4_in.val[3])); + const int16x8_t q_a3 = vreinterpretq_s16_u16(vsubl_u8(q4_in.val[0], + q4_in.val[2])); + int16x8x4_t q4_out; + + INIT_VECTOR4(q4_out, + vaddq_s16(q_a0, q_a1), vaddq_s16(q_a3, q_a2), + vsubq_s16(q_a3, q_a2), vsubq_s16(q_a0, q_a1)); + return q4_out; +} + +static WEBP_INLINE int16x4x4_t DistoLoadW_NEON(const uint16_t* w) { + const uint16x8_t q_w07 = vld1q_u16(&w[0]); + const uint16x8_t q_w8f = vld1q_u16(&w[8]); + int16x4x4_t d4_w; + INIT_VECTOR4(d4_w, + vget_low_s16(vreinterpretq_s16_u16(q_w07)), + vget_high_s16(vreinterpretq_s16_u16(q_w07)), + vget_low_s16(vreinterpretq_s16_u16(q_w8f)), + vget_high_s16(vreinterpretq_s16_u16(q_w8f))); + return d4_w; +} + +static WEBP_INLINE int32x2_t DistoSum_NEON(const int16x8x4_t q4_in, + const int16x4x4_t d4_w) { + int32x2_t d_sum; + // sum += w[ 0] * abs(b0); + // sum += w[ 4] * abs(b1); + // sum += w[ 8] * abs(b2); + // sum += w[12] * abs(b3); + int32x4_t q_sum0 = vmull_s16(d4_w.val[0], vget_low_s16(q4_in.val[0])); + int32x4_t q_sum1 = vmull_s16(d4_w.val[1], vget_low_s16(q4_in.val[1])); + int32x4_t q_sum2 = vmull_s16(d4_w.val[2], vget_low_s16(q4_in.val[2])); + int32x4_t q_sum3 = vmull_s16(d4_w.val[3], vget_low_s16(q4_in.val[3])); + q_sum0 = vmlsl_s16(q_sum0, d4_w.val[0], vget_high_s16(q4_in.val[0])); + q_sum1 = vmlsl_s16(q_sum1, d4_w.val[1], vget_high_s16(q4_in.val[1])); + q_sum2 = vmlsl_s16(q_sum2, d4_w.val[2], vget_high_s16(q4_in.val[2])); + q_sum3 = vmlsl_s16(q_sum3, d4_w.val[3], vget_high_s16(q4_in.val[3])); + + q_sum0 = vaddq_s32(q_sum0, q_sum1); + q_sum2 = vaddq_s32(q_sum2, q_sum3); + q_sum2 = vaddq_s32(q_sum0, q_sum2); + d_sum = vpadd_s32(vget_low_s32(q_sum2), vget_high_s32(q_sum2)); + d_sum = vpadd_s32(d_sum, d_sum); + return d_sum; +} + +#define LOAD_LANE_32b(src, VALUE, LANE) \ + (VALUE) = vld1_lane_u32((const uint32_t*)(src), (VALUE), (LANE)) + +// Hadamard transform +// Returns the weighted sum of the absolute value of transformed coefficients. +// w[] contains a row-major 4 by 4 symmetric matrix. +static int Disto4x4_NEON(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + uint32x2_t d_in_ab_0123 = vdup_n_u32(0); + uint32x2_t d_in_ab_4567 = vdup_n_u32(0); + uint32x2_t d_in_ab_89ab = vdup_n_u32(0); + uint32x2_t d_in_ab_cdef = vdup_n_u32(0); + uint8x8x4_t d4_in; + + // load data a, b + LOAD_LANE_32b(a + 0 * BPS, d_in_ab_0123, 0); + LOAD_LANE_32b(a + 1 * BPS, d_in_ab_4567, 0); + LOAD_LANE_32b(a + 2 * BPS, d_in_ab_89ab, 0); + LOAD_LANE_32b(a + 3 * BPS, d_in_ab_cdef, 0); + LOAD_LANE_32b(b + 0 * BPS, d_in_ab_0123, 1); + LOAD_LANE_32b(b + 1 * BPS, d_in_ab_4567, 1); + LOAD_LANE_32b(b + 2 * BPS, d_in_ab_89ab, 1); + LOAD_LANE_32b(b + 3 * BPS, d_in_ab_cdef, 1); + INIT_VECTOR4(d4_in, + vreinterpret_u8_u32(d_in_ab_0123), + vreinterpret_u8_u32(d_in_ab_4567), + vreinterpret_u8_u32(d_in_ab_89ab), + vreinterpret_u8_u32(d_in_ab_cdef)); + + { + // Vertical pass first to avoid a transpose (vertical and horizontal passes + // are commutative because w/kWeightY is symmetric) and subsequent + // transpose. + const int16x8x4_t q4_v = DistoVerticalPass_NEON(d4_in); + const int16x4x4_t d4_w = DistoLoadW_NEON(w); + // horizontal pass + const int16x8x4_t q4_t = DistoTranspose4x4S16_NEON(q4_v); + const int16x8x4_t q4_h = DistoHorizontalPass_NEON(q4_t); + int32x2_t d_sum = DistoSum_NEON(q4_h, d4_w); + + // abs(sum2 - sum1) >> 5 + d_sum = vabs_s32(d_sum); + d_sum = vshr_n_s32(d_sum, 5); + return vget_lane_s32(d_sum, 0); + } +} +#undef LOAD_LANE_32b + +static int Disto16x16_NEON(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + int D = 0; + int x, y; + for (y = 0; y < 16 * BPS; y += 4 * BPS) { + for (x = 0; x < 16; x += 4) { + D += Disto4x4_NEON(a + x + y, b + x + y, w); + } + } + return D; +} + +//------------------------------------------------------------------------------ + +static void CollectHistogram_NEON(const uint8_t* ref, const uint8_t* pred, + int start_block, int end_block, + VP8Histogram* const histo) { + const uint16x8_t max_coeff_thresh = vdupq_n_u16(MAX_COEFF_THRESH); + int j; + int distribution[MAX_COEFF_THRESH + 1] = { 0 }; + for (j = start_block; j < end_block; ++j) { + int16_t out[16]; + FTransform_NEON(ref + VP8DspScan[j], pred + VP8DspScan[j], out); + { + int k; + const int16x8_t a0 = vld1q_s16(out + 0); + const int16x8_t b0 = vld1q_s16(out + 8); + const uint16x8_t a1 = vreinterpretq_u16_s16(vabsq_s16(a0)); + const uint16x8_t b1 = vreinterpretq_u16_s16(vabsq_s16(b0)); + const uint16x8_t a2 = vshrq_n_u16(a1, 3); + const uint16x8_t b2 = vshrq_n_u16(b1, 3); + const uint16x8_t a3 = vminq_u16(a2, max_coeff_thresh); + const uint16x8_t b3 = vminq_u16(b2, max_coeff_thresh); + vst1q_s16(out + 0, vreinterpretq_s16_u16(a3)); + vst1q_s16(out + 8, vreinterpretq_s16_u16(b3)); + // Convert coefficients to bin. + for (k = 0; k < 16; ++k) { + ++distribution[out[k]]; + } + } + } + VP8SetHistogramData(distribution, histo); +} + +//------------------------------------------------------------------------------ + +static WEBP_INLINE void AccumulateSSE16_NEON(const uint8_t* const a, + const uint8_t* const b, + uint32x4_t* const sum) { + const uint8x16_t a0 = vld1q_u8(a); + const uint8x16_t b0 = vld1q_u8(b); + const uint8x16_t abs_diff = vabdq_u8(a0, b0); + const uint16x8_t prod1 = vmull_u8(vget_low_u8(abs_diff), + vget_low_u8(abs_diff)); + const uint16x8_t prod2 = vmull_u8(vget_high_u8(abs_diff), + vget_high_u8(abs_diff)); + /* pair-wise adds and widen */ + const uint32x4_t sum1 = vpaddlq_u16(prod1); + const uint32x4_t sum2 = vpaddlq_u16(prod2); + *sum = vaddq_u32(*sum, vaddq_u32(sum1, sum2)); +} + +// Horizontal sum of all four uint32_t values in 'sum'. +static int SumToInt_NEON(uint32x4_t sum) { +#if WEBP_AARCH64 + return (int)vaddvq_u32(sum); +#else + const uint64x2_t sum2 = vpaddlq_u32(sum); + const uint32x2_t sum3 = vadd_u32(vreinterpret_u32_u64(vget_low_u64(sum2)), + vreinterpret_u32_u64(vget_high_u64(sum2))); + return (int)vget_lane_u32(sum3, 0); +#endif +} + +static int SSE16x16_NEON(const uint8_t* a, const uint8_t* b) { + uint32x4_t sum = vdupq_n_u32(0); + int y; + for (y = 0; y < 16; ++y) { + AccumulateSSE16_NEON(a + y * BPS, b + y * BPS, &sum); + } + return SumToInt_NEON(sum); +} + +static int SSE16x8_NEON(const uint8_t* a, const uint8_t* b) { + uint32x4_t sum = vdupq_n_u32(0); + int y; + for (y = 0; y < 8; ++y) { + AccumulateSSE16_NEON(a + y * BPS, b + y * BPS, &sum); + } + return SumToInt_NEON(sum); +} + +static int SSE8x8_NEON(const uint8_t* a, const uint8_t* b) { + uint32x4_t sum = vdupq_n_u32(0); + int y; + for (y = 0; y < 8; ++y) { + const uint8x8_t a0 = vld1_u8(a + y * BPS); + const uint8x8_t b0 = vld1_u8(b + y * BPS); + const uint8x8_t abs_diff = vabd_u8(a0, b0); + const uint16x8_t prod = vmull_u8(abs_diff, abs_diff); + sum = vpadalq_u16(sum, prod); + } + return SumToInt_NEON(sum); +} + +static int SSE4x4_NEON(const uint8_t* a, const uint8_t* b) { + const uint8x16_t a0 = Load4x4_NEON(a); + const uint8x16_t b0 = Load4x4_NEON(b); + const uint8x16_t abs_diff = vabdq_u8(a0, b0); + const uint16x8_t prod1 = vmull_u8(vget_low_u8(abs_diff), + vget_low_u8(abs_diff)); + const uint16x8_t prod2 = vmull_u8(vget_high_u8(abs_diff), + vget_high_u8(abs_diff)); + /* pair-wise adds and widen */ + const uint32x4_t sum1 = vpaddlq_u16(prod1); + const uint32x4_t sum2 = vpaddlq_u16(prod2); + return SumToInt_NEON(vaddq_u32(sum1, sum2)); +} + +//------------------------------------------------------------------------------ + +// Compilation with gcc-4.6.x is problematic for now. +#if !defined(WORK_AROUND_GCC) + +static int16x8_t Quantize_NEON(int16_t* const in, + const VP8Matrix* const mtx, int offset) { + const uint16x8_t sharp = vld1q_u16(&mtx->sharpen_[offset]); + const uint16x8_t q = vld1q_u16(&mtx->q_[offset]); + const uint16x8_t iq = vld1q_u16(&mtx->iq_[offset]); + const uint32x4_t bias0 = vld1q_u32(&mtx->bias_[offset + 0]); + const uint32x4_t bias1 = vld1q_u32(&mtx->bias_[offset + 4]); + + const int16x8_t a = vld1q_s16(in + offset); // in + const uint16x8_t b = vreinterpretq_u16_s16(vabsq_s16(a)); // coeff = abs(in) + const int16x8_t sign = vshrq_n_s16(a, 15); // sign + const uint16x8_t c = vaddq_u16(b, sharp); // + sharpen + const uint32x4_t m0 = vmull_u16(vget_low_u16(c), vget_low_u16(iq)); + const uint32x4_t m1 = vmull_u16(vget_high_u16(c), vget_high_u16(iq)); + const uint32x4_t m2 = vhaddq_u32(m0, bias0); + const uint32x4_t m3 = vhaddq_u32(m1, bias1); // (coeff * iQ + bias) >> 1 + const uint16x8_t c0 = vcombine_u16(vshrn_n_u32(m2, 16), + vshrn_n_u32(m3, 16)); // QFIX=17 = 16+1 + const uint16x8_t c1 = vminq_u16(c0, vdupq_n_u16(MAX_LEVEL)); + const int16x8_t c2 = veorq_s16(vreinterpretq_s16_u16(c1), sign); + const int16x8_t c3 = vsubq_s16(c2, sign); // restore sign + const int16x8_t c4 = vmulq_s16(c3, vreinterpretq_s16_u16(q)); + vst1q_s16(in + offset, c4); + assert(QFIX == 17); // this function can't work as is if QFIX != 16+1 + return c3; +} + +static const uint8_t kShuffles[4][8] = { + { 0, 1, 2, 3, 8, 9, 16, 17 }, + { 10, 11, 4, 5, 6, 7, 12, 13 }, + { 18, 19, 24, 25, 26, 27, 20, 21 }, + { 14, 15, 22, 23, 28, 29, 30, 31 } +}; + +static int QuantizeBlock_NEON(int16_t in[16], int16_t out[16], + const VP8Matrix* const mtx) { + const int16x8_t out0 = Quantize_NEON(in, mtx, 0); + const int16x8_t out1 = Quantize_NEON(in, mtx, 8); + uint8x8x4_t shuffles; + // vtbl?_u8 are marked unavailable for iOS arm64 with Xcode < 6.3, use + // non-standard versions there. +#if defined(__APPLE__) && WEBP_AARCH64 && \ + defined(__apple_build_version__) && (__apple_build_version__< 6020037) + uint8x16x2_t all_out; + INIT_VECTOR2(all_out, vreinterpretq_u8_s16(out0), vreinterpretq_u8_s16(out1)); + INIT_VECTOR4(shuffles, + vtbl2q_u8(all_out, vld1_u8(kShuffles[0])), + vtbl2q_u8(all_out, vld1_u8(kShuffles[1])), + vtbl2q_u8(all_out, vld1_u8(kShuffles[2])), + vtbl2q_u8(all_out, vld1_u8(kShuffles[3]))); +#else + uint8x8x4_t all_out; + INIT_VECTOR4(all_out, + vreinterpret_u8_s16(vget_low_s16(out0)), + vreinterpret_u8_s16(vget_high_s16(out0)), + vreinterpret_u8_s16(vget_low_s16(out1)), + vreinterpret_u8_s16(vget_high_s16(out1))); + INIT_VECTOR4(shuffles, + vtbl4_u8(all_out, vld1_u8(kShuffles[0])), + vtbl4_u8(all_out, vld1_u8(kShuffles[1])), + vtbl4_u8(all_out, vld1_u8(kShuffles[2])), + vtbl4_u8(all_out, vld1_u8(kShuffles[3]))); +#endif + // Zigzag reordering + vst1_u8((uint8_t*)(out + 0), shuffles.val[0]); + vst1_u8((uint8_t*)(out + 4), shuffles.val[1]); + vst1_u8((uint8_t*)(out + 8), shuffles.val[2]); + vst1_u8((uint8_t*)(out + 12), shuffles.val[3]); + // test zeros + if (*(uint64_t*)(out + 0) != 0) return 1; + if (*(uint64_t*)(out + 4) != 0) return 1; + if (*(uint64_t*)(out + 8) != 0) return 1; + if (*(uint64_t*)(out + 12) != 0) return 1; + return 0; +} + +static int Quantize2Blocks_NEON(int16_t in[32], int16_t out[32], + const VP8Matrix* const mtx) { + int nz; + nz = QuantizeBlock_NEON(in + 0 * 16, out + 0 * 16, mtx) << 0; + nz |= QuantizeBlock_NEON(in + 1 * 16, out + 1 * 16, mtx) << 1; + return nz; +} + +#endif // !WORK_AROUND_GCC + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8EncDspInitNEON(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitNEON(void) { + VP8ITransform = ITransform_NEON; + VP8FTransform = FTransform_NEON; + + VP8FTransformWHT = FTransformWHT_NEON; + + VP8TDisto4x4 = Disto4x4_NEON; + VP8TDisto16x16 = Disto16x16_NEON; + VP8CollectHistogram = CollectHistogram_NEON; + + VP8SSE16x16 = SSE16x16_NEON; + VP8SSE16x8 = SSE16x8_NEON; + VP8SSE8x8 = SSE8x8_NEON; + VP8SSE4x4 = SSE4x4_NEON; + +#if !defined(WORK_AROUND_GCC) + VP8EncQuantizeBlock = QuantizeBlock_NEON; + VP8EncQuantize2Blocks = Quantize2Blocks_NEON; +#endif +} + +#else // !WEBP_USE_NEON + +WEBP_DSP_INIT_STUB(VP8EncDspInitNEON) + +#endif // WEBP_USE_NEON diff --git a/third-party/webp/libwebp/src/dsp/enc_sse2.c b/third-party/webp/libwebp/src/dsp/enc_sse2.c new file mode 100644 index 0000000000..010624a2f7 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/enc_sse2.c @@ -0,0 +1,1514 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE2 version of speed-critical encoding functions. +// +// Author: Christian Duvivier (cduvivier@google.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE2) +#include +#include // for abs() +#include + +#include "src/dsp/common_sse2.h" +#include "src/enc/cost_enc.h" +#include "src/enc/vp8i_enc.h" + +//------------------------------------------------------------------------------ +// Transforms (Paragraph 14.4) + +// Does one inverse transform. +static void ITransform_One_SSE2(const uint8_t* ref, const int16_t* in, + uint8_t* dst) { + // This implementation makes use of 16-bit fixed point versions of two + // multiply constants: + // K1 = sqrt(2) * cos (pi/8) ~= 85627 / 2^16 + // K2 = sqrt(2) * sin (pi/8) ~= 35468 / 2^16 + // + // To be able to use signed 16-bit integers, we use the following trick to + // have constants within range: + // - Associated constants are obtained by subtracting the 16-bit fixed point + // version of one: + // k = K - (1 << 16) => K = k + (1 << 16) + // K1 = 85267 => k1 = 20091 + // K2 = 35468 => k2 = -30068 + // - The multiplication of a variable by a constant become the sum of the + // variable and the multiplication of that variable by the associated + // constant: + // (x * K) >> 16 = (x * (k + (1 << 16))) >> 16 = ((x * k ) >> 16) + x + const __m128i k1k2 = _mm_set_epi16(-30068, -30068, -30068, -30068, + 20091, 20091, 20091, 20091); + const __m128i k2k1 = _mm_set_epi16(20091, 20091, 20091, 20091, + -30068, -30068, -30068, -30068); + const __m128i zero = _mm_setzero_si128(); + const __m128i zero_four = _mm_set_epi16(0, 0, 0, 0, 4, 4, 4, 4); + __m128i T01, T23; + + // Load and concatenate the transform coefficients. + const __m128i in01 = _mm_loadu_si128((const __m128i*)&in[0]); + const __m128i in23 = _mm_loadu_si128((const __m128i*)&in[8]); + // a00 a10 a20 a30 a01 a11 a21 a31 + // a02 a12 a22 a32 a03 a13 a23 a33 + + // Vertical pass and subsequent transpose. + { + const __m128i in1 = _mm_unpackhi_epi64(in01, in01); + const __m128i in3 = _mm_unpackhi_epi64(in23, in23); + + // First pass, c and d calculations are longer because of the "trick" + // multiplications. + // c = MUL(in1, K2) - MUL(in3, K1) = MUL(in1, k2) - MUL(in3, k1) + in1 - in3 + // d = MUL(in1, K1) + MUL(in3, K2) = MUL(in1, k1) + MUL(in3, k2) + in1 + in3 + const __m128i a_d3 = _mm_add_epi16(in01, in23); + const __m128i b_c3 = _mm_sub_epi16(in01, in23); + const __m128i c1d1 = _mm_mulhi_epi16(in1, k2k1); + const __m128i c2d2 = _mm_mulhi_epi16(in3, k1k2); + const __m128i c3 = _mm_unpackhi_epi64(b_c3, b_c3); + const __m128i c4 = _mm_sub_epi16(c1d1, c2d2); + const __m128i c = _mm_add_epi16(c3, c4); + const __m128i d4u = _mm_add_epi16(c1d1, c2d2); + const __m128i du = _mm_add_epi16(a_d3, d4u); + const __m128i d = _mm_unpackhi_epi64(du, du); + + // Second pass. + const __m128i comb_ab = _mm_unpacklo_epi64(a_d3, b_c3); + const __m128i comb_dc = _mm_unpacklo_epi64(d, c); + + const __m128i tmp01 = _mm_add_epi16(comb_ab, comb_dc); + const __m128i tmp32 = _mm_sub_epi16(comb_ab, comb_dc); + const __m128i tmp23 = _mm_shuffle_epi32(tmp32, _MM_SHUFFLE(1, 0, 3, 2)); + + const __m128i transpose_0 = _mm_unpacklo_epi16(tmp01, tmp23); + const __m128i transpose_1 = _mm_unpackhi_epi16(tmp01, tmp23); + // a00 a20 a01 a21 a02 a22 a03 a23 + // a10 a30 a11 a31 a12 a32 a13 a33 + + T01 = _mm_unpacklo_epi16(transpose_0, transpose_1); + T23 = _mm_unpackhi_epi16(transpose_0, transpose_1); + // a00 a10 a20 a30 a01 a11 a21 a31 + // a02 a12 a22 a32 a03 a13 a23 a33 + } + + // Horizontal pass and subsequent transpose. + { + const __m128i T1 = _mm_unpackhi_epi64(T01, T01); + const __m128i T3 = _mm_unpackhi_epi64(T23, T23); + + // First pass, c and d calculations are longer because of the "trick" + // multiplications. + const __m128i dc = _mm_add_epi16(T01, zero_four); + + // c = MUL(T1, K2) - MUL(T3, K1) = MUL(T1, k2) - MUL(T3, k1) + T1 - T3 + // d = MUL(T1, K1) + MUL(T3, K2) = MUL(T1, k1) + MUL(T3, k2) + T1 + T3 + const __m128i a_d3 = _mm_add_epi16(dc, T23); + const __m128i b_c3 = _mm_sub_epi16(dc, T23); + const __m128i c1d1 = _mm_mulhi_epi16(T1, k2k1); + const __m128i c2d2 = _mm_mulhi_epi16(T3, k1k2); + const __m128i c3 = _mm_unpackhi_epi64(b_c3, b_c3); + const __m128i c4 = _mm_sub_epi16(c1d1, c2d2); + const __m128i c = _mm_add_epi16(c3, c4); + const __m128i d4u = _mm_add_epi16(c1d1, c2d2); + const __m128i du = _mm_add_epi16(a_d3, d4u); + const __m128i d = _mm_unpackhi_epi64(du, du); + + // Second pass. + const __m128i comb_ab = _mm_unpacklo_epi64(a_d3, b_c3); + const __m128i comb_dc = _mm_unpacklo_epi64(d, c); + + const __m128i tmp01 = _mm_add_epi16(comb_ab, comb_dc); + const __m128i tmp32 = _mm_sub_epi16(comb_ab, comb_dc); + const __m128i tmp23 = _mm_shuffle_epi32(tmp32, _MM_SHUFFLE(1, 0, 3, 2)); + + const __m128i shifted01 = _mm_srai_epi16(tmp01, 3); + const __m128i shifted23 = _mm_srai_epi16(tmp23, 3); + // a00 a01 a02 a03 a10 a11 a12 a13 + // a20 a21 a22 a23 a30 a31 a32 a33 + + const __m128i transpose_0 = _mm_unpacklo_epi16(shifted01, shifted23); + const __m128i transpose_1 = _mm_unpackhi_epi16(shifted01, shifted23); + // a00 a20 a01 a21 a02 a22 a03 a23 + // a10 a30 a11 a31 a12 a32 a13 a33 + + T01 = _mm_unpacklo_epi16(transpose_0, transpose_1); + T23 = _mm_unpackhi_epi16(transpose_0, transpose_1); + // a00 a10 a20 a30 a01 a11 a21 a31 + // a02 a12 a22 a32 a03 a13 a23 a33 + } + + // Add inverse transform to 'ref' and store. + { + // Load the reference(s). + __m128i ref01, ref23, ref0123; + int32_t buf[4]; + + // Load four bytes/pixels per line. + const __m128i ref0 = _mm_cvtsi32_si128(WebPMemToInt32(&ref[0 * BPS])); + const __m128i ref1 = _mm_cvtsi32_si128(WebPMemToInt32(&ref[1 * BPS])); + const __m128i ref2 = _mm_cvtsi32_si128(WebPMemToInt32(&ref[2 * BPS])); + const __m128i ref3 = _mm_cvtsi32_si128(WebPMemToInt32(&ref[3 * BPS])); + ref01 = _mm_unpacklo_epi32(ref0, ref1); + ref23 = _mm_unpacklo_epi32(ref2, ref3); + + // Convert to 16b. + ref01 = _mm_unpacklo_epi8(ref01, zero); + ref23 = _mm_unpacklo_epi8(ref23, zero); + // Add the inverse transform(s). + ref01 = _mm_add_epi16(ref01, T01); + ref23 = _mm_add_epi16(ref23, T23); + // Unsigned saturate to 8b. + ref0123 = _mm_packus_epi16(ref01, ref23); + + _mm_storeu_si128((__m128i *)buf, ref0123); + + // Store four bytes/pixels per line. + WebPInt32ToMem(&dst[0 * BPS], buf[0]); + WebPInt32ToMem(&dst[1 * BPS], buf[1]); + WebPInt32ToMem(&dst[2 * BPS], buf[2]); + WebPInt32ToMem(&dst[3 * BPS], buf[3]); + } +} + +// Does two inverse transforms. +static void ITransform_Two_SSE2(const uint8_t* ref, const int16_t* in, + uint8_t* dst) { + // This implementation makes use of 16-bit fixed point versions of two + // multiply constants: + // K1 = sqrt(2) * cos (pi/8) ~= 85627 / 2^16 + // K2 = sqrt(2) * sin (pi/8) ~= 35468 / 2^16 + // + // To be able to use signed 16-bit integers, we use the following trick to + // have constants within range: + // - Associated constants are obtained by subtracting the 16-bit fixed point + // version of one: + // k = K - (1 << 16) => K = k + (1 << 16) + // K1 = 85267 => k1 = 20091 + // K2 = 35468 => k2 = -30068 + // - The multiplication of a variable by a constant become the sum of the + // variable and the multiplication of that variable by the associated + // constant: + // (x * K) >> 16 = (x * (k + (1 << 16))) >> 16 = ((x * k ) >> 16) + x + const __m128i k1 = _mm_set1_epi16(20091); + const __m128i k2 = _mm_set1_epi16(-30068); + __m128i T0, T1, T2, T3; + + // Load and concatenate the transform coefficients (we'll do two inverse + // transforms in parallel). + __m128i in0, in1, in2, in3; + { + const __m128i tmp0 = _mm_loadu_si128((const __m128i*)&in[0]); + const __m128i tmp1 = _mm_loadu_si128((const __m128i*)&in[8]); + const __m128i tmp2 = _mm_loadu_si128((const __m128i*)&in[16]); + const __m128i tmp3 = _mm_loadu_si128((const __m128i*)&in[24]); + in0 = _mm_unpacklo_epi64(tmp0, tmp2); + in1 = _mm_unpackhi_epi64(tmp0, tmp2); + in2 = _mm_unpacklo_epi64(tmp1, tmp3); + in3 = _mm_unpackhi_epi64(tmp1, tmp3); + // a00 a10 a20 a30 b00 b10 b20 b30 + // a01 a11 a21 a31 b01 b11 b21 b31 + // a02 a12 a22 a32 b02 b12 b22 b32 + // a03 a13 a23 a33 b03 b13 b23 b33 + } + + // Vertical pass and subsequent transpose. + { + // First pass, c and d calculations are longer because of the "trick" + // multiplications. + const __m128i a = _mm_add_epi16(in0, in2); + const __m128i b = _mm_sub_epi16(in0, in2); + // c = MUL(in1, K2) - MUL(in3, K1) = MUL(in1, k2) - MUL(in3, k1) + in1 - in3 + const __m128i c1 = _mm_mulhi_epi16(in1, k2); + const __m128i c2 = _mm_mulhi_epi16(in3, k1); + const __m128i c3 = _mm_sub_epi16(in1, in3); + const __m128i c4 = _mm_sub_epi16(c1, c2); + const __m128i c = _mm_add_epi16(c3, c4); + // d = MUL(in1, K1) + MUL(in3, K2) = MUL(in1, k1) + MUL(in3, k2) + in1 + in3 + const __m128i d1 = _mm_mulhi_epi16(in1, k1); + const __m128i d2 = _mm_mulhi_epi16(in3, k2); + const __m128i d3 = _mm_add_epi16(in1, in3); + const __m128i d4 = _mm_add_epi16(d1, d2); + const __m128i d = _mm_add_epi16(d3, d4); + + // Second pass. + const __m128i tmp0 = _mm_add_epi16(a, d); + const __m128i tmp1 = _mm_add_epi16(b, c); + const __m128i tmp2 = _mm_sub_epi16(b, c); + const __m128i tmp3 = _mm_sub_epi16(a, d); + + // Transpose the two 4x4. + VP8Transpose_2_4x4_16b(&tmp0, &tmp1, &tmp2, &tmp3, &T0, &T1, &T2, &T3); + } + + // Horizontal pass and subsequent transpose. + { + // First pass, c and d calculations are longer because of the "trick" + // multiplications. + const __m128i four = _mm_set1_epi16(4); + const __m128i dc = _mm_add_epi16(T0, four); + const __m128i a = _mm_add_epi16(dc, T2); + const __m128i b = _mm_sub_epi16(dc, T2); + // c = MUL(T1, K2) - MUL(T3, K1) = MUL(T1, k2) - MUL(T3, k1) + T1 - T3 + const __m128i c1 = _mm_mulhi_epi16(T1, k2); + const __m128i c2 = _mm_mulhi_epi16(T3, k1); + const __m128i c3 = _mm_sub_epi16(T1, T3); + const __m128i c4 = _mm_sub_epi16(c1, c2); + const __m128i c = _mm_add_epi16(c3, c4); + // d = MUL(T1, K1) + MUL(T3, K2) = MUL(T1, k1) + MUL(T3, k2) + T1 + T3 + const __m128i d1 = _mm_mulhi_epi16(T1, k1); + const __m128i d2 = _mm_mulhi_epi16(T3, k2); + const __m128i d3 = _mm_add_epi16(T1, T3); + const __m128i d4 = _mm_add_epi16(d1, d2); + const __m128i d = _mm_add_epi16(d3, d4); + + // Second pass. + const __m128i tmp0 = _mm_add_epi16(a, d); + const __m128i tmp1 = _mm_add_epi16(b, c); + const __m128i tmp2 = _mm_sub_epi16(b, c); + const __m128i tmp3 = _mm_sub_epi16(a, d); + const __m128i shifted0 = _mm_srai_epi16(tmp0, 3); + const __m128i shifted1 = _mm_srai_epi16(tmp1, 3); + const __m128i shifted2 = _mm_srai_epi16(tmp2, 3); + const __m128i shifted3 = _mm_srai_epi16(tmp3, 3); + + // Transpose the two 4x4. + VP8Transpose_2_4x4_16b(&shifted0, &shifted1, &shifted2, &shifted3, &T0, &T1, + &T2, &T3); + } + + // Add inverse transform to 'ref' and store. + { + const __m128i zero = _mm_setzero_si128(); + // Load the reference(s). + __m128i ref0, ref1, ref2, ref3; + // Load eight bytes/pixels per line. + ref0 = _mm_loadl_epi64((const __m128i*)&ref[0 * BPS]); + ref1 = _mm_loadl_epi64((const __m128i*)&ref[1 * BPS]); + ref2 = _mm_loadl_epi64((const __m128i*)&ref[2 * BPS]); + ref3 = _mm_loadl_epi64((const __m128i*)&ref[3 * BPS]); + // Convert to 16b. + ref0 = _mm_unpacklo_epi8(ref0, zero); + ref1 = _mm_unpacklo_epi8(ref1, zero); + ref2 = _mm_unpacklo_epi8(ref2, zero); + ref3 = _mm_unpacklo_epi8(ref3, zero); + // Add the inverse transform(s). + ref0 = _mm_add_epi16(ref0, T0); + ref1 = _mm_add_epi16(ref1, T1); + ref2 = _mm_add_epi16(ref2, T2); + ref3 = _mm_add_epi16(ref3, T3); + // Unsigned saturate to 8b. + ref0 = _mm_packus_epi16(ref0, ref0); + ref1 = _mm_packus_epi16(ref1, ref1); + ref2 = _mm_packus_epi16(ref2, ref2); + ref3 = _mm_packus_epi16(ref3, ref3); + // Store eight bytes/pixels per line. + _mm_storel_epi64((__m128i*)&dst[0 * BPS], ref0); + _mm_storel_epi64((__m128i*)&dst[1 * BPS], ref1); + _mm_storel_epi64((__m128i*)&dst[2 * BPS], ref2); + _mm_storel_epi64((__m128i*)&dst[3 * BPS], ref3); + } +} + +// Does one or two inverse transforms. +static void ITransform_SSE2(const uint8_t* ref, const int16_t* in, uint8_t* dst, + int do_two) { + if (do_two) { + ITransform_Two_SSE2(ref, in, dst); + } else { + ITransform_One_SSE2(ref, in, dst); + } +} + +static void FTransformPass1_SSE2(const __m128i* const in01, + const __m128i* const in23, + __m128i* const out01, + __m128i* const out32) { + const __m128i k937 = _mm_set1_epi32(937); + const __m128i k1812 = _mm_set1_epi32(1812); + + const __m128i k88p = _mm_set_epi16(8, 8, 8, 8, 8, 8, 8, 8); + const __m128i k88m = _mm_set_epi16(-8, 8, -8, 8, -8, 8, -8, 8); + const __m128i k5352_2217p = _mm_set_epi16(2217, 5352, 2217, 5352, + 2217, 5352, 2217, 5352); + const __m128i k5352_2217m = _mm_set_epi16(-5352, 2217, -5352, 2217, + -5352, 2217, -5352, 2217); + + // *in01 = 00 01 10 11 02 03 12 13 + // *in23 = 20 21 30 31 22 23 32 33 + const __m128i shuf01_p = _mm_shufflehi_epi16(*in01, _MM_SHUFFLE(2, 3, 0, 1)); + const __m128i shuf23_p = _mm_shufflehi_epi16(*in23, _MM_SHUFFLE(2, 3, 0, 1)); + // 00 01 10 11 03 02 13 12 + // 20 21 30 31 23 22 33 32 + const __m128i s01 = _mm_unpacklo_epi64(shuf01_p, shuf23_p); + const __m128i s32 = _mm_unpackhi_epi64(shuf01_p, shuf23_p); + // 00 01 10 11 20 21 30 31 + // 03 02 13 12 23 22 33 32 + const __m128i a01 = _mm_add_epi16(s01, s32); + const __m128i a32 = _mm_sub_epi16(s01, s32); + // [d0 + d3 | d1 + d2 | ...] = [a0 a1 | a0' a1' | ... ] + // [d0 - d3 | d1 - d2 | ...] = [a3 a2 | a3' a2' | ... ] + + const __m128i tmp0 = _mm_madd_epi16(a01, k88p); // [ (a0 + a1) << 3, ... ] + const __m128i tmp2 = _mm_madd_epi16(a01, k88m); // [ (a0 - a1) << 3, ... ] + const __m128i tmp1_1 = _mm_madd_epi16(a32, k5352_2217p); + const __m128i tmp3_1 = _mm_madd_epi16(a32, k5352_2217m); + const __m128i tmp1_2 = _mm_add_epi32(tmp1_1, k1812); + const __m128i tmp3_2 = _mm_add_epi32(tmp3_1, k937); + const __m128i tmp1 = _mm_srai_epi32(tmp1_2, 9); + const __m128i tmp3 = _mm_srai_epi32(tmp3_2, 9); + const __m128i s03 = _mm_packs_epi32(tmp0, tmp2); + const __m128i s12 = _mm_packs_epi32(tmp1, tmp3); + const __m128i s_lo = _mm_unpacklo_epi16(s03, s12); // 0 1 0 1 0 1... + const __m128i s_hi = _mm_unpackhi_epi16(s03, s12); // 2 3 2 3 2 3 + const __m128i v23 = _mm_unpackhi_epi32(s_lo, s_hi); + *out01 = _mm_unpacklo_epi32(s_lo, s_hi); + *out32 = _mm_shuffle_epi32(v23, _MM_SHUFFLE(1, 0, 3, 2)); // 3 2 3 2 3 2.. +} + +static void FTransformPass2_SSE2(const __m128i* const v01, + const __m128i* const v32, + int16_t* out) { + const __m128i zero = _mm_setzero_si128(); + const __m128i seven = _mm_set1_epi16(7); + const __m128i k5352_2217 = _mm_set_epi16(5352, 2217, 5352, 2217, + 5352, 2217, 5352, 2217); + const __m128i k2217_5352 = _mm_set_epi16(2217, -5352, 2217, -5352, + 2217, -5352, 2217, -5352); + const __m128i k12000_plus_one = _mm_set1_epi32(12000 + (1 << 16)); + const __m128i k51000 = _mm_set1_epi32(51000); + + // Same operations are done on the (0,3) and (1,2) pairs. + // a3 = v0 - v3 + // a2 = v1 - v2 + const __m128i a32 = _mm_sub_epi16(*v01, *v32); + const __m128i a22 = _mm_unpackhi_epi64(a32, a32); + + const __m128i b23 = _mm_unpacklo_epi16(a22, a32); + const __m128i c1 = _mm_madd_epi16(b23, k5352_2217); + const __m128i c3 = _mm_madd_epi16(b23, k2217_5352); + const __m128i d1 = _mm_add_epi32(c1, k12000_plus_one); + const __m128i d3 = _mm_add_epi32(c3, k51000); + const __m128i e1 = _mm_srai_epi32(d1, 16); + const __m128i e3 = _mm_srai_epi32(d3, 16); + // f1 = ((b3 * 5352 + b2 * 2217 + 12000) >> 16) + // f3 = ((b3 * 2217 - b2 * 5352 + 51000) >> 16) + const __m128i f1 = _mm_packs_epi32(e1, e1); + const __m128i f3 = _mm_packs_epi32(e3, e3); + // g1 = f1 + (a3 != 0); + // The compare will return (0xffff, 0) for (==0, !=0). To turn that into the + // desired (0, 1), we add one earlier through k12000_plus_one. + // -> g1 = f1 + 1 - (a3 == 0) + const __m128i g1 = _mm_add_epi16(f1, _mm_cmpeq_epi16(a32, zero)); + + // a0 = v0 + v3 + // a1 = v1 + v2 + const __m128i a01 = _mm_add_epi16(*v01, *v32); + const __m128i a01_plus_7 = _mm_add_epi16(a01, seven); + const __m128i a11 = _mm_unpackhi_epi64(a01, a01); + const __m128i c0 = _mm_add_epi16(a01_plus_7, a11); + const __m128i c2 = _mm_sub_epi16(a01_plus_7, a11); + // d0 = (a0 + a1 + 7) >> 4; + // d2 = (a0 - a1 + 7) >> 4; + const __m128i d0 = _mm_srai_epi16(c0, 4); + const __m128i d2 = _mm_srai_epi16(c2, 4); + + const __m128i d0_g1 = _mm_unpacklo_epi64(d0, g1); + const __m128i d2_f3 = _mm_unpacklo_epi64(d2, f3); + _mm_storeu_si128((__m128i*)&out[0], d0_g1); + _mm_storeu_si128((__m128i*)&out[8], d2_f3); +} + +static void FTransform_SSE2(const uint8_t* src, const uint8_t* ref, + int16_t* out) { + const __m128i zero = _mm_setzero_si128(); + // Load src. + const __m128i src0 = _mm_loadl_epi64((const __m128i*)&src[0 * BPS]); + const __m128i src1 = _mm_loadl_epi64((const __m128i*)&src[1 * BPS]); + const __m128i src2 = _mm_loadl_epi64((const __m128i*)&src[2 * BPS]); + const __m128i src3 = _mm_loadl_epi64((const __m128i*)&src[3 * BPS]); + // 00 01 02 03 * + // 10 11 12 13 * + // 20 21 22 23 * + // 30 31 32 33 * + // Shuffle. + const __m128i src_0 = _mm_unpacklo_epi16(src0, src1); + const __m128i src_1 = _mm_unpacklo_epi16(src2, src3); + // 00 01 10 11 02 03 12 13 * * ... + // 20 21 30 31 22 22 32 33 * * ... + + // Load ref. + const __m128i ref0 = _mm_loadl_epi64((const __m128i*)&ref[0 * BPS]); + const __m128i ref1 = _mm_loadl_epi64((const __m128i*)&ref[1 * BPS]); + const __m128i ref2 = _mm_loadl_epi64((const __m128i*)&ref[2 * BPS]); + const __m128i ref3 = _mm_loadl_epi64((const __m128i*)&ref[3 * BPS]); + const __m128i ref_0 = _mm_unpacklo_epi16(ref0, ref1); + const __m128i ref_1 = _mm_unpacklo_epi16(ref2, ref3); + + // Convert both to 16 bit. + const __m128i src_0_16b = _mm_unpacklo_epi8(src_0, zero); + const __m128i src_1_16b = _mm_unpacklo_epi8(src_1, zero); + const __m128i ref_0_16b = _mm_unpacklo_epi8(ref_0, zero); + const __m128i ref_1_16b = _mm_unpacklo_epi8(ref_1, zero); + + // Compute the difference. + const __m128i row01 = _mm_sub_epi16(src_0_16b, ref_0_16b); + const __m128i row23 = _mm_sub_epi16(src_1_16b, ref_1_16b); + __m128i v01, v32; + + // First pass + FTransformPass1_SSE2(&row01, &row23, &v01, &v32); + + // Second pass + FTransformPass2_SSE2(&v01, &v32, out); +} + +static void FTransform2_SSE2(const uint8_t* src, const uint8_t* ref, + int16_t* out) { + const __m128i zero = _mm_setzero_si128(); + + // Load src and convert to 16b. + const __m128i src0 = _mm_loadl_epi64((const __m128i*)&src[0 * BPS]); + const __m128i src1 = _mm_loadl_epi64((const __m128i*)&src[1 * BPS]); + const __m128i src2 = _mm_loadl_epi64((const __m128i*)&src[2 * BPS]); + const __m128i src3 = _mm_loadl_epi64((const __m128i*)&src[3 * BPS]); + const __m128i src_0 = _mm_unpacklo_epi8(src0, zero); + const __m128i src_1 = _mm_unpacklo_epi8(src1, zero); + const __m128i src_2 = _mm_unpacklo_epi8(src2, zero); + const __m128i src_3 = _mm_unpacklo_epi8(src3, zero); + // Load ref and convert to 16b. + const __m128i ref0 = _mm_loadl_epi64((const __m128i*)&ref[0 * BPS]); + const __m128i ref1 = _mm_loadl_epi64((const __m128i*)&ref[1 * BPS]); + const __m128i ref2 = _mm_loadl_epi64((const __m128i*)&ref[2 * BPS]); + const __m128i ref3 = _mm_loadl_epi64((const __m128i*)&ref[3 * BPS]); + const __m128i ref_0 = _mm_unpacklo_epi8(ref0, zero); + const __m128i ref_1 = _mm_unpacklo_epi8(ref1, zero); + const __m128i ref_2 = _mm_unpacklo_epi8(ref2, zero); + const __m128i ref_3 = _mm_unpacklo_epi8(ref3, zero); + // Compute difference. -> 00 01 02 03 00' 01' 02' 03' + const __m128i diff0 = _mm_sub_epi16(src_0, ref_0); + const __m128i diff1 = _mm_sub_epi16(src_1, ref_1); + const __m128i diff2 = _mm_sub_epi16(src_2, ref_2); + const __m128i diff3 = _mm_sub_epi16(src_3, ref_3); + + // Unpack and shuffle + // 00 01 02 03 0 0 0 0 + // 10 11 12 13 0 0 0 0 + // 20 21 22 23 0 0 0 0 + // 30 31 32 33 0 0 0 0 + const __m128i shuf01l = _mm_unpacklo_epi32(diff0, diff1); + const __m128i shuf23l = _mm_unpacklo_epi32(diff2, diff3); + const __m128i shuf01h = _mm_unpackhi_epi32(diff0, diff1); + const __m128i shuf23h = _mm_unpackhi_epi32(diff2, diff3); + __m128i v01l, v32l; + __m128i v01h, v32h; + + // First pass + FTransformPass1_SSE2(&shuf01l, &shuf23l, &v01l, &v32l); + FTransformPass1_SSE2(&shuf01h, &shuf23h, &v01h, &v32h); + + // Second pass + FTransformPass2_SSE2(&v01l, &v32l, out + 0); + FTransformPass2_SSE2(&v01h, &v32h, out + 16); +} + +static void FTransformWHTRow_SSE2(const int16_t* const in, __m128i* const out) { + const __m128i kMult = _mm_set_epi16(-1, 1, -1, 1, 1, 1, 1, 1); + const __m128i src0 = _mm_loadl_epi64((__m128i*)&in[0 * 16]); + const __m128i src1 = _mm_loadl_epi64((__m128i*)&in[1 * 16]); + const __m128i src2 = _mm_loadl_epi64((__m128i*)&in[2 * 16]); + const __m128i src3 = _mm_loadl_epi64((__m128i*)&in[3 * 16]); + const __m128i A01 = _mm_unpacklo_epi16(src0, src1); // A0 A1 | ... + const __m128i A23 = _mm_unpacklo_epi16(src2, src3); // A2 A3 | ... + const __m128i B0 = _mm_adds_epi16(A01, A23); // a0 | a1 | ... + const __m128i B1 = _mm_subs_epi16(A01, A23); // a3 | a2 | ... + const __m128i C0 = _mm_unpacklo_epi32(B0, B1); // a0 | a1 | a3 | a2 | ... + const __m128i C1 = _mm_unpacklo_epi32(B1, B0); // a3 | a2 | a0 | a1 | ... + const __m128i D = _mm_unpacklo_epi64(C0, C1); // a0 a1 a3 a2 a3 a2 a0 a1 + *out = _mm_madd_epi16(D, kMult); +} + +static void FTransformWHT_SSE2(const int16_t* in, int16_t* out) { + // Input is 12b signed. + __m128i row0, row1, row2, row3; + // Rows are 14b signed. + FTransformWHTRow_SSE2(in + 0 * 64, &row0); + FTransformWHTRow_SSE2(in + 1 * 64, &row1); + FTransformWHTRow_SSE2(in + 2 * 64, &row2); + FTransformWHTRow_SSE2(in + 3 * 64, &row3); + + { + // The a* are 15b signed. + const __m128i a0 = _mm_add_epi32(row0, row2); + const __m128i a1 = _mm_add_epi32(row1, row3); + const __m128i a2 = _mm_sub_epi32(row1, row3); + const __m128i a3 = _mm_sub_epi32(row0, row2); + const __m128i a0a3 = _mm_packs_epi32(a0, a3); + const __m128i a1a2 = _mm_packs_epi32(a1, a2); + + // The b* are 16b signed. + const __m128i b0b1 = _mm_add_epi16(a0a3, a1a2); + const __m128i b3b2 = _mm_sub_epi16(a0a3, a1a2); + const __m128i tmp_b2b3 = _mm_unpackhi_epi64(b3b2, b3b2); + const __m128i b2b3 = _mm_unpacklo_epi64(tmp_b2b3, b3b2); + + _mm_storeu_si128((__m128i*)&out[0], _mm_srai_epi16(b0b1, 1)); + _mm_storeu_si128((__m128i*)&out[8], _mm_srai_epi16(b2b3, 1)); + } +} + +//------------------------------------------------------------------------------ +// Compute susceptibility based on DCT-coeff histograms: +// the higher, the "easier" the macroblock is to compress. + +static void CollectHistogram_SSE2(const uint8_t* ref, const uint8_t* pred, + int start_block, int end_block, + VP8Histogram* const histo) { + const __m128i zero = _mm_setzero_si128(); + const __m128i max_coeff_thresh = _mm_set1_epi16(MAX_COEFF_THRESH); + int j; + int distribution[MAX_COEFF_THRESH + 1] = { 0 }; + for (j = start_block; j < end_block; ++j) { + int16_t out[16]; + int k; + + FTransform_SSE2(ref + VP8DspScan[j], pred + VP8DspScan[j], out); + + // Convert coefficients to bin (within out[]). + { + // Load. + const __m128i out0 = _mm_loadu_si128((__m128i*)&out[0]); + const __m128i out1 = _mm_loadu_si128((__m128i*)&out[8]); + const __m128i d0 = _mm_sub_epi16(zero, out0); + const __m128i d1 = _mm_sub_epi16(zero, out1); + const __m128i abs0 = _mm_max_epi16(out0, d0); // abs(v), 16b + const __m128i abs1 = _mm_max_epi16(out1, d1); + // v = abs(out) >> 3 + const __m128i v0 = _mm_srai_epi16(abs0, 3); + const __m128i v1 = _mm_srai_epi16(abs1, 3); + // bin = min(v, MAX_COEFF_THRESH) + const __m128i bin0 = _mm_min_epi16(v0, max_coeff_thresh); + const __m128i bin1 = _mm_min_epi16(v1, max_coeff_thresh); + // Store. + _mm_storeu_si128((__m128i*)&out[0], bin0); + _mm_storeu_si128((__m128i*)&out[8], bin1); + } + + // Convert coefficients to bin. + for (k = 0; k < 16; ++k) { + ++distribution[out[k]]; + } + } + VP8SetHistogramData(distribution, histo); +} + +//------------------------------------------------------------------------------ +// Intra predictions + +// helper for chroma-DC predictions +static WEBP_INLINE void Put8x8uv_SSE2(uint8_t v, uint8_t* dst) { + int j; + const __m128i values = _mm_set1_epi8((char)v); + for (j = 0; j < 8; ++j) { + _mm_storel_epi64((__m128i*)(dst + j * BPS), values); + } +} + +static WEBP_INLINE void Put16_SSE2(uint8_t v, uint8_t* dst) { + int j; + const __m128i values = _mm_set1_epi8((char)v); + for (j = 0; j < 16; ++j) { + _mm_store_si128((__m128i*)(dst + j * BPS), values); + } +} + +static WEBP_INLINE void Fill_SSE2(uint8_t* dst, int value, int size) { + if (size == 4) { + int j; + for (j = 0; j < 4; ++j) { + memset(dst + j * BPS, value, 4); + } + } else if (size == 8) { + Put8x8uv_SSE2(value, dst); + } else { + Put16_SSE2(value, dst); + } +} + +static WEBP_INLINE void VE8uv_SSE2(uint8_t* dst, const uint8_t* top) { + int j; + const __m128i top_values = _mm_loadl_epi64((const __m128i*)top); + for (j = 0; j < 8; ++j) { + _mm_storel_epi64((__m128i*)(dst + j * BPS), top_values); + } +} + +static WEBP_INLINE void VE16_SSE2(uint8_t* dst, const uint8_t* top) { + const __m128i top_values = _mm_load_si128((const __m128i*)top); + int j; + for (j = 0; j < 16; ++j) { + _mm_store_si128((__m128i*)(dst + j * BPS), top_values); + } +} + +static WEBP_INLINE void VerticalPred_SSE2(uint8_t* dst, + const uint8_t* top, int size) { + if (top != NULL) { + if (size == 8) { + VE8uv_SSE2(dst, top); + } else { + VE16_SSE2(dst, top); + } + } else { + Fill_SSE2(dst, 127, size); + } +} + +static WEBP_INLINE void HE8uv_SSE2(uint8_t* dst, const uint8_t* left) { + int j; + for (j = 0; j < 8; ++j) { + const __m128i values = _mm_set1_epi8((char)left[j]); + _mm_storel_epi64((__m128i*)dst, values); + dst += BPS; + } +} + +static WEBP_INLINE void HE16_SSE2(uint8_t* dst, const uint8_t* left) { + int j; + for (j = 0; j < 16; ++j) { + const __m128i values = _mm_set1_epi8((char)left[j]); + _mm_store_si128((__m128i*)dst, values); + dst += BPS; + } +} + +static WEBP_INLINE void HorizontalPred_SSE2(uint8_t* dst, + const uint8_t* left, int size) { + if (left != NULL) { + if (size == 8) { + HE8uv_SSE2(dst, left); + } else { + HE16_SSE2(dst, left); + } + } else { + Fill_SSE2(dst, 129, size); + } +} + +static WEBP_INLINE void TM_SSE2(uint8_t* dst, const uint8_t* left, + const uint8_t* top, int size) { + const __m128i zero = _mm_setzero_si128(); + int y; + if (size == 8) { + const __m128i top_values = _mm_loadl_epi64((const __m128i*)top); + const __m128i top_base = _mm_unpacklo_epi8(top_values, zero); + for (y = 0; y < 8; ++y, dst += BPS) { + const int val = left[y] - left[-1]; + const __m128i base = _mm_set1_epi16(val); + const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero); + _mm_storel_epi64((__m128i*)dst, out); + } + } else { + const __m128i top_values = _mm_load_si128((const __m128i*)top); + const __m128i top_base_0 = _mm_unpacklo_epi8(top_values, zero); + const __m128i top_base_1 = _mm_unpackhi_epi8(top_values, zero); + for (y = 0; y < 16; ++y, dst += BPS) { + const int val = left[y] - left[-1]; + const __m128i base = _mm_set1_epi16(val); + const __m128i out_0 = _mm_add_epi16(base, top_base_0); + const __m128i out_1 = _mm_add_epi16(base, top_base_1); + const __m128i out = _mm_packus_epi16(out_0, out_1); + _mm_store_si128((__m128i*)dst, out); + } + } +} + +static WEBP_INLINE void TrueMotion_SSE2(uint8_t* dst, const uint8_t* left, + const uint8_t* top, int size) { + if (left != NULL) { + if (top != NULL) { + TM_SSE2(dst, left, top, size); + } else { + HorizontalPred_SSE2(dst, left, size); + } + } else { + // true motion without left samples (hence: with default 129 value) + // is equivalent to VE prediction where you just copy the top samples. + // Note that if top samples are not available, the default value is + // then 129, and not 127 as in the VerticalPred case. + if (top != NULL) { + VerticalPred_SSE2(dst, top, size); + } else { + Fill_SSE2(dst, 129, size); + } + } +} + +static WEBP_INLINE void DC8uv_SSE2(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { + const __m128i top_values = _mm_loadl_epi64((const __m128i*)top); + const __m128i left_values = _mm_loadl_epi64((const __m128i*)left); + const __m128i combined = _mm_unpacklo_epi64(top_values, left_values); + const int DC = VP8HorizontalAdd8b(&combined) + 8; + Put8x8uv_SSE2(DC >> 4, dst); +} + +static WEBP_INLINE void DC8uvNoLeft_SSE2(uint8_t* dst, const uint8_t* top) { + const __m128i zero = _mm_setzero_si128(); + const __m128i top_values = _mm_loadl_epi64((const __m128i*)top); + const __m128i sum = _mm_sad_epu8(top_values, zero); + const int DC = _mm_cvtsi128_si32(sum) + 4; + Put8x8uv_SSE2(DC >> 3, dst); +} + +static WEBP_INLINE void DC8uvNoTop_SSE2(uint8_t* dst, const uint8_t* left) { + // 'left' is contiguous so we can reuse the top summation. + DC8uvNoLeft_SSE2(dst, left); +} + +static WEBP_INLINE void DC8uvNoTopLeft_SSE2(uint8_t* dst) { + Put8x8uv_SSE2(0x80, dst); +} + +static WEBP_INLINE void DC8uvMode_SSE2(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { + if (top != NULL) { + if (left != NULL) { // top and left present + DC8uv_SSE2(dst, left, top); + } else { // top, but no left + DC8uvNoLeft_SSE2(dst, top); + } + } else if (left != NULL) { // left but no top + DC8uvNoTop_SSE2(dst, left); + } else { // no top, no left, nothing. + DC8uvNoTopLeft_SSE2(dst); + } +} + +static WEBP_INLINE void DC16_SSE2(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { + const __m128i top_row = _mm_load_si128((const __m128i*)top); + const __m128i left_row = _mm_load_si128((const __m128i*)left); + const int DC = + VP8HorizontalAdd8b(&top_row) + VP8HorizontalAdd8b(&left_row) + 16; + Put16_SSE2(DC >> 5, dst); +} + +static WEBP_INLINE void DC16NoLeft_SSE2(uint8_t* dst, const uint8_t* top) { + const __m128i top_row = _mm_load_si128((const __m128i*)top); + const int DC = VP8HorizontalAdd8b(&top_row) + 8; + Put16_SSE2(DC >> 4, dst); +} + +static WEBP_INLINE void DC16NoTop_SSE2(uint8_t* dst, const uint8_t* left) { + // 'left' is contiguous so we can reuse the top summation. + DC16NoLeft_SSE2(dst, left); +} + +static WEBP_INLINE void DC16NoTopLeft_SSE2(uint8_t* dst) { + Put16_SSE2(0x80, dst); +} + +static WEBP_INLINE void DC16Mode_SSE2(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { + if (top != NULL) { + if (left != NULL) { // top and left present + DC16_SSE2(dst, left, top); + } else { // top, but no left + DC16NoLeft_SSE2(dst, top); + } + } else if (left != NULL) { // left but no top + DC16NoTop_SSE2(dst, left); + } else { // no top, no left, nothing. + DC16NoTopLeft_SSE2(dst); + } +} + +//------------------------------------------------------------------------------ +// 4x4 predictions + +#define DST(x, y) dst[(x) + (y) * BPS] +#define AVG3(a, b, c) (((a) + 2 * (b) + (c) + 2) >> 2) +#define AVG2(a, b) (((a) + (b) + 1) >> 1) + +// We use the following 8b-arithmetic tricks: +// (a + 2 * b + c + 2) >> 2 = (AC + b + 1) >> 1 +// where: AC = (a + c) >> 1 = [(a + c + 1) >> 1] - [(a^c) & 1] +// and: +// (a + 2 * b + c + 2) >> 2 = (AB + BC + 1) >> 1 - (ab|bc)&lsb +// where: AC = (a + b + 1) >> 1, BC = (b + c + 1) >> 1 +// and ab = a ^ b, bc = b ^ c, lsb = (AC^BC)&1 + +static WEBP_INLINE void VE4_SSE2(uint8_t* dst, + const uint8_t* top) { // vertical + const __m128i one = _mm_set1_epi8(1); + const __m128i ABCDEFGH = _mm_loadl_epi64((__m128i*)(top - 1)); + const __m128i BCDEFGH0 = _mm_srli_si128(ABCDEFGH, 1); + const __m128i CDEFGH00 = _mm_srli_si128(ABCDEFGH, 2); + const __m128i a = _mm_avg_epu8(ABCDEFGH, CDEFGH00); + const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGH00), one); + const __m128i b = _mm_subs_epu8(a, lsb); + const __m128i avg = _mm_avg_epu8(b, BCDEFGH0); + const int vals = _mm_cvtsi128_si32(avg); + int i; + for (i = 0; i < 4; ++i) { + WebPInt32ToMem(dst + i * BPS, vals); + } +} + +static WEBP_INLINE void HE4_SSE2(uint8_t* dst, + const uint8_t* top) { // horizontal + const int X = top[-1]; + const int I = top[-2]; + const int J = top[-3]; + const int K = top[-4]; + const int L = top[-5]; + WebPUint32ToMem(dst + 0 * BPS, 0x01010101U * AVG3(X, I, J)); + WebPUint32ToMem(dst + 1 * BPS, 0x01010101U * AVG3(I, J, K)); + WebPUint32ToMem(dst + 2 * BPS, 0x01010101U * AVG3(J, K, L)); + WebPUint32ToMem(dst + 3 * BPS, 0x01010101U * AVG3(K, L, L)); +} + +static WEBP_INLINE void DC4_SSE2(uint8_t* dst, const uint8_t* top) { + uint32_t dc = 4; + int i; + for (i = 0; i < 4; ++i) dc += top[i] + top[-5 + i]; + Fill_SSE2(dst, dc >> 3, 4); +} + +static WEBP_INLINE void LD4_SSE2(uint8_t* dst, + const uint8_t* top) { // Down-Left + const __m128i one = _mm_set1_epi8(1); + const __m128i ABCDEFGH = _mm_loadl_epi64((const __m128i*)top); + const __m128i BCDEFGH0 = _mm_srli_si128(ABCDEFGH, 1); + const __m128i CDEFGH00 = _mm_srli_si128(ABCDEFGH, 2); + const __m128i CDEFGHH0 = _mm_insert_epi16(CDEFGH00, top[7], 3); + const __m128i avg1 = _mm_avg_epu8(ABCDEFGH, CDEFGHH0); + const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGHH0), one); + const __m128i avg2 = _mm_subs_epu8(avg1, lsb); + const __m128i abcdefg = _mm_avg_epu8(avg2, BCDEFGH0); + WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcdefg )); + WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1))); + WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2))); + WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3))); +} + +static WEBP_INLINE void VR4_SSE2(uint8_t* dst, + const uint8_t* top) { // Vertical-Right + const __m128i one = _mm_set1_epi8(1); + const int I = top[-2]; + const int J = top[-3]; + const int K = top[-4]; + const int X = top[-1]; + const __m128i XABCD = _mm_loadl_epi64((const __m128i*)(top - 1)); + const __m128i ABCD0 = _mm_srli_si128(XABCD, 1); + const __m128i abcd = _mm_avg_epu8(XABCD, ABCD0); + const __m128i _XABCD = _mm_slli_si128(XABCD, 1); + const __m128i IXABCD = _mm_insert_epi16(_XABCD, (short)(I | (X << 8)), 0); + const __m128i avg1 = _mm_avg_epu8(IXABCD, ABCD0); + const __m128i lsb = _mm_and_si128(_mm_xor_si128(IXABCD, ABCD0), one); + const __m128i avg2 = _mm_subs_epu8(avg1, lsb); + const __m128i efgh = _mm_avg_epu8(avg2, XABCD); + WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcd )); + WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( efgh )); + WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(abcd, 1))); + WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(efgh, 1))); + + // these two are hard to implement in SSE2, so we keep the C-version: + DST(0, 2) = AVG3(J, I, X); + DST(0, 3) = AVG3(K, J, I); +} + +static WEBP_INLINE void VL4_SSE2(uint8_t* dst, + const uint8_t* top) { // Vertical-Left + const __m128i one = _mm_set1_epi8(1); + const __m128i ABCDEFGH = _mm_loadl_epi64((const __m128i*)top); + const __m128i BCDEFGH_ = _mm_srli_si128(ABCDEFGH, 1); + const __m128i CDEFGH__ = _mm_srli_si128(ABCDEFGH, 2); + const __m128i avg1 = _mm_avg_epu8(ABCDEFGH, BCDEFGH_); + const __m128i avg2 = _mm_avg_epu8(CDEFGH__, BCDEFGH_); + const __m128i avg3 = _mm_avg_epu8(avg1, avg2); + const __m128i lsb1 = _mm_and_si128(_mm_xor_si128(avg1, avg2), one); + const __m128i ab = _mm_xor_si128(ABCDEFGH, BCDEFGH_); + const __m128i bc = _mm_xor_si128(CDEFGH__, BCDEFGH_); + const __m128i abbc = _mm_or_si128(ab, bc); + const __m128i lsb2 = _mm_and_si128(abbc, lsb1); + const __m128i avg4 = _mm_subs_epu8(avg3, lsb2); + const uint32_t extra_out = + (uint32_t)_mm_cvtsi128_si32(_mm_srli_si128(avg4, 4)); + WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( avg1 )); + WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( avg4 )); + WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg1, 1))); + WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg4, 1))); + + // these two are hard to get and irregular + DST(3, 2) = (extra_out >> 0) & 0xff; + DST(3, 3) = (extra_out >> 8) & 0xff; +} + +static WEBP_INLINE void RD4_SSE2(uint8_t* dst, + const uint8_t* top) { // Down-right + const __m128i one = _mm_set1_epi8(1); + const __m128i LKJIXABC = _mm_loadl_epi64((const __m128i*)(top - 5)); + const __m128i LKJIXABCD = _mm_insert_epi16(LKJIXABC, top[3], 4); + const __m128i KJIXABCD_ = _mm_srli_si128(LKJIXABCD, 1); + const __m128i JIXABCD__ = _mm_srli_si128(LKJIXABCD, 2); + const __m128i avg1 = _mm_avg_epu8(JIXABCD__, LKJIXABCD); + const __m128i lsb = _mm_and_si128(_mm_xor_si128(JIXABCD__, LKJIXABCD), one); + const __m128i avg2 = _mm_subs_epu8(avg1, lsb); + const __m128i abcdefg = _mm_avg_epu8(avg2, KJIXABCD_); + WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32( abcdefg )); + WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1))); + WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2))); + WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3))); +} + +static WEBP_INLINE void HU4_SSE2(uint8_t* dst, const uint8_t* top) { + const int I = top[-2]; + const int J = top[-3]; + const int K = top[-4]; + const int L = top[-5]; + DST(0, 0) = AVG2(I, J); + DST(2, 0) = DST(0, 1) = AVG2(J, K); + DST(2, 1) = DST(0, 2) = AVG2(K, L); + DST(1, 0) = AVG3(I, J, K); + DST(3, 0) = DST(1, 1) = AVG3(J, K, L); + DST(3, 1) = DST(1, 2) = AVG3(K, L, L); + DST(3, 2) = DST(2, 2) = + DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L; +} + +static WEBP_INLINE void HD4_SSE2(uint8_t* dst, const uint8_t* top) { + const int X = top[-1]; + const int I = top[-2]; + const int J = top[-3]; + const int K = top[-4]; + const int L = top[-5]; + const int A = top[0]; + const int B = top[1]; + const int C = top[2]; + + DST(0, 0) = DST(2, 1) = AVG2(I, X); + DST(0, 1) = DST(2, 2) = AVG2(J, I); + DST(0, 2) = DST(2, 3) = AVG2(K, J); + DST(0, 3) = AVG2(L, K); + + DST(3, 0) = AVG3(A, B, C); + DST(2, 0) = AVG3(X, A, B); + DST(1, 0) = DST(3, 1) = AVG3(I, X, A); + DST(1, 1) = DST(3, 2) = AVG3(J, I, X); + DST(1, 2) = DST(3, 3) = AVG3(K, J, I); + DST(1, 3) = AVG3(L, K, J); +} + +static WEBP_INLINE void TM4_SSE2(uint8_t* dst, const uint8_t* top) { + const __m128i zero = _mm_setzero_si128(); + const __m128i top_values = _mm_cvtsi32_si128(WebPMemToInt32(top)); + const __m128i top_base = _mm_unpacklo_epi8(top_values, zero); + int y; + for (y = 0; y < 4; ++y, dst += BPS) { + const int val = top[-2 - y] - top[-1]; + const __m128i base = _mm_set1_epi16(val); + const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero); + WebPInt32ToMem(dst, _mm_cvtsi128_si32(out)); + } +} + +#undef DST +#undef AVG3 +#undef AVG2 + +//------------------------------------------------------------------------------ +// luma 4x4 prediction + +// Left samples are top[-5 .. -2], top_left is top[-1], top are +// located at top[0..3], and top right is top[4..7] +static void Intra4Preds_SSE2(uint8_t* dst, const uint8_t* top) { + DC4_SSE2(I4DC4 + dst, top); + TM4_SSE2(I4TM4 + dst, top); + VE4_SSE2(I4VE4 + dst, top); + HE4_SSE2(I4HE4 + dst, top); + RD4_SSE2(I4RD4 + dst, top); + VR4_SSE2(I4VR4 + dst, top); + LD4_SSE2(I4LD4 + dst, top); + VL4_SSE2(I4VL4 + dst, top); + HD4_SSE2(I4HD4 + dst, top); + HU4_SSE2(I4HU4 + dst, top); +} + +//------------------------------------------------------------------------------ +// Chroma 8x8 prediction (paragraph 12.2) + +static void IntraChromaPreds_SSE2(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { + // U block + DC8uvMode_SSE2(C8DC8 + dst, left, top); + VerticalPred_SSE2(C8VE8 + dst, top, 8); + HorizontalPred_SSE2(C8HE8 + dst, left, 8); + TrueMotion_SSE2(C8TM8 + dst, left, top, 8); + // V block + dst += 8; + if (top != NULL) top += 8; + if (left != NULL) left += 16; + DC8uvMode_SSE2(C8DC8 + dst, left, top); + VerticalPred_SSE2(C8VE8 + dst, top, 8); + HorizontalPred_SSE2(C8HE8 + dst, left, 8); + TrueMotion_SSE2(C8TM8 + dst, left, top, 8); +} + +//------------------------------------------------------------------------------ +// luma 16x16 prediction (paragraph 12.3) + +static void Intra16Preds_SSE2(uint8_t* dst, + const uint8_t* left, const uint8_t* top) { + DC16Mode_SSE2(I16DC16 + dst, left, top); + VerticalPred_SSE2(I16VE16 + dst, top, 16); + HorizontalPred_SSE2(I16HE16 + dst, left, 16); + TrueMotion_SSE2(I16TM16 + dst, left, top, 16); +} + +//------------------------------------------------------------------------------ +// Metric + +static WEBP_INLINE void SubtractAndAccumulate_SSE2(const __m128i a, + const __m128i b, + __m128i* const sum) { + // take abs(a-b) in 8b + const __m128i a_b = _mm_subs_epu8(a, b); + const __m128i b_a = _mm_subs_epu8(b, a); + const __m128i abs_a_b = _mm_or_si128(a_b, b_a); + // zero-extend to 16b + const __m128i zero = _mm_setzero_si128(); + const __m128i C0 = _mm_unpacklo_epi8(abs_a_b, zero); + const __m128i C1 = _mm_unpackhi_epi8(abs_a_b, zero); + // multiply with self + const __m128i sum1 = _mm_madd_epi16(C0, C0); + const __m128i sum2 = _mm_madd_epi16(C1, C1); + *sum = _mm_add_epi32(sum1, sum2); +} + +static WEBP_INLINE int SSE_16xN_SSE2(const uint8_t* a, const uint8_t* b, + int num_pairs) { + __m128i sum = _mm_setzero_si128(); + int32_t tmp[4]; + int i; + + for (i = 0; i < num_pairs; ++i) { + const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[BPS * 0]); + const __m128i b0 = _mm_loadu_si128((const __m128i*)&b[BPS * 0]); + const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[BPS * 1]); + const __m128i b1 = _mm_loadu_si128((const __m128i*)&b[BPS * 1]); + __m128i sum1, sum2; + SubtractAndAccumulate_SSE2(a0, b0, &sum1); + SubtractAndAccumulate_SSE2(a1, b1, &sum2); + sum = _mm_add_epi32(sum, _mm_add_epi32(sum1, sum2)); + a += 2 * BPS; + b += 2 * BPS; + } + _mm_storeu_si128((__m128i*)tmp, sum); + return (tmp[3] + tmp[2] + tmp[1] + tmp[0]); +} + +static int SSE16x16_SSE2(const uint8_t* a, const uint8_t* b) { + return SSE_16xN_SSE2(a, b, 8); +} + +static int SSE16x8_SSE2(const uint8_t* a, const uint8_t* b) { + return SSE_16xN_SSE2(a, b, 4); +} + +#define LOAD_8x16b(ptr) \ + _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i*)(ptr)), zero) + +static int SSE8x8_SSE2(const uint8_t* a, const uint8_t* b) { + const __m128i zero = _mm_setzero_si128(); + int num_pairs = 4; + __m128i sum = zero; + int32_t tmp[4]; + while (num_pairs-- > 0) { + const __m128i a0 = LOAD_8x16b(&a[BPS * 0]); + const __m128i a1 = LOAD_8x16b(&a[BPS * 1]); + const __m128i b0 = LOAD_8x16b(&b[BPS * 0]); + const __m128i b1 = LOAD_8x16b(&b[BPS * 1]); + // subtract + const __m128i c0 = _mm_subs_epi16(a0, b0); + const __m128i c1 = _mm_subs_epi16(a1, b1); + // multiply/accumulate with self + const __m128i d0 = _mm_madd_epi16(c0, c0); + const __m128i d1 = _mm_madd_epi16(c1, c1); + // collect + const __m128i sum01 = _mm_add_epi32(d0, d1); + sum = _mm_add_epi32(sum, sum01); + a += 2 * BPS; + b += 2 * BPS; + } + _mm_storeu_si128((__m128i*)tmp, sum); + return (tmp[3] + tmp[2] + tmp[1] + tmp[0]); +} +#undef LOAD_8x16b + +static int SSE4x4_SSE2(const uint8_t* a, const uint8_t* b) { + const __m128i zero = _mm_setzero_si128(); + + // Load values. Note that we read 8 pixels instead of 4, + // but the a/b buffers are over-allocated to that effect. + const __m128i a0 = _mm_loadl_epi64((const __m128i*)&a[BPS * 0]); + const __m128i a1 = _mm_loadl_epi64((const __m128i*)&a[BPS * 1]); + const __m128i a2 = _mm_loadl_epi64((const __m128i*)&a[BPS * 2]); + const __m128i a3 = _mm_loadl_epi64((const __m128i*)&a[BPS * 3]); + const __m128i b0 = _mm_loadl_epi64((const __m128i*)&b[BPS * 0]); + const __m128i b1 = _mm_loadl_epi64((const __m128i*)&b[BPS * 1]); + const __m128i b2 = _mm_loadl_epi64((const __m128i*)&b[BPS * 2]); + const __m128i b3 = _mm_loadl_epi64((const __m128i*)&b[BPS * 3]); + // Combine pair of lines. + const __m128i a01 = _mm_unpacklo_epi32(a0, a1); + const __m128i a23 = _mm_unpacklo_epi32(a2, a3); + const __m128i b01 = _mm_unpacklo_epi32(b0, b1); + const __m128i b23 = _mm_unpacklo_epi32(b2, b3); + // Convert to 16b. + const __m128i a01s = _mm_unpacklo_epi8(a01, zero); + const __m128i a23s = _mm_unpacklo_epi8(a23, zero); + const __m128i b01s = _mm_unpacklo_epi8(b01, zero); + const __m128i b23s = _mm_unpacklo_epi8(b23, zero); + // subtract, square and accumulate + const __m128i d0 = _mm_subs_epi16(a01s, b01s); + const __m128i d1 = _mm_subs_epi16(a23s, b23s); + const __m128i e0 = _mm_madd_epi16(d0, d0); + const __m128i e1 = _mm_madd_epi16(d1, d1); + const __m128i sum = _mm_add_epi32(e0, e1); + + int32_t tmp[4]; + _mm_storeu_si128((__m128i*)tmp, sum); + return (tmp[3] + tmp[2] + tmp[1] + tmp[0]); +} + +//------------------------------------------------------------------------------ + +static void Mean16x4_SSE2(const uint8_t* ref, uint32_t dc[4]) { + const __m128i mask = _mm_set1_epi16(0x00ff); + const __m128i a0 = _mm_loadu_si128((const __m128i*)&ref[BPS * 0]); + const __m128i a1 = _mm_loadu_si128((const __m128i*)&ref[BPS * 1]); + const __m128i a2 = _mm_loadu_si128((const __m128i*)&ref[BPS * 2]); + const __m128i a3 = _mm_loadu_si128((const __m128i*)&ref[BPS * 3]); + const __m128i b0 = _mm_srli_epi16(a0, 8); // hi byte + const __m128i b1 = _mm_srli_epi16(a1, 8); + const __m128i b2 = _mm_srli_epi16(a2, 8); + const __m128i b3 = _mm_srli_epi16(a3, 8); + const __m128i c0 = _mm_and_si128(a0, mask); // lo byte + const __m128i c1 = _mm_and_si128(a1, mask); + const __m128i c2 = _mm_and_si128(a2, mask); + const __m128i c3 = _mm_and_si128(a3, mask); + const __m128i d0 = _mm_add_epi32(b0, c0); + const __m128i d1 = _mm_add_epi32(b1, c1); + const __m128i d2 = _mm_add_epi32(b2, c2); + const __m128i d3 = _mm_add_epi32(b3, c3); + const __m128i e0 = _mm_add_epi32(d0, d1); + const __m128i e1 = _mm_add_epi32(d2, d3); + const __m128i f0 = _mm_add_epi32(e0, e1); + uint16_t tmp[8]; + _mm_storeu_si128((__m128i*)tmp, f0); + dc[0] = tmp[0] + tmp[1]; + dc[1] = tmp[2] + tmp[3]; + dc[2] = tmp[4] + tmp[5]; + dc[3] = tmp[6] + tmp[7]; +} + +//------------------------------------------------------------------------------ +// Texture distortion +// +// We try to match the spectral content (weighted) between source and +// reconstructed samples. + +// Hadamard transform +// Returns the weighted sum of the absolute value of transformed coefficients. +// w[] contains a row-major 4 by 4 symmetric matrix. +static int TTransform_SSE2(const uint8_t* inA, const uint8_t* inB, + const uint16_t* const w) { + int32_t sum[4]; + __m128i tmp_0, tmp_1, tmp_2, tmp_3; + const __m128i zero = _mm_setzero_si128(); + + // Load and combine inputs. + { + const __m128i inA_0 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 0]); + const __m128i inA_1 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 1]); + const __m128i inA_2 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 2]); + const __m128i inA_3 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 3]); + const __m128i inB_0 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 0]); + const __m128i inB_1 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 1]); + const __m128i inB_2 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 2]); + const __m128i inB_3 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 3]); + + // Combine inA and inB (we'll do two transforms in parallel). + const __m128i inAB_0 = _mm_unpacklo_epi32(inA_0, inB_0); + const __m128i inAB_1 = _mm_unpacklo_epi32(inA_1, inB_1); + const __m128i inAB_2 = _mm_unpacklo_epi32(inA_2, inB_2); + const __m128i inAB_3 = _mm_unpacklo_epi32(inA_3, inB_3); + tmp_0 = _mm_unpacklo_epi8(inAB_0, zero); + tmp_1 = _mm_unpacklo_epi8(inAB_1, zero); + tmp_2 = _mm_unpacklo_epi8(inAB_2, zero); + tmp_3 = _mm_unpacklo_epi8(inAB_3, zero); + // a00 a01 a02 a03 b00 b01 b02 b03 + // a10 a11 a12 a13 b10 b11 b12 b13 + // a20 a21 a22 a23 b20 b21 b22 b23 + // a30 a31 a32 a33 b30 b31 b32 b33 + } + + // Vertical pass first to avoid a transpose (vertical and horizontal passes + // are commutative because w/kWeightY is symmetric) and subsequent transpose. + { + // Calculate a and b (two 4x4 at once). + const __m128i a0 = _mm_add_epi16(tmp_0, tmp_2); + const __m128i a1 = _mm_add_epi16(tmp_1, tmp_3); + const __m128i a2 = _mm_sub_epi16(tmp_1, tmp_3); + const __m128i a3 = _mm_sub_epi16(tmp_0, tmp_2); + const __m128i b0 = _mm_add_epi16(a0, a1); + const __m128i b1 = _mm_add_epi16(a3, a2); + const __m128i b2 = _mm_sub_epi16(a3, a2); + const __m128i b3 = _mm_sub_epi16(a0, a1); + // a00 a01 a02 a03 b00 b01 b02 b03 + // a10 a11 a12 a13 b10 b11 b12 b13 + // a20 a21 a22 a23 b20 b21 b22 b23 + // a30 a31 a32 a33 b30 b31 b32 b33 + + // Transpose the two 4x4. + VP8Transpose_2_4x4_16b(&b0, &b1, &b2, &b3, &tmp_0, &tmp_1, &tmp_2, &tmp_3); + } + + // Horizontal pass and difference of weighted sums. + { + // Load all inputs. + const __m128i w_0 = _mm_loadu_si128((const __m128i*)&w[0]); + const __m128i w_8 = _mm_loadu_si128((const __m128i*)&w[8]); + + // Calculate a and b (two 4x4 at once). + const __m128i a0 = _mm_add_epi16(tmp_0, tmp_2); + const __m128i a1 = _mm_add_epi16(tmp_1, tmp_3); + const __m128i a2 = _mm_sub_epi16(tmp_1, tmp_3); + const __m128i a3 = _mm_sub_epi16(tmp_0, tmp_2); + const __m128i b0 = _mm_add_epi16(a0, a1); + const __m128i b1 = _mm_add_epi16(a3, a2); + const __m128i b2 = _mm_sub_epi16(a3, a2); + const __m128i b3 = _mm_sub_epi16(a0, a1); + + // Separate the transforms of inA and inB. + __m128i A_b0 = _mm_unpacklo_epi64(b0, b1); + __m128i A_b2 = _mm_unpacklo_epi64(b2, b3); + __m128i B_b0 = _mm_unpackhi_epi64(b0, b1); + __m128i B_b2 = _mm_unpackhi_epi64(b2, b3); + + { + const __m128i d0 = _mm_sub_epi16(zero, A_b0); + const __m128i d1 = _mm_sub_epi16(zero, A_b2); + const __m128i d2 = _mm_sub_epi16(zero, B_b0); + const __m128i d3 = _mm_sub_epi16(zero, B_b2); + A_b0 = _mm_max_epi16(A_b0, d0); // abs(v), 16b + A_b2 = _mm_max_epi16(A_b2, d1); + B_b0 = _mm_max_epi16(B_b0, d2); + B_b2 = _mm_max_epi16(B_b2, d3); + } + + // weighted sums + A_b0 = _mm_madd_epi16(A_b0, w_0); + A_b2 = _mm_madd_epi16(A_b2, w_8); + B_b0 = _mm_madd_epi16(B_b0, w_0); + B_b2 = _mm_madd_epi16(B_b2, w_8); + A_b0 = _mm_add_epi32(A_b0, A_b2); + B_b0 = _mm_add_epi32(B_b0, B_b2); + + // difference of weighted sums + A_b0 = _mm_sub_epi32(A_b0, B_b0); + _mm_storeu_si128((__m128i*)&sum[0], A_b0); + } + return sum[0] + sum[1] + sum[2] + sum[3]; +} + +static int Disto4x4_SSE2(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + const int diff_sum = TTransform_SSE2(a, b, w); + return abs(diff_sum) >> 5; +} + +static int Disto16x16_SSE2(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + int D = 0; + int x, y; + for (y = 0; y < 16 * BPS; y += 4 * BPS) { + for (x = 0; x < 16; x += 4) { + D += Disto4x4_SSE2(a + x + y, b + x + y, w); + } + } + return D; +} + +//------------------------------------------------------------------------------ +// Quantization +// + +static WEBP_INLINE int DoQuantizeBlock_SSE2(int16_t in[16], int16_t out[16], + const uint16_t* const sharpen, + const VP8Matrix* const mtx) { + const __m128i max_coeff_2047 = _mm_set1_epi16(MAX_LEVEL); + const __m128i zero = _mm_setzero_si128(); + __m128i coeff0, coeff8; + __m128i out0, out8; + __m128i packed_out; + + // Load all inputs. + __m128i in0 = _mm_loadu_si128((__m128i*)&in[0]); + __m128i in8 = _mm_loadu_si128((__m128i*)&in[8]); + const __m128i iq0 = _mm_loadu_si128((const __m128i*)&mtx->iq_[0]); + const __m128i iq8 = _mm_loadu_si128((const __m128i*)&mtx->iq_[8]); + const __m128i q0 = _mm_loadu_si128((const __m128i*)&mtx->q_[0]); + const __m128i q8 = _mm_loadu_si128((const __m128i*)&mtx->q_[8]); + + // extract sign(in) (0x0000 if positive, 0xffff if negative) + const __m128i sign0 = _mm_cmpgt_epi16(zero, in0); + const __m128i sign8 = _mm_cmpgt_epi16(zero, in8); + + // coeff = abs(in) = (in ^ sign) - sign + coeff0 = _mm_xor_si128(in0, sign0); + coeff8 = _mm_xor_si128(in8, sign8); + coeff0 = _mm_sub_epi16(coeff0, sign0); + coeff8 = _mm_sub_epi16(coeff8, sign8); + + // coeff = abs(in) + sharpen + if (sharpen != NULL) { + const __m128i sharpen0 = _mm_loadu_si128((const __m128i*)&sharpen[0]); + const __m128i sharpen8 = _mm_loadu_si128((const __m128i*)&sharpen[8]); + coeff0 = _mm_add_epi16(coeff0, sharpen0); + coeff8 = _mm_add_epi16(coeff8, sharpen8); + } + + // out = (coeff * iQ + B) >> QFIX + { + // doing calculations with 32b precision (QFIX=17) + // out = (coeff * iQ) + const __m128i coeff_iQ0H = _mm_mulhi_epu16(coeff0, iq0); + const __m128i coeff_iQ0L = _mm_mullo_epi16(coeff0, iq0); + const __m128i coeff_iQ8H = _mm_mulhi_epu16(coeff8, iq8); + const __m128i coeff_iQ8L = _mm_mullo_epi16(coeff8, iq8); + __m128i out_00 = _mm_unpacklo_epi16(coeff_iQ0L, coeff_iQ0H); + __m128i out_04 = _mm_unpackhi_epi16(coeff_iQ0L, coeff_iQ0H); + __m128i out_08 = _mm_unpacklo_epi16(coeff_iQ8L, coeff_iQ8H); + __m128i out_12 = _mm_unpackhi_epi16(coeff_iQ8L, coeff_iQ8H); + // out = (coeff * iQ + B) + const __m128i bias_00 = _mm_loadu_si128((const __m128i*)&mtx->bias_[0]); + const __m128i bias_04 = _mm_loadu_si128((const __m128i*)&mtx->bias_[4]); + const __m128i bias_08 = _mm_loadu_si128((const __m128i*)&mtx->bias_[8]); + const __m128i bias_12 = _mm_loadu_si128((const __m128i*)&mtx->bias_[12]); + out_00 = _mm_add_epi32(out_00, bias_00); + out_04 = _mm_add_epi32(out_04, bias_04); + out_08 = _mm_add_epi32(out_08, bias_08); + out_12 = _mm_add_epi32(out_12, bias_12); + // out = QUANTDIV(coeff, iQ, B, QFIX) + out_00 = _mm_srai_epi32(out_00, QFIX); + out_04 = _mm_srai_epi32(out_04, QFIX); + out_08 = _mm_srai_epi32(out_08, QFIX); + out_12 = _mm_srai_epi32(out_12, QFIX); + + // pack result as 16b + out0 = _mm_packs_epi32(out_00, out_04); + out8 = _mm_packs_epi32(out_08, out_12); + + // if (coeff > 2047) coeff = 2047 + out0 = _mm_min_epi16(out0, max_coeff_2047); + out8 = _mm_min_epi16(out8, max_coeff_2047); + } + + // get sign back (if (sign[j]) out_n = -out_n) + out0 = _mm_xor_si128(out0, sign0); + out8 = _mm_xor_si128(out8, sign8); + out0 = _mm_sub_epi16(out0, sign0); + out8 = _mm_sub_epi16(out8, sign8); + + // in = out * Q + in0 = _mm_mullo_epi16(out0, q0); + in8 = _mm_mullo_epi16(out8, q8); + + _mm_storeu_si128((__m128i*)&in[0], in0); + _mm_storeu_si128((__m128i*)&in[8], in8); + + // zigzag the output before storing it. + // + // The zigzag pattern can almost be reproduced with a small sequence of + // shuffles. After it, we only need to swap the 7th (ending up in third + // position instead of twelfth) and 8th values. + { + __m128i outZ0, outZ8; + outZ0 = _mm_shufflehi_epi16(out0, _MM_SHUFFLE(2, 1, 3, 0)); + outZ0 = _mm_shuffle_epi32 (outZ0, _MM_SHUFFLE(3, 1, 2, 0)); + outZ0 = _mm_shufflehi_epi16(outZ0, _MM_SHUFFLE(3, 1, 0, 2)); + outZ8 = _mm_shufflelo_epi16(out8, _MM_SHUFFLE(3, 0, 2, 1)); + outZ8 = _mm_shuffle_epi32 (outZ8, _MM_SHUFFLE(3, 1, 2, 0)); + outZ8 = _mm_shufflelo_epi16(outZ8, _MM_SHUFFLE(1, 3, 2, 0)); + _mm_storeu_si128((__m128i*)&out[0], outZ0); + _mm_storeu_si128((__m128i*)&out[8], outZ8); + packed_out = _mm_packs_epi16(outZ0, outZ8); + } + { + const int16_t outZ_12 = out[12]; + const int16_t outZ_3 = out[3]; + out[3] = outZ_12; + out[12] = outZ_3; + } + + // detect if all 'out' values are zeroes or not + return (_mm_movemask_epi8(_mm_cmpeq_epi8(packed_out, zero)) != 0xffff); +} + +static int QuantizeBlock_SSE2(int16_t in[16], int16_t out[16], + const VP8Matrix* const mtx) { + return DoQuantizeBlock_SSE2(in, out, &mtx->sharpen_[0], mtx); +} + +static int QuantizeBlockWHT_SSE2(int16_t in[16], int16_t out[16], + const VP8Matrix* const mtx) { + return DoQuantizeBlock_SSE2(in, out, NULL, mtx); +} + +static int Quantize2Blocks_SSE2(int16_t in[32], int16_t out[32], + const VP8Matrix* const mtx) { + int nz; + const uint16_t* const sharpen = &mtx->sharpen_[0]; + nz = DoQuantizeBlock_SSE2(in + 0 * 16, out + 0 * 16, sharpen, mtx) << 0; + nz |= DoQuantizeBlock_SSE2(in + 1 * 16, out + 1 * 16, sharpen, mtx) << 1; + return nz; +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8EncDspInitSSE2(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitSSE2(void) { + VP8CollectHistogram = CollectHistogram_SSE2; + VP8EncPredLuma16 = Intra16Preds_SSE2; + VP8EncPredChroma8 = IntraChromaPreds_SSE2; + VP8EncPredLuma4 = Intra4Preds_SSE2; + VP8EncQuantizeBlock = QuantizeBlock_SSE2; + VP8EncQuantize2Blocks = Quantize2Blocks_SSE2; + VP8EncQuantizeBlockWHT = QuantizeBlockWHT_SSE2; + VP8ITransform = ITransform_SSE2; + VP8FTransform = FTransform_SSE2; + VP8FTransform2 = FTransform2_SSE2; + VP8FTransformWHT = FTransformWHT_SSE2; + VP8SSE16x16 = SSE16x16_SSE2; + VP8SSE16x8 = SSE16x8_SSE2; + VP8SSE8x8 = SSE8x8_SSE2; + VP8SSE4x4 = SSE4x4_SSE2; + VP8TDisto4x4 = Disto4x4_SSE2; + VP8TDisto16x16 = Disto16x16_SSE2; + VP8Mean16x4 = Mean16x4_SSE2; +} + +#else // !WEBP_USE_SSE2 + +WEBP_DSP_INIT_STUB(VP8EncDspInitSSE2) + +#endif // WEBP_USE_SSE2 diff --git a/third-party/webp/libwebp/src/dsp/enc_sse41.c b/third-party/webp/libwebp/src/dsp/enc_sse41.c new file mode 100644 index 0000000000..924035a644 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/enc_sse41.c @@ -0,0 +1,339 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE4 version of some encoding functions. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE41) +#include +#include // for abs() + +#include "src/dsp/common_sse2.h" +#include "src/enc/vp8i_enc.h" + +//------------------------------------------------------------------------------ +// Compute susceptibility based on DCT-coeff histograms. + +static void CollectHistogram_SSE41(const uint8_t* ref, const uint8_t* pred, + int start_block, int end_block, + VP8Histogram* const histo) { + const __m128i max_coeff_thresh = _mm_set1_epi16(MAX_COEFF_THRESH); + int j; + int distribution[MAX_COEFF_THRESH + 1] = { 0 }; + for (j = start_block; j < end_block; ++j) { + int16_t out[16]; + int k; + + VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out); + + // Convert coefficients to bin (within out[]). + { + // Load. + const __m128i out0 = _mm_loadu_si128((__m128i*)&out[0]); + const __m128i out1 = _mm_loadu_si128((__m128i*)&out[8]); + // v = abs(out) >> 3 + const __m128i abs0 = _mm_abs_epi16(out0); + const __m128i abs1 = _mm_abs_epi16(out1); + const __m128i v0 = _mm_srai_epi16(abs0, 3); + const __m128i v1 = _mm_srai_epi16(abs1, 3); + // bin = min(v, MAX_COEFF_THRESH) + const __m128i bin0 = _mm_min_epi16(v0, max_coeff_thresh); + const __m128i bin1 = _mm_min_epi16(v1, max_coeff_thresh); + // Store. + _mm_storeu_si128((__m128i*)&out[0], bin0); + _mm_storeu_si128((__m128i*)&out[8], bin1); + } + + // Convert coefficients to bin. + for (k = 0; k < 16; ++k) { + ++distribution[out[k]]; + } + } + VP8SetHistogramData(distribution, histo); +} + +//------------------------------------------------------------------------------ +// Texture distortion +// +// We try to match the spectral content (weighted) between source and +// reconstructed samples. + +// Hadamard transform +// Returns the weighted sum of the absolute value of transformed coefficients. +// w[] contains a row-major 4 by 4 symmetric matrix. +static int TTransform_SSE41(const uint8_t* inA, const uint8_t* inB, + const uint16_t* const w) { + int32_t sum[4]; + __m128i tmp_0, tmp_1, tmp_2, tmp_3; + + // Load and combine inputs. + { + const __m128i inA_0 = _mm_loadu_si128((const __m128i*)&inA[BPS * 0]); + const __m128i inA_1 = _mm_loadu_si128((const __m128i*)&inA[BPS * 1]); + const __m128i inA_2 = _mm_loadu_si128((const __m128i*)&inA[BPS * 2]); + // In SSE4.1, with gcc 4.8 at least (maybe other versions), + // _mm_loadu_si128 is faster than _mm_loadl_epi64. But for the last lump + // of inA and inB, _mm_loadl_epi64 is still used not to have an out of + // bound read. + const __m128i inA_3 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 3]); + const __m128i inB_0 = _mm_loadu_si128((const __m128i*)&inB[BPS * 0]); + const __m128i inB_1 = _mm_loadu_si128((const __m128i*)&inB[BPS * 1]); + const __m128i inB_2 = _mm_loadu_si128((const __m128i*)&inB[BPS * 2]); + const __m128i inB_3 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 3]); + + // Combine inA and inB (we'll do two transforms in parallel). + const __m128i inAB_0 = _mm_unpacklo_epi32(inA_0, inB_0); + const __m128i inAB_1 = _mm_unpacklo_epi32(inA_1, inB_1); + const __m128i inAB_2 = _mm_unpacklo_epi32(inA_2, inB_2); + const __m128i inAB_3 = _mm_unpacklo_epi32(inA_3, inB_3); + tmp_0 = _mm_cvtepu8_epi16(inAB_0); + tmp_1 = _mm_cvtepu8_epi16(inAB_1); + tmp_2 = _mm_cvtepu8_epi16(inAB_2); + tmp_3 = _mm_cvtepu8_epi16(inAB_3); + // a00 a01 a02 a03 b00 b01 b02 b03 + // a10 a11 a12 a13 b10 b11 b12 b13 + // a20 a21 a22 a23 b20 b21 b22 b23 + // a30 a31 a32 a33 b30 b31 b32 b33 + } + + // Vertical pass first to avoid a transpose (vertical and horizontal passes + // are commutative because w/kWeightY is symmetric) and subsequent transpose. + { + // Calculate a and b (two 4x4 at once). + const __m128i a0 = _mm_add_epi16(tmp_0, tmp_2); + const __m128i a1 = _mm_add_epi16(tmp_1, tmp_3); + const __m128i a2 = _mm_sub_epi16(tmp_1, tmp_3); + const __m128i a3 = _mm_sub_epi16(tmp_0, tmp_2); + const __m128i b0 = _mm_add_epi16(a0, a1); + const __m128i b1 = _mm_add_epi16(a3, a2); + const __m128i b2 = _mm_sub_epi16(a3, a2); + const __m128i b3 = _mm_sub_epi16(a0, a1); + // a00 a01 a02 a03 b00 b01 b02 b03 + // a10 a11 a12 a13 b10 b11 b12 b13 + // a20 a21 a22 a23 b20 b21 b22 b23 + // a30 a31 a32 a33 b30 b31 b32 b33 + + // Transpose the two 4x4. + VP8Transpose_2_4x4_16b(&b0, &b1, &b2, &b3, &tmp_0, &tmp_1, &tmp_2, &tmp_3); + } + + // Horizontal pass and difference of weighted sums. + { + // Load all inputs. + const __m128i w_0 = _mm_loadu_si128((const __m128i*)&w[0]); + const __m128i w_8 = _mm_loadu_si128((const __m128i*)&w[8]); + + // Calculate a and b (two 4x4 at once). + const __m128i a0 = _mm_add_epi16(tmp_0, tmp_2); + const __m128i a1 = _mm_add_epi16(tmp_1, tmp_3); + const __m128i a2 = _mm_sub_epi16(tmp_1, tmp_3); + const __m128i a3 = _mm_sub_epi16(tmp_0, tmp_2); + const __m128i b0 = _mm_add_epi16(a0, a1); + const __m128i b1 = _mm_add_epi16(a3, a2); + const __m128i b2 = _mm_sub_epi16(a3, a2); + const __m128i b3 = _mm_sub_epi16(a0, a1); + + // Separate the transforms of inA and inB. + __m128i A_b0 = _mm_unpacklo_epi64(b0, b1); + __m128i A_b2 = _mm_unpacklo_epi64(b2, b3); + __m128i B_b0 = _mm_unpackhi_epi64(b0, b1); + __m128i B_b2 = _mm_unpackhi_epi64(b2, b3); + + A_b0 = _mm_abs_epi16(A_b0); + A_b2 = _mm_abs_epi16(A_b2); + B_b0 = _mm_abs_epi16(B_b0); + B_b2 = _mm_abs_epi16(B_b2); + + // weighted sums + A_b0 = _mm_madd_epi16(A_b0, w_0); + A_b2 = _mm_madd_epi16(A_b2, w_8); + B_b0 = _mm_madd_epi16(B_b0, w_0); + B_b2 = _mm_madd_epi16(B_b2, w_8); + A_b0 = _mm_add_epi32(A_b0, A_b2); + B_b0 = _mm_add_epi32(B_b0, B_b2); + + // difference of weighted sums + A_b2 = _mm_sub_epi32(A_b0, B_b0); + _mm_storeu_si128((__m128i*)&sum[0], A_b2); + } + return sum[0] + sum[1] + sum[2] + sum[3]; +} + +static int Disto4x4_SSE41(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + const int diff_sum = TTransform_SSE41(a, b, w); + return abs(diff_sum) >> 5; +} + +static int Disto16x16_SSE41(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + int D = 0; + int x, y; + for (y = 0; y < 16 * BPS; y += 4 * BPS) { + for (x = 0; x < 16; x += 4) { + D += Disto4x4_SSE41(a + x + y, b + x + y, w); + } + } + return D; +} + +//------------------------------------------------------------------------------ +// Quantization +// + +// Generates a pshufb constant for shuffling 16b words. +#define PSHUFB_CST(A,B,C,D,E,F,G,H) \ + _mm_set_epi8(2 * (H) + 1, 2 * (H) + 0, 2 * (G) + 1, 2 * (G) + 0, \ + 2 * (F) + 1, 2 * (F) + 0, 2 * (E) + 1, 2 * (E) + 0, \ + 2 * (D) + 1, 2 * (D) + 0, 2 * (C) + 1, 2 * (C) + 0, \ + 2 * (B) + 1, 2 * (B) + 0, 2 * (A) + 1, 2 * (A) + 0) + +static WEBP_INLINE int DoQuantizeBlock_SSE41(int16_t in[16], int16_t out[16], + const uint16_t* const sharpen, + const VP8Matrix* const mtx) { + const __m128i max_coeff_2047 = _mm_set1_epi16(MAX_LEVEL); + const __m128i zero = _mm_setzero_si128(); + __m128i out0, out8; + __m128i packed_out; + + // Load all inputs. + __m128i in0 = _mm_loadu_si128((__m128i*)&in[0]); + __m128i in8 = _mm_loadu_si128((__m128i*)&in[8]); + const __m128i iq0 = _mm_loadu_si128((const __m128i*)&mtx->iq_[0]); + const __m128i iq8 = _mm_loadu_si128((const __m128i*)&mtx->iq_[8]); + const __m128i q0 = _mm_loadu_si128((const __m128i*)&mtx->q_[0]); + const __m128i q8 = _mm_loadu_si128((const __m128i*)&mtx->q_[8]); + + // coeff = abs(in) + __m128i coeff0 = _mm_abs_epi16(in0); + __m128i coeff8 = _mm_abs_epi16(in8); + + // coeff = abs(in) + sharpen + if (sharpen != NULL) { + const __m128i sharpen0 = _mm_loadu_si128((const __m128i*)&sharpen[0]); + const __m128i sharpen8 = _mm_loadu_si128((const __m128i*)&sharpen[8]); + coeff0 = _mm_add_epi16(coeff0, sharpen0); + coeff8 = _mm_add_epi16(coeff8, sharpen8); + } + + // out = (coeff * iQ + B) >> QFIX + { + // doing calculations with 32b precision (QFIX=17) + // out = (coeff * iQ) + const __m128i coeff_iQ0H = _mm_mulhi_epu16(coeff0, iq0); + const __m128i coeff_iQ0L = _mm_mullo_epi16(coeff0, iq0); + const __m128i coeff_iQ8H = _mm_mulhi_epu16(coeff8, iq8); + const __m128i coeff_iQ8L = _mm_mullo_epi16(coeff8, iq8); + __m128i out_00 = _mm_unpacklo_epi16(coeff_iQ0L, coeff_iQ0H); + __m128i out_04 = _mm_unpackhi_epi16(coeff_iQ0L, coeff_iQ0H); + __m128i out_08 = _mm_unpacklo_epi16(coeff_iQ8L, coeff_iQ8H); + __m128i out_12 = _mm_unpackhi_epi16(coeff_iQ8L, coeff_iQ8H); + // out = (coeff * iQ + B) + const __m128i bias_00 = _mm_loadu_si128((const __m128i*)&mtx->bias_[0]); + const __m128i bias_04 = _mm_loadu_si128((const __m128i*)&mtx->bias_[4]); + const __m128i bias_08 = _mm_loadu_si128((const __m128i*)&mtx->bias_[8]); + const __m128i bias_12 = _mm_loadu_si128((const __m128i*)&mtx->bias_[12]); + out_00 = _mm_add_epi32(out_00, bias_00); + out_04 = _mm_add_epi32(out_04, bias_04); + out_08 = _mm_add_epi32(out_08, bias_08); + out_12 = _mm_add_epi32(out_12, bias_12); + // out = QUANTDIV(coeff, iQ, B, QFIX) + out_00 = _mm_srai_epi32(out_00, QFIX); + out_04 = _mm_srai_epi32(out_04, QFIX); + out_08 = _mm_srai_epi32(out_08, QFIX); + out_12 = _mm_srai_epi32(out_12, QFIX); + + // pack result as 16b + out0 = _mm_packs_epi32(out_00, out_04); + out8 = _mm_packs_epi32(out_08, out_12); + + // if (coeff > 2047) coeff = 2047 + out0 = _mm_min_epi16(out0, max_coeff_2047); + out8 = _mm_min_epi16(out8, max_coeff_2047); + } + + // put sign back + out0 = _mm_sign_epi16(out0, in0); + out8 = _mm_sign_epi16(out8, in8); + + // in = out * Q + in0 = _mm_mullo_epi16(out0, q0); + in8 = _mm_mullo_epi16(out8, q8); + + _mm_storeu_si128((__m128i*)&in[0], in0); + _mm_storeu_si128((__m128i*)&in[8], in8); + + // zigzag the output before storing it. The re-ordering is: + // 0 1 2 3 4 5 6 7 | 8 9 10 11 12 13 14 15 + // -> 0 1 4[8]5 2 3 6 | 9 12 13 10 [7]11 14 15 + // There's only two misplaced entries ([8] and [7]) that are crossing the + // reg's boundaries. + // We use pshufb instead of pshuflo/pshufhi. + { + const __m128i kCst_lo = PSHUFB_CST(0, 1, 4, -1, 5, 2, 3, 6); + const __m128i kCst_7 = PSHUFB_CST(-1, -1, -1, -1, 7, -1, -1, -1); + const __m128i tmp_lo = _mm_shuffle_epi8(out0, kCst_lo); + const __m128i tmp_7 = _mm_shuffle_epi8(out0, kCst_7); // extract #7 + const __m128i kCst_hi = PSHUFB_CST(1, 4, 5, 2, -1, 3, 6, 7); + const __m128i kCst_8 = PSHUFB_CST(-1, -1, -1, 0, -1, -1, -1, -1); + const __m128i tmp_hi = _mm_shuffle_epi8(out8, kCst_hi); + const __m128i tmp_8 = _mm_shuffle_epi8(out8, kCst_8); // extract #8 + const __m128i out_z0 = _mm_or_si128(tmp_lo, tmp_8); + const __m128i out_z8 = _mm_or_si128(tmp_hi, tmp_7); + _mm_storeu_si128((__m128i*)&out[0], out_z0); + _mm_storeu_si128((__m128i*)&out[8], out_z8); + packed_out = _mm_packs_epi16(out_z0, out_z8); + } + + // detect if all 'out' values are zeroes or not + return (_mm_movemask_epi8(_mm_cmpeq_epi8(packed_out, zero)) != 0xffff); +} + +#undef PSHUFB_CST + +static int QuantizeBlock_SSE41(int16_t in[16], int16_t out[16], + const VP8Matrix* const mtx) { + return DoQuantizeBlock_SSE41(in, out, &mtx->sharpen_[0], mtx); +} + +static int QuantizeBlockWHT_SSE41(int16_t in[16], int16_t out[16], + const VP8Matrix* const mtx) { + return DoQuantizeBlock_SSE41(in, out, NULL, mtx); +} + +static int Quantize2Blocks_SSE41(int16_t in[32], int16_t out[32], + const VP8Matrix* const mtx) { + int nz; + const uint16_t* const sharpen = &mtx->sharpen_[0]; + nz = DoQuantizeBlock_SSE41(in + 0 * 16, out + 0 * 16, sharpen, mtx) << 0; + nz |= DoQuantizeBlock_SSE41(in + 1 * 16, out + 1 * 16, sharpen, mtx) << 1; + return nz; +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8EncDspInitSSE41(void); +WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitSSE41(void) { + VP8CollectHistogram = CollectHistogram_SSE41; + VP8EncQuantizeBlock = QuantizeBlock_SSE41; + VP8EncQuantize2Blocks = Quantize2Blocks_SSE41; + VP8EncQuantizeBlockWHT = QuantizeBlockWHT_SSE41; + VP8TDisto4x4 = Disto4x4_SSE41; + VP8TDisto16x16 = Disto16x16_SSE41; +} + +#else // !WEBP_USE_SSE41 + +WEBP_DSP_INIT_STUB(VP8EncDspInitSSE41) + +#endif // WEBP_USE_SSE41 diff --git a/third-party/webp/libwebp/src/dsp/filters.c b/third-party/webp/libwebp/src/dsp/filters.c new file mode 100644 index 0000000000..c1350d5c9d --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/filters.c @@ -0,0 +1,295 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Spatial prediction using various filters +// +// Author: Urvang (urvang@google.com) + +#include "src/dsp/dsp.h" +#include +#include +#include + +//------------------------------------------------------------------------------ +// Helpful macro. + +# define SANITY_CHECK(in, out) \ + assert((in) != NULL); \ + assert((out) != NULL); \ + assert(width > 0); \ + assert(height > 0); \ + assert(stride >= width); \ + assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ + (void)height; // Silence unused warning. + +#if !WEBP_NEON_OMIT_C_CODE +static WEBP_INLINE void PredictLine_C(const uint8_t* src, const uint8_t* pred, + uint8_t* dst, int length, int inverse) { + int i; + if (inverse) { + for (i = 0; i < length; ++i) dst[i] = (uint8_t)(src[i] + pred[i]); + } else { + for (i = 0; i < length; ++i) dst[i] = (uint8_t)(src[i] - pred[i]); + } +} + +//------------------------------------------------------------------------------ +// Horizontal filter. + +static WEBP_INLINE void DoHorizontalFilter_C(const uint8_t* in, + int width, int height, int stride, + int row, int num_rows, + int inverse, uint8_t* out) { + const uint8_t* preds; + const size_t start_offset = row * stride; + const int last_row = row + num_rows; + SANITY_CHECK(in, out); + in += start_offset; + out += start_offset; + preds = inverse ? out : in; + + if (row == 0) { + // Leftmost pixel is the same as input for topmost scanline. + out[0] = in[0]; + PredictLine_C(in + 1, preds, out + 1, width - 1, inverse); + row = 1; + preds += stride; + in += stride; + out += stride; + } + + // Filter line-by-line. + while (row < last_row) { + // Leftmost pixel is predicted from above. + PredictLine_C(in, preds - stride, out, 1, inverse); + PredictLine_C(in + 1, preds, out + 1, width - 1, inverse); + ++row; + preds += stride; + in += stride; + out += stride; + } +} + +//------------------------------------------------------------------------------ +// Vertical filter. + +static WEBP_INLINE void DoVerticalFilter_C(const uint8_t* in, + int width, int height, int stride, + int row, int num_rows, + int inverse, uint8_t* out) { + const uint8_t* preds; + const size_t start_offset = row * stride; + const int last_row = row + num_rows; + SANITY_CHECK(in, out); + in += start_offset; + out += start_offset; + preds = inverse ? out : in; + + if (row == 0) { + // Very first top-left pixel is copied. + out[0] = in[0]; + // Rest of top scan-line is left-predicted. + PredictLine_C(in + 1, preds, out + 1, width - 1, inverse); + row = 1; + in += stride; + out += stride; + } else { + // We are starting from in-between. Make sure 'preds' points to prev row. + preds -= stride; + } + + // Filter line-by-line. + while (row < last_row) { + PredictLine_C(in, preds, out, width, inverse); + ++row; + preds += stride; + in += stride; + out += stride; + } +} +#endif // !WEBP_NEON_OMIT_C_CODE + +//------------------------------------------------------------------------------ +// Gradient filter. + +static WEBP_INLINE int GradientPredictor_C(uint8_t a, uint8_t b, uint8_t c) { + const int g = a + b - c; + return ((g & ~0xff) == 0) ? g : (g < 0) ? 0 : 255; // clip to 8bit +} + +#if !WEBP_NEON_OMIT_C_CODE +static WEBP_INLINE void DoGradientFilter_C(const uint8_t* in, + int width, int height, int stride, + int row, int num_rows, + int inverse, uint8_t* out) { + const uint8_t* preds; + const size_t start_offset = row * stride; + const int last_row = row + num_rows; + SANITY_CHECK(in, out); + in += start_offset; + out += start_offset; + preds = inverse ? out : in; + + // left prediction for top scan-line + if (row == 0) { + out[0] = in[0]; + PredictLine_C(in + 1, preds, out + 1, width - 1, inverse); + row = 1; + preds += stride; + in += stride; + out += stride; + } + + // Filter line-by-line. + while (row < last_row) { + int w; + // leftmost pixel: predict from above. + PredictLine_C(in, preds - stride, out, 1, inverse); + for (w = 1; w < width; ++w) { + const int pred = GradientPredictor_C(preds[w - 1], + preds[w - stride], + preds[w - stride - 1]); + out[w] = (uint8_t)(in[w] + (inverse ? pred : -pred)); + } + ++row; + preds += stride; + in += stride; + out += stride; + } +} +#endif // !WEBP_NEON_OMIT_C_CODE + +#undef SANITY_CHECK + +//------------------------------------------------------------------------------ + +#if !WEBP_NEON_OMIT_C_CODE +static void HorizontalFilter_C(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + DoHorizontalFilter_C(data, width, height, stride, 0, height, 0, + filtered_data); +} + +static void VerticalFilter_C(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + DoVerticalFilter_C(data, width, height, stride, 0, height, 0, filtered_data); +} + +static void GradientFilter_C(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + DoGradientFilter_C(data, width, height, stride, 0, height, 0, filtered_data); +} +#endif // !WEBP_NEON_OMIT_C_CODE + +//------------------------------------------------------------------------------ + +static void NoneUnfilter_C(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { + (void)prev; + if (out != in) memcpy(out, in, width * sizeof(*out)); +} + +static void HorizontalUnfilter_C(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { + uint8_t pred = (prev == NULL) ? 0 : prev[0]; + int i; + for (i = 0; i < width; ++i) { + out[i] = (uint8_t)(pred + in[i]); + pred = out[i]; + } +} + +#if !WEBP_NEON_OMIT_C_CODE +static void VerticalUnfilter_C(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { + if (prev == NULL) { + HorizontalUnfilter_C(NULL, in, out, width); + } else { + int i; + for (i = 0; i < width; ++i) out[i] = (uint8_t)(prev[i] + in[i]); + } +} +#endif // !WEBP_NEON_OMIT_C_CODE + +static void GradientUnfilter_C(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { + if (prev == NULL) { + HorizontalUnfilter_C(NULL, in, out, width); + } else { + uint8_t top = prev[0], top_left = top, left = top; + int i; + for (i = 0; i < width; ++i) { + top = prev[i]; // need to read this first, in case prev==out + left = (uint8_t)(in[i] + GradientPredictor_C(left, top, top_left)); + top_left = top; + out[i] = left; + } + } +} + +//------------------------------------------------------------------------------ +// Init function + +WebPFilterFunc WebPFilters[WEBP_FILTER_LAST]; +WebPUnfilterFunc WebPUnfilters[WEBP_FILTER_LAST]; + +extern VP8CPUInfo VP8GetCPUInfo; +extern void VP8FiltersInitMIPSdspR2(void); +extern void VP8FiltersInitMSA(void); +extern void VP8FiltersInitNEON(void); +extern void VP8FiltersInitSSE2(void); + +WEBP_DSP_INIT_FUNC(VP8FiltersInit) { + WebPUnfilters[WEBP_FILTER_NONE] = NoneUnfilter_C; +#if !WEBP_NEON_OMIT_C_CODE + WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter_C; + WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter_C; +#endif + WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter_C; + + WebPFilters[WEBP_FILTER_NONE] = NULL; +#if !WEBP_NEON_OMIT_C_CODE + WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter_C; + WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter_C; + WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter_C; +#endif + + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_HAVE_SSE2) + if (VP8GetCPUInfo(kSSE2)) { + VP8FiltersInitSSE2(); + } +#endif +#if defined(WEBP_USE_MIPS_DSP_R2) + if (VP8GetCPUInfo(kMIPSdspR2)) { + VP8FiltersInitMIPSdspR2(); + } +#endif +#if defined(WEBP_USE_MSA) + if (VP8GetCPUInfo(kMSA)) { + VP8FiltersInitMSA(); + } +#endif + } + +#if defined(WEBP_HAVE_NEON) + if (WEBP_NEON_OMIT_C_CODE || + (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) { + VP8FiltersInitNEON(); + } +#endif + + assert(WebPUnfilters[WEBP_FILTER_NONE] != NULL); + assert(WebPUnfilters[WEBP_FILTER_HORIZONTAL] != NULL); + assert(WebPUnfilters[WEBP_FILTER_VERTICAL] != NULL); + assert(WebPUnfilters[WEBP_FILTER_GRADIENT] != NULL); + assert(WebPFilters[WEBP_FILTER_HORIZONTAL] != NULL); + assert(WebPFilters[WEBP_FILTER_VERTICAL] != NULL); + assert(WebPFilters[WEBP_FILTER_GRADIENT] != NULL); +} diff --git a/third-party/webp/libwebp/src/dsp/filters_mips_dsp_r2.c b/third-party/webp/libwebp/src/dsp/filters_mips_dsp_r2.c new file mode 100644 index 0000000000..9382b12823 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/filters_mips_dsp_r2.c @@ -0,0 +1,402 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Spatial prediction using various filters +// +// Author(s): Branimir Vasic (branimir.vasic@imgtec.com) +// Djordje Pesut (djordje.pesut@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MIPS_DSP_R2) + +#include "src/dsp/dsp.h" +#include +#include +#include + +//------------------------------------------------------------------------------ +// Helpful macro. + +# define SANITY_CHECK(in, out) \ + assert(in != NULL); \ + assert(out != NULL); \ + assert(width > 0); \ + assert(height > 0); \ + assert(stride >= width); \ + assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ + (void)height; // Silence unused warning. + +#define DO_PREDICT_LINE(SRC, DST, LENGTH, INVERSE) do { \ + const uint8_t* psrc = (uint8_t*)(SRC); \ + uint8_t* pdst = (uint8_t*)(DST); \ + const int ilength = (int)(LENGTH); \ + int temp0, temp1, temp2, temp3, temp4, temp5, temp6; \ + __asm__ volatile ( \ + ".set push \n\t" \ + ".set noreorder \n\t" \ + "srl %[temp0], %[length], 2 \n\t" \ + "beqz %[temp0], 4f \n\t" \ + " andi %[temp6], %[length], 3 \n\t" \ + ".if " #INVERSE " \n\t" \ + "1: \n\t" \ + "lbu %[temp1], -1(%[dst]) \n\t" \ + "lbu %[temp2], 0(%[src]) \n\t" \ + "lbu %[temp3], 1(%[src]) \n\t" \ + "lbu %[temp4], 2(%[src]) \n\t" \ + "lbu %[temp5], 3(%[src]) \n\t" \ + "addu %[temp1], %[temp1], %[temp2] \n\t" \ + "addu %[temp2], %[temp1], %[temp3] \n\t" \ + "addu %[temp3], %[temp2], %[temp4] \n\t" \ + "addu %[temp4], %[temp3], %[temp5] \n\t" \ + "sb %[temp1], 0(%[dst]) \n\t" \ + "sb %[temp2], 1(%[dst]) \n\t" \ + "sb %[temp3], 2(%[dst]) \n\t" \ + "sb %[temp4], 3(%[dst]) \n\t" \ + "addiu %[src], %[src], 4 \n\t" \ + "addiu %[temp0], %[temp0], -1 \n\t" \ + "bnez %[temp0], 1b \n\t" \ + " addiu %[dst], %[dst], 4 \n\t" \ + ".else \n\t" \ + "1: \n\t" \ + "ulw %[temp1], -1(%[src]) \n\t" \ + "ulw %[temp2], 0(%[src]) \n\t" \ + "addiu %[src], %[src], 4 \n\t" \ + "addiu %[temp0], %[temp0], -1 \n\t" \ + "subu.qb %[temp3], %[temp2], %[temp1] \n\t" \ + "usw %[temp3], 0(%[dst]) \n\t" \ + "bnez %[temp0], 1b \n\t" \ + " addiu %[dst], %[dst], 4 \n\t" \ + ".endif \n\t" \ + "4: \n\t" \ + "beqz %[temp6], 3f \n\t" \ + " nop \n\t" \ + "2: \n\t" \ + "lbu %[temp2], 0(%[src]) \n\t" \ + ".if " #INVERSE " \n\t" \ + "lbu %[temp1], -1(%[dst]) \n\t" \ + "addu %[temp3], %[temp1], %[temp2] \n\t" \ + ".else \n\t" \ + "lbu %[temp1], -1(%[src]) \n\t" \ + "subu %[temp3], %[temp1], %[temp2] \n\t" \ + ".endif \n\t" \ + "addiu %[src], %[src], 1 \n\t" \ + "sb %[temp3], 0(%[dst]) \n\t" \ + "addiu %[temp6], %[temp6], -1 \n\t" \ + "bnez %[temp6], 2b \n\t" \ + " addiu %[dst], %[dst], 1 \n\t" \ + "3: \n\t" \ + ".set pop \n\t" \ + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), \ + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), \ + [temp6]"=&r"(temp6), [dst]"+&r"(pdst), [src]"+&r"(psrc) \ + : [length]"r"(ilength) \ + : "memory" \ + ); \ + } while (0) + +static WEBP_INLINE void PredictLine_MIPSdspR2(const uint8_t* src, uint8_t* dst, + int length) { + DO_PREDICT_LINE(src, dst, length, 0); +} + +#define DO_PREDICT_LINE_VERTICAL(SRC, PRED, DST, LENGTH, INVERSE) do { \ + const uint8_t* psrc = (uint8_t*)(SRC); \ + const uint8_t* ppred = (uint8_t*)(PRED); \ + uint8_t* pdst = (uint8_t*)(DST); \ + const int ilength = (int)(LENGTH); \ + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; \ + __asm__ volatile ( \ + ".set push \n\t" \ + ".set noreorder \n\t" \ + "srl %[temp0], %[length], 0x3 \n\t" \ + "beqz %[temp0], 4f \n\t" \ + " andi %[temp7], %[length], 0x7 \n\t" \ + "1: \n\t" \ + "ulw %[temp1], 0(%[src]) \n\t" \ + "ulw %[temp2], 0(%[pred]) \n\t" \ + "ulw %[temp3], 4(%[src]) \n\t" \ + "ulw %[temp4], 4(%[pred]) \n\t" \ + "addiu %[src], %[src], 8 \n\t" \ + ".if " #INVERSE " \n\t" \ + "addu.qb %[temp5], %[temp1], %[temp2] \n\t" \ + "addu.qb %[temp6], %[temp3], %[temp4] \n\t" \ + ".else \n\t" \ + "subu.qb %[temp5], %[temp1], %[temp2] \n\t" \ + "subu.qb %[temp6], %[temp3], %[temp4] \n\t" \ + ".endif \n\t" \ + "addiu %[pred], %[pred], 8 \n\t" \ + "usw %[temp5], 0(%[dst]) \n\t" \ + "usw %[temp6], 4(%[dst]) \n\t" \ + "addiu %[temp0], %[temp0], -1 \n\t" \ + "bnez %[temp0], 1b \n\t" \ + " addiu %[dst], %[dst], 8 \n\t" \ + "4: \n\t" \ + "beqz %[temp7], 3f \n\t" \ + " nop \n\t" \ + "2: \n\t" \ + "lbu %[temp1], 0(%[src]) \n\t" \ + "lbu %[temp2], 0(%[pred]) \n\t" \ + "addiu %[src], %[src], 1 \n\t" \ + "addiu %[pred], %[pred], 1 \n\t" \ + ".if " #INVERSE " \n\t" \ + "addu %[temp3], %[temp1], %[temp2] \n\t" \ + ".else \n\t" \ + "subu %[temp3], %[temp1], %[temp2] \n\t" \ + ".endif \n\t" \ + "sb %[temp3], 0(%[dst]) \n\t" \ + "addiu %[temp7], %[temp7], -1 \n\t" \ + "bnez %[temp7], 2b \n\t" \ + " addiu %[dst], %[dst], 1 \n\t" \ + "3: \n\t" \ + ".set pop \n\t" \ + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), \ + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), \ + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [pred]"+&r"(ppred), \ + [dst]"+&r"(pdst), [src]"+&r"(psrc) \ + : [length]"r"(ilength) \ + : "memory" \ + ); \ + } while (0) + +#define PREDICT_LINE_ONE_PASS(SRC, PRED, DST) do { \ + int temp1, temp2, temp3; \ + __asm__ volatile ( \ + "lbu %[temp1], 0(%[src]) \n\t" \ + "lbu %[temp2], 0(%[pred]) \n\t" \ + "subu %[temp3], %[temp1], %[temp2] \n\t" \ + "sb %[temp3], 0(%[dst]) \n\t" \ + : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), [temp3]"=&r"(temp3) \ + : [pred]"r"((PRED)), [dst]"r"((DST)), [src]"r"((SRC)) \ + : "memory" \ + ); \ + } while (0) + +//------------------------------------------------------------------------------ +// Horizontal filter. + +#define FILTER_LINE_BY_LINE do { \ + while (row < last_row) { \ + PREDICT_LINE_ONE_PASS(in, preds - stride, out); \ + DO_PREDICT_LINE(in + 1, out + 1, width - 1, 0); \ + ++row; \ + preds += stride; \ + in += stride; \ + out += stride; \ + } \ + } while (0) + +static WEBP_INLINE void DoHorizontalFilter_MIPSdspR2(const uint8_t* in, + int width, int height, + int stride, + int row, int num_rows, + uint8_t* out) { + const uint8_t* preds; + const size_t start_offset = row * stride; + const int last_row = row + num_rows; + SANITY_CHECK(in, out); + in += start_offset; + out += start_offset; + preds = in; + + if (row == 0) { + // Leftmost pixel is the same as input for topmost scanline. + out[0] = in[0]; + PredictLine_MIPSdspR2(in + 1, out + 1, width - 1); + row = 1; + preds += stride; + in += stride; + out += stride; + } + + // Filter line-by-line. + FILTER_LINE_BY_LINE; +} +#undef FILTER_LINE_BY_LINE + +static void HorizontalFilter_MIPSdspR2(const uint8_t* data, + int width, int height, + int stride, uint8_t* filtered_data) { + DoHorizontalFilter_MIPSdspR2(data, width, height, stride, 0, height, + filtered_data); +} + +//------------------------------------------------------------------------------ +// Vertical filter. + +#define FILTER_LINE_BY_LINE do { \ + while (row < last_row) { \ + DO_PREDICT_LINE_VERTICAL(in, preds, out, width, 0); \ + ++row; \ + preds += stride; \ + in += stride; \ + out += stride; \ + } \ + } while (0) + +static WEBP_INLINE void DoVerticalFilter_MIPSdspR2(const uint8_t* in, + int width, int height, + int stride, + int row, int num_rows, + uint8_t* out) { + const uint8_t* preds; + const size_t start_offset = row * stride; + const int last_row = row + num_rows; + SANITY_CHECK(in, out); + in += start_offset; + out += start_offset; + preds = in; + + if (row == 0) { + // Very first top-left pixel is copied. + out[0] = in[0]; + // Rest of top scan-line is left-predicted. + PredictLine_MIPSdspR2(in + 1, out + 1, width - 1); + row = 1; + in += stride; + out += stride; + } else { + // We are starting from in-between. Make sure 'preds' points to prev row. + preds -= stride; + } + + // Filter line-by-line. + FILTER_LINE_BY_LINE; +} +#undef FILTER_LINE_BY_LINE + +static void VerticalFilter_MIPSdspR2(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + DoVerticalFilter_MIPSdspR2(data, width, height, stride, 0, height, + filtered_data); +} + +//------------------------------------------------------------------------------ +// Gradient filter. + +static int GradientPredictor_MIPSdspR2(uint8_t a, uint8_t b, uint8_t c) { + int temp0; + __asm__ volatile ( + "addu %[temp0], %[a], %[b] \n\t" + "subu %[temp0], %[temp0], %[c] \n\t" + "shll_s.w %[temp0], %[temp0], 23 \n\t" + "precrqu_s.qb.ph %[temp0], %[temp0], $zero \n\t" + "srl %[temp0], %[temp0], 24 \n\t" + : [temp0]"=&r"(temp0) + : [a]"r"(a),[b]"r"(b),[c]"r"(c) + ); + return temp0; +} + +#define FILTER_LINE_BY_LINE(PREDS, OPERATION) do { \ + while (row < last_row) { \ + int w; \ + PREDICT_LINE_ONE_PASS(in, PREDS - stride, out); \ + for (w = 1; w < width; ++w) { \ + const int pred = GradientPredictor_MIPSdspR2(PREDS[w - 1], \ + PREDS[w - stride], \ + PREDS[w - stride - 1]); \ + out[w] = in[w] OPERATION pred; \ + } \ + ++row; \ + in += stride; \ + out += stride; \ + } \ + } while (0) + +static void DoGradientFilter_MIPSdspR2(const uint8_t* in, + int width, int height, int stride, + int row, int num_rows, uint8_t* out) { + const uint8_t* preds; + const size_t start_offset = row * stride; + const int last_row = row + num_rows; + SANITY_CHECK(in, out); + in += start_offset; + out += start_offset; + preds = in; + + // left prediction for top scan-line + if (row == 0) { + out[0] = in[0]; + PredictLine_MIPSdspR2(in + 1, out + 1, width - 1); + row = 1; + preds += stride; + in += stride; + out += stride; + } + + // Filter line-by-line. + FILTER_LINE_BY_LINE(in, -); +} +#undef FILTER_LINE_BY_LINE + +static void GradientFilter_MIPSdspR2(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + DoGradientFilter_MIPSdspR2(data, width, height, stride, 0, height, + filtered_data); +} + +//------------------------------------------------------------------------------ + +static void HorizontalUnfilter_MIPSdspR2(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { + out[0] = in[0] + (prev == NULL ? 0 : prev[0]); + DO_PREDICT_LINE(in + 1, out + 1, width - 1, 1); +} + +static void VerticalUnfilter_MIPSdspR2(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { + if (prev == NULL) { + HorizontalUnfilter_MIPSdspR2(NULL, in, out, width); + } else { + DO_PREDICT_LINE_VERTICAL(in, prev, out, width, 1); + } +} + +static void GradientUnfilter_MIPSdspR2(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { + if (prev == NULL) { + HorizontalUnfilter_MIPSdspR2(NULL, in, out, width); + } else { + uint8_t top = prev[0], top_left = top, left = top; + int i; + for (i = 0; i < width; ++i) { + top = prev[i]; // need to read this first, in case prev==dst + left = in[i] + GradientPredictor_MIPSdspR2(left, top, top_left); + top_left = top; + out[i] = left; + } + } +} + +#undef DO_PREDICT_LINE_VERTICAL +#undef PREDICT_LINE_ONE_PASS +#undef DO_PREDICT_LINE +#undef SANITY_CHECK + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8FiltersInitMIPSdspR2(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInitMIPSdspR2(void) { + WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter_MIPSdspR2; + WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter_MIPSdspR2; + WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter_MIPSdspR2; + + WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter_MIPSdspR2; + WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter_MIPSdspR2; + WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter_MIPSdspR2; +} + +#else // !WEBP_USE_MIPS_DSP_R2 + +WEBP_DSP_INIT_STUB(VP8FiltersInitMIPSdspR2) + +#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/third-party/webp/libwebp/src/dsp/filters_msa.c b/third-party/webp/libwebp/src/dsp/filters_msa.c new file mode 100644 index 0000000000..14c437d141 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/filters_msa.c @@ -0,0 +1,202 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MSA variant of alpha filters +// +// Author: Prashant Patil (prashant.patil@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MSA) + +#include "src/dsp/msa_macro.h" + +#include + +static WEBP_INLINE void PredictLineInverse0(const uint8_t* src, + const uint8_t* pred, + uint8_t* dst, int length) { + v16u8 src0, pred0, dst0; + assert(length >= 0); + while (length >= 32) { + v16u8 src1, pred1, dst1; + LD_UB2(src, 16, src0, src1); + LD_UB2(pred, 16, pred0, pred1); + SUB2(src0, pred0, src1, pred1, dst0, dst1); + ST_UB2(dst0, dst1, dst, 16); + src += 32; + pred += 32; + dst += 32; + length -= 32; + } + if (length > 0) { + int i; + if (length >= 16) { + src0 = LD_UB(src); + pred0 = LD_UB(pred); + dst0 = src0 - pred0; + ST_UB(dst0, dst); + src += 16; + pred += 16; + dst += 16; + length -= 16; + } + for (i = 0; i < length; i++) { + dst[i] = src[i] - pred[i]; + } + } +} + +//------------------------------------------------------------------------------ +// Helpful macro. + +#define SANITY_CHECK(in, out) \ + assert(in != NULL); \ + assert(out != NULL); \ + assert(width > 0); \ + assert(height > 0); \ + assert(stride >= width); + +//------------------------------------------------------------------------------ +// Horrizontal filter + +static void HorizontalFilter_MSA(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + const uint8_t* preds = data; + const uint8_t* in = data; + uint8_t* out = filtered_data; + int row = 1; + SANITY_CHECK(in, out); + + // Leftmost pixel is the same as input for topmost scanline. + out[0] = in[0]; + PredictLineInverse0(in + 1, preds, out + 1, width - 1); + preds += stride; + in += stride; + out += stride; + // Filter line-by-line. + while (row < height) { + // Leftmost pixel is predicted from above. + PredictLineInverse0(in, preds - stride, out, 1); + PredictLineInverse0(in + 1, preds, out + 1, width - 1); + ++row; + preds += stride; + in += stride; + out += stride; + } +} + +//------------------------------------------------------------------------------ +// Gradient filter + +static WEBP_INLINE void PredictLineGradient(const uint8_t* pinput, + const uint8_t* ppred, + uint8_t* poutput, int stride, + int size) { + int w; + const v16i8 zero = { 0 }; + while (size >= 16) { + v16u8 pred0, dst0; + v8i16 a0, a1, b0, b1, c0, c1; + const v16u8 tmp0 = LD_UB(ppred - 1); + const v16u8 tmp1 = LD_UB(ppred - stride); + const v16u8 tmp2 = LD_UB(ppred - stride - 1); + const v16u8 src0 = LD_UB(pinput); + ILVRL_B2_SH(zero, tmp0, a0, a1); + ILVRL_B2_SH(zero, tmp1, b0, b1); + ILVRL_B2_SH(zero, tmp2, c0, c1); + ADD2(a0, b0, a1, b1, a0, a1); + SUB2(a0, c0, a1, c1, a0, a1); + CLIP_SH2_0_255(a0, a1); + pred0 = (v16u8)__msa_pckev_b((v16i8)a1, (v16i8)a0); + dst0 = src0 - pred0; + ST_UB(dst0, poutput); + ppred += 16; + pinput += 16; + poutput += 16; + size -= 16; + } + for (w = 0; w < size; ++w) { + const int pred = ppred[w - 1] + ppred[w - stride] - ppred[w - stride - 1]; + poutput[w] = pinput[w] - (pred < 0 ? 0 : pred > 255 ? 255 : pred); + } +} + + +static void GradientFilter_MSA(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + const uint8_t* in = data; + const uint8_t* preds = data; + uint8_t* out = filtered_data; + int row = 1; + SANITY_CHECK(in, out); + + // left prediction for top scan-line + out[0] = in[0]; + PredictLineInverse0(in + 1, preds, out + 1, width - 1); + preds += stride; + in += stride; + out += stride; + // Filter line-by-line. + while (row < height) { + out[0] = in[0] - preds[- stride]; + PredictLineGradient(preds + 1, in + 1, out + 1, stride, width - 1); + ++row; + preds += stride; + in += stride; + out += stride; + } +} + +//------------------------------------------------------------------------------ +// Vertical filter + +static void VerticalFilter_MSA(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + const uint8_t* in = data; + const uint8_t* preds = data; + uint8_t* out = filtered_data; + int row = 1; + SANITY_CHECK(in, out); + + // Very first top-left pixel is copied. + out[0] = in[0]; + // Rest of top scan-line is left-predicted. + PredictLineInverse0(in + 1, preds, out + 1, width - 1); + in += stride; + out += stride; + + // Filter line-by-line. + while (row < height) { + PredictLineInverse0(in, preds, out, width); + ++row; + preds += stride; + in += stride; + out += stride; + } +} + +#undef SANITY_CHECK + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8FiltersInitMSA(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInitMSA(void) { + WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter_MSA; + WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter_MSA; + WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter_MSA; +} + +#else // !WEBP_USE_MSA + +WEBP_DSP_INIT_STUB(VP8FiltersInitMSA) + +#endif // WEBP_USE_MSA diff --git a/third-party/webp/libwebp/src/dsp/filters_neon.c b/third-party/webp/libwebp/src/dsp/filters_neon.c new file mode 100644 index 0000000000..3e6a578ea7 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/filters_neon.c @@ -0,0 +1,329 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// NEON variant of alpha filters +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_NEON) + +#include +#include "src/dsp/neon.h" + +//------------------------------------------------------------------------------ +// Helpful macros. + +# define SANITY_CHECK(in, out) \ + assert(in != NULL); \ + assert(out != NULL); \ + assert(width > 0); \ + assert(height > 0); \ + assert(stride >= width); \ + assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ + (void)height; // Silence unused warning. + +// load eight u8 and widen to s16 +#define U8_TO_S16(A) vreinterpretq_s16_u16(vmovl_u8(A)) +#define LOAD_U8_TO_S16(A) U8_TO_S16(vld1_u8(A)) + +// shift left or right by N byte, inserting zeros +#define SHIFT_RIGHT_N_Q(A, N) vextq_u8((A), zero, (N)) +#define SHIFT_LEFT_N_Q(A, N) vextq_u8(zero, (A), (16 - (N)) % 16) + +// rotate left by N bytes +#define ROTATE_LEFT_N(A, N) vext_u8((A), (A), (N)) +// rotate right by N bytes +#define ROTATE_RIGHT_N(A, N) vext_u8((A), (A), (8 - (N)) % 8) + +static void PredictLine_NEON(const uint8_t* src, const uint8_t* pred, + uint8_t* dst, int length) { + int i; + assert(length >= 0); + for (i = 0; i + 16 <= length; i += 16) { + const uint8x16_t A = vld1q_u8(&src[i]); + const uint8x16_t B = vld1q_u8(&pred[i]); + const uint8x16_t C = vsubq_u8(A, B); + vst1q_u8(&dst[i], C); + } + for (; i < length; ++i) dst[i] = src[i] - pred[i]; +} + +// Special case for left-based prediction (when preds==dst-1 or preds==src-1). +static void PredictLineLeft_NEON(const uint8_t* src, uint8_t* dst, int length) { + PredictLine_NEON(src, src - 1, dst, length); +} + +//------------------------------------------------------------------------------ +// Horizontal filter. + +static WEBP_INLINE void DoHorizontalFilter_NEON(const uint8_t* in, + int width, int height, + int stride, + int row, int num_rows, + uint8_t* out) { + const size_t start_offset = row * stride; + const int last_row = row + num_rows; + SANITY_CHECK(in, out); + in += start_offset; + out += start_offset; + + if (row == 0) { + // Leftmost pixel is the same as input for topmost scanline. + out[0] = in[0]; + PredictLineLeft_NEON(in + 1, out + 1, width - 1); + row = 1; + in += stride; + out += stride; + } + + // Filter line-by-line. + while (row < last_row) { + // Leftmost pixel is predicted from above. + out[0] = in[0] - in[-stride]; + PredictLineLeft_NEON(in + 1, out + 1, width - 1); + ++row; + in += stride; + out += stride; + } +} + +static void HorizontalFilter_NEON(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + DoHorizontalFilter_NEON(data, width, height, stride, 0, height, + filtered_data); +} + +//------------------------------------------------------------------------------ +// Vertical filter. + +static WEBP_INLINE void DoVerticalFilter_NEON(const uint8_t* in, + int width, int height, int stride, + int row, int num_rows, + uint8_t* out) { + const size_t start_offset = row * stride; + const int last_row = row + num_rows; + SANITY_CHECK(in, out); + in += start_offset; + out += start_offset; + + if (row == 0) { + // Very first top-left pixel is copied. + out[0] = in[0]; + // Rest of top scan-line is left-predicted. + PredictLineLeft_NEON(in + 1, out + 1, width - 1); + row = 1; + in += stride; + out += stride; + } + + // Filter line-by-line. + while (row < last_row) { + PredictLine_NEON(in, in - stride, out, width); + ++row; + in += stride; + out += stride; + } +} + +static void VerticalFilter_NEON(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + DoVerticalFilter_NEON(data, width, height, stride, 0, height, + filtered_data); +} + +//------------------------------------------------------------------------------ +// Gradient filter. + +static WEBP_INLINE int GradientPredictor_C(uint8_t a, uint8_t b, uint8_t c) { + const int g = a + b - c; + return ((g & ~0xff) == 0) ? g : (g < 0) ? 0 : 255; // clip to 8bit +} + +static void GradientPredictDirect_NEON(const uint8_t* const row, + const uint8_t* const top, + uint8_t* const out, int length) { + int i; + for (i = 0; i + 8 <= length; i += 8) { + const uint8x8_t A = vld1_u8(&row[i - 1]); + const uint8x8_t B = vld1_u8(&top[i + 0]); + const int16x8_t C = vreinterpretq_s16_u16(vaddl_u8(A, B)); + const int16x8_t D = LOAD_U8_TO_S16(&top[i - 1]); + const uint8x8_t E = vqmovun_s16(vsubq_s16(C, D)); + const uint8x8_t F = vld1_u8(&row[i + 0]); + vst1_u8(&out[i], vsub_u8(F, E)); + } + for (; i < length; ++i) { + out[i] = row[i] - GradientPredictor_C(row[i - 1], top[i], top[i - 1]); + } +} + +static WEBP_INLINE void DoGradientFilter_NEON(const uint8_t* in, + int width, int height, + int stride, + int row, int num_rows, + uint8_t* out) { + const size_t start_offset = row * stride; + const int last_row = row + num_rows; + SANITY_CHECK(in, out); + in += start_offset; + out += start_offset; + + // left prediction for top scan-line + if (row == 0) { + out[0] = in[0]; + PredictLineLeft_NEON(in + 1, out + 1, width - 1); + row = 1; + in += stride; + out += stride; + } + + // Filter line-by-line. + while (row < last_row) { + out[0] = in[0] - in[-stride]; + GradientPredictDirect_NEON(in + 1, in + 1 - stride, out + 1, width - 1); + ++row; + in += stride; + out += stride; + } +} + +static void GradientFilter_NEON(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + DoGradientFilter_NEON(data, width, height, stride, 0, height, + filtered_data); +} + +#undef SANITY_CHECK + +//------------------------------------------------------------------------------ +// Inverse transforms + +static void HorizontalUnfilter_NEON(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { + int i; + const uint8x16_t zero = vdupq_n_u8(0); + uint8x16_t last; + out[0] = in[0] + (prev == NULL ? 0 : prev[0]); + if (width <= 1) return; + last = vsetq_lane_u8(out[0], zero, 0); + for (i = 1; i + 16 <= width; i += 16) { + const uint8x16_t A0 = vld1q_u8(&in[i]); + const uint8x16_t A1 = vaddq_u8(A0, last); + const uint8x16_t A2 = SHIFT_LEFT_N_Q(A1, 1); + const uint8x16_t A3 = vaddq_u8(A1, A2); + const uint8x16_t A4 = SHIFT_LEFT_N_Q(A3, 2); + const uint8x16_t A5 = vaddq_u8(A3, A4); + const uint8x16_t A6 = SHIFT_LEFT_N_Q(A5, 4); + const uint8x16_t A7 = vaddq_u8(A5, A6); + const uint8x16_t A8 = SHIFT_LEFT_N_Q(A7, 8); + const uint8x16_t A9 = vaddq_u8(A7, A8); + vst1q_u8(&out[i], A9); + last = SHIFT_RIGHT_N_Q(A9, 15); + } + for (; i < width; ++i) out[i] = in[i] + out[i - 1]; +} + +static void VerticalUnfilter_NEON(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { + if (prev == NULL) { + HorizontalUnfilter_NEON(NULL, in, out, width); + } else { + int i; + assert(width >= 0); + for (i = 0; i + 16 <= width; i += 16) { + const uint8x16_t A = vld1q_u8(&in[i]); + const uint8x16_t B = vld1q_u8(&prev[i]); + const uint8x16_t C = vaddq_u8(A, B); + vst1q_u8(&out[i], C); + } + for (; i < width; ++i) out[i] = in[i] + prev[i]; + } +} + +// GradientUnfilter_NEON is correct but slower than the C-version, +// at least on ARM64. For armv7, it's a wash. +// So best is to disable it for now, but keep the idea around... +#if !defined(USE_GRADIENT_UNFILTER) +#define USE_GRADIENT_UNFILTER 0 // ALTERNATE_CODE +#endif + +#if (USE_GRADIENT_UNFILTER == 1) +#define GRAD_PROCESS_LANE(L) do { \ + const uint8x8_t tmp1 = ROTATE_RIGHT_N(pred, 1); /* rotate predictor in */ \ + const int16x8_t tmp2 = vaddq_s16(BC, U8_TO_S16(tmp1)); \ + const uint8x8_t delta = vqmovun_s16(tmp2); \ + pred = vadd_u8(D, delta); \ + out = vext_u8(out, ROTATE_LEFT_N(pred, (L)), 1); \ +} while (0) + +static void GradientPredictInverse_NEON(const uint8_t* const in, + const uint8_t* const top, + uint8_t* const row, int length) { + if (length > 0) { + int i; + uint8x8_t pred = vdup_n_u8(row[-1]); // left sample + uint8x8_t out = vdup_n_u8(0); + for (i = 0; i + 8 <= length; i += 8) { + const int16x8_t B = LOAD_U8_TO_S16(&top[i + 0]); + const int16x8_t C = LOAD_U8_TO_S16(&top[i - 1]); + const int16x8_t BC = vsubq_s16(B, C); // unclipped gradient basis B - C + const uint8x8_t D = vld1_u8(&in[i]); // base input + GRAD_PROCESS_LANE(0); + GRAD_PROCESS_LANE(1); + GRAD_PROCESS_LANE(2); + GRAD_PROCESS_LANE(3); + GRAD_PROCESS_LANE(4); + GRAD_PROCESS_LANE(5); + GRAD_PROCESS_LANE(6); + GRAD_PROCESS_LANE(7); + vst1_u8(&row[i], out); + } + for (; i < length; ++i) { + row[i] = in[i] + GradientPredictor_C(row[i - 1], top[i], top[i - 1]); + } + } +} +#undef GRAD_PROCESS_LANE + +static void GradientUnfilter_NEON(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { + if (prev == NULL) { + HorizontalUnfilter_NEON(NULL, in, out, width); + } else { + out[0] = in[0] + prev[0]; // predict from above + GradientPredictInverse_NEON(in + 1, prev + 1, out + 1, width - 1); + } +} + +#endif // USE_GRADIENT_UNFILTER + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8FiltersInitNEON(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInitNEON(void) { + WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter_NEON; + WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter_NEON; +#if (USE_GRADIENT_UNFILTER == 1) + WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter_NEON; +#endif + + WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter_NEON; + WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter_NEON; + WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter_NEON; +} + +#else // !WEBP_USE_NEON + +WEBP_DSP_INIT_STUB(VP8FiltersInitNEON) + +#endif // WEBP_USE_NEON diff --git a/third-party/webp/libwebp/src/dsp/filters_sse2.c b/third-party/webp/libwebp/src/dsp/filters_sse2.c new file mode 100644 index 0000000000..5c33ec15e2 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/filters_sse2.c @@ -0,0 +1,340 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE2 variant of alpha filters +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE2) + +#include +#include +#include +#include + +//------------------------------------------------------------------------------ +// Helpful macro. + +# define SANITY_CHECK(in, out) \ + assert((in) != NULL); \ + assert((out) != NULL); \ + assert(width > 0); \ + assert(height > 0); \ + assert(stride >= width); \ + assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ + (void)height; // Silence unused warning. + +static void PredictLineTop_SSE2(const uint8_t* src, const uint8_t* pred, + uint8_t* dst, int length) { + int i; + const int max_pos = length & ~31; + assert(length >= 0); + for (i = 0; i < max_pos; i += 32) { + const __m128i A0 = _mm_loadu_si128((const __m128i*)&src[i + 0]); + const __m128i A1 = _mm_loadu_si128((const __m128i*)&src[i + 16]); + const __m128i B0 = _mm_loadu_si128((const __m128i*)&pred[i + 0]); + const __m128i B1 = _mm_loadu_si128((const __m128i*)&pred[i + 16]); + const __m128i C0 = _mm_sub_epi8(A0, B0); + const __m128i C1 = _mm_sub_epi8(A1, B1); + _mm_storeu_si128((__m128i*)&dst[i + 0], C0); + _mm_storeu_si128((__m128i*)&dst[i + 16], C1); + } + for (; i < length; ++i) dst[i] = src[i] - pred[i]; +} + +// Special case for left-based prediction (when preds==dst-1 or preds==src-1). +static void PredictLineLeft_SSE2(const uint8_t* src, uint8_t* dst, int length) { + int i; + const int max_pos = length & ~31; + assert(length >= 0); + for (i = 0; i < max_pos; i += 32) { + const __m128i A0 = _mm_loadu_si128((const __m128i*)(src + i + 0 )); + const __m128i B0 = _mm_loadu_si128((const __m128i*)(src + i + 0 - 1)); + const __m128i A1 = _mm_loadu_si128((const __m128i*)(src + i + 16 )); + const __m128i B1 = _mm_loadu_si128((const __m128i*)(src + i + 16 - 1)); + const __m128i C0 = _mm_sub_epi8(A0, B0); + const __m128i C1 = _mm_sub_epi8(A1, B1); + _mm_storeu_si128((__m128i*)(dst + i + 0), C0); + _mm_storeu_si128((__m128i*)(dst + i + 16), C1); + } + for (; i < length; ++i) dst[i] = src[i] - src[i - 1]; +} + +//------------------------------------------------------------------------------ +// Horizontal filter. + +static WEBP_INLINE void DoHorizontalFilter_SSE2(const uint8_t* in, + int width, int height, + int stride, + int row, int num_rows, + uint8_t* out) { + const size_t start_offset = row * stride; + const int last_row = row + num_rows; + SANITY_CHECK(in, out); + in += start_offset; + out += start_offset; + + if (row == 0) { + // Leftmost pixel is the same as input for topmost scanline. + out[0] = in[0]; + PredictLineLeft_SSE2(in + 1, out + 1, width - 1); + row = 1; + in += stride; + out += stride; + } + + // Filter line-by-line. + while (row < last_row) { + // Leftmost pixel is predicted from above. + out[0] = in[0] - in[-stride]; + PredictLineLeft_SSE2(in + 1, out + 1, width - 1); + ++row; + in += stride; + out += stride; + } +} + +//------------------------------------------------------------------------------ +// Vertical filter. + +static WEBP_INLINE void DoVerticalFilter_SSE2(const uint8_t* in, + int width, int height, int stride, + int row, int num_rows, + uint8_t* out) { + const size_t start_offset = row * stride; + const int last_row = row + num_rows; + SANITY_CHECK(in, out); + in += start_offset; + out += start_offset; + + if (row == 0) { + // Very first top-left pixel is copied. + out[0] = in[0]; + // Rest of top scan-line is left-predicted. + PredictLineLeft_SSE2(in + 1, out + 1, width - 1); + row = 1; + in += stride; + out += stride; + } + + // Filter line-by-line. + while (row < last_row) { + PredictLineTop_SSE2(in, in - stride, out, width); + ++row; + in += stride; + out += stride; + } +} + +//------------------------------------------------------------------------------ +// Gradient filter. + +static WEBP_INLINE int GradientPredictor_SSE2(uint8_t a, uint8_t b, uint8_t c) { + const int g = a + b - c; + return ((g & ~0xff) == 0) ? g : (g < 0) ? 0 : 255; // clip to 8bit +} + +static void GradientPredictDirect_SSE2(const uint8_t* const row, + const uint8_t* const top, + uint8_t* const out, int length) { + const int max_pos = length & ~7; + int i; + const __m128i zero = _mm_setzero_si128(); + for (i = 0; i < max_pos; i += 8) { + const __m128i A0 = _mm_loadl_epi64((const __m128i*)&row[i - 1]); + const __m128i B0 = _mm_loadl_epi64((const __m128i*)&top[i]); + const __m128i C0 = _mm_loadl_epi64((const __m128i*)&top[i - 1]); + const __m128i D = _mm_loadl_epi64((const __m128i*)&row[i]); + const __m128i A1 = _mm_unpacklo_epi8(A0, zero); + const __m128i B1 = _mm_unpacklo_epi8(B0, zero); + const __m128i C1 = _mm_unpacklo_epi8(C0, zero); + const __m128i E = _mm_add_epi16(A1, B1); + const __m128i F = _mm_sub_epi16(E, C1); + const __m128i G = _mm_packus_epi16(F, zero); + const __m128i H = _mm_sub_epi8(D, G); + _mm_storel_epi64((__m128i*)(out + i), H); + } + for (; i < length; ++i) { + const int delta = GradientPredictor_SSE2(row[i - 1], top[i], top[i - 1]); + out[i] = (uint8_t)(row[i] - delta); + } +} + +static WEBP_INLINE void DoGradientFilter_SSE2(const uint8_t* in, + int width, int height, int stride, + int row, int num_rows, + uint8_t* out) { + const size_t start_offset = row * stride; + const int last_row = row + num_rows; + SANITY_CHECK(in, out); + in += start_offset; + out += start_offset; + + // left prediction for top scan-line + if (row == 0) { + out[0] = in[0]; + PredictLineLeft_SSE2(in + 1, out + 1, width - 1); + row = 1; + in += stride; + out += stride; + } + + // Filter line-by-line. + while (row < last_row) { + out[0] = (uint8_t)(in[0] - in[-stride]); + GradientPredictDirect_SSE2(in + 1, in + 1 - stride, out + 1, width - 1); + ++row; + in += stride; + out += stride; + } +} + +#undef SANITY_CHECK + +//------------------------------------------------------------------------------ + +static void HorizontalFilter_SSE2(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + DoHorizontalFilter_SSE2(data, width, height, stride, 0, height, + filtered_data); +} + +static void VerticalFilter_SSE2(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + DoVerticalFilter_SSE2(data, width, height, stride, 0, height, filtered_data); +} + +static void GradientFilter_SSE2(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + DoGradientFilter_SSE2(data, width, height, stride, 0, height, filtered_data); +} + +//------------------------------------------------------------------------------ +// Inverse transforms + +static void HorizontalUnfilter_SSE2(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { + int i; + __m128i last; + out[0] = (uint8_t)(in[0] + (prev == NULL ? 0 : prev[0])); + if (width <= 1) return; + last = _mm_set_epi32(0, 0, 0, out[0]); + for (i = 1; i + 8 <= width; i += 8) { + const __m128i A0 = _mm_loadl_epi64((const __m128i*)(in + i)); + const __m128i A1 = _mm_add_epi8(A0, last); + const __m128i A2 = _mm_slli_si128(A1, 1); + const __m128i A3 = _mm_add_epi8(A1, A2); + const __m128i A4 = _mm_slli_si128(A3, 2); + const __m128i A5 = _mm_add_epi8(A3, A4); + const __m128i A6 = _mm_slli_si128(A5, 4); + const __m128i A7 = _mm_add_epi8(A5, A6); + _mm_storel_epi64((__m128i*)(out + i), A7); + last = _mm_srli_epi64(A7, 56); + } + for (; i < width; ++i) out[i] = (uint8_t)(in[i] + out[i - 1]); +} + +static void VerticalUnfilter_SSE2(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { + if (prev == NULL) { + HorizontalUnfilter_SSE2(NULL, in, out, width); + } else { + int i; + const int max_pos = width & ~31; + assert(width >= 0); + for (i = 0; i < max_pos; i += 32) { + const __m128i A0 = _mm_loadu_si128((const __m128i*)&in[i + 0]); + const __m128i A1 = _mm_loadu_si128((const __m128i*)&in[i + 16]); + const __m128i B0 = _mm_loadu_si128((const __m128i*)&prev[i + 0]); + const __m128i B1 = _mm_loadu_si128((const __m128i*)&prev[i + 16]); + const __m128i C0 = _mm_add_epi8(A0, B0); + const __m128i C1 = _mm_add_epi8(A1, B1); + _mm_storeu_si128((__m128i*)&out[i + 0], C0); + _mm_storeu_si128((__m128i*)&out[i + 16], C1); + } + for (; i < width; ++i) out[i] = (uint8_t)(in[i] + prev[i]); + } +} + +static void GradientPredictInverse_SSE2(const uint8_t* const in, + const uint8_t* const top, + uint8_t* const row, int length) { + if (length > 0) { + int i; + const int max_pos = length & ~7; + const __m128i zero = _mm_setzero_si128(); + __m128i A = _mm_set_epi32(0, 0, 0, row[-1]); // left sample + for (i = 0; i < max_pos; i += 8) { + const __m128i tmp0 = _mm_loadl_epi64((const __m128i*)&top[i]); + const __m128i tmp1 = _mm_loadl_epi64((const __m128i*)&top[i - 1]); + const __m128i B = _mm_unpacklo_epi8(tmp0, zero); + const __m128i C = _mm_unpacklo_epi8(tmp1, zero); + const __m128i D = _mm_loadl_epi64((const __m128i*)&in[i]); // base input + const __m128i E = _mm_sub_epi16(B, C); // unclipped gradient basis B - C + __m128i out = zero; // accumulator for output + __m128i mask_hi = _mm_set_epi32(0, 0, 0, 0xff); + int k = 8; + while (1) { + const __m128i tmp3 = _mm_add_epi16(A, E); // delta = A + B - C + const __m128i tmp4 = _mm_packus_epi16(tmp3, zero); // saturate delta + const __m128i tmp5 = _mm_add_epi8(tmp4, D); // add to in[] + A = _mm_and_si128(tmp5, mask_hi); // 1-complement clip + out = _mm_or_si128(out, A); // accumulate output + if (--k == 0) break; + A = _mm_slli_si128(A, 1); // rotate left sample + mask_hi = _mm_slli_si128(mask_hi, 1); // rotate mask + A = _mm_unpacklo_epi8(A, zero); // convert 8b->16b + } + A = _mm_srli_si128(A, 7); // prepare left sample for next iteration + _mm_storel_epi64((__m128i*)&row[i], out); + } + for (; i < length; ++i) { + const int delta = GradientPredictor_SSE2(row[i - 1], top[i], top[i - 1]); + row[i] = (uint8_t)(in[i] + delta); + } + } +} + +static void GradientUnfilter_SSE2(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { + if (prev == NULL) { + HorizontalUnfilter_SSE2(NULL, in, out, width); + } else { + out[0] = (uint8_t)(in[0] + prev[0]); // predict from above + GradientPredictInverse_SSE2(in + 1, prev + 1, out + 1, width - 1); + } +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8FiltersInitSSE2(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInitSSE2(void) { + WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter_SSE2; +#if defined(CHROMIUM) + // TODO(crbug.com/654974) + (void)VerticalUnfilter_SSE2; +#else + WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter_SSE2; +#endif + WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter_SSE2; + + WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter_SSE2; + WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter_SSE2; + WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter_SSE2; +} + +#else // !WEBP_USE_SSE2 + +WEBP_DSP_INIT_STUB(VP8FiltersInitSSE2) + +#endif // WEBP_USE_SSE2 diff --git a/third-party/webp/libwebp/src/dsp/lossless.c b/third-party/webp/libwebp/src/dsp/lossless.c new file mode 100644 index 0000000000..9f81209453 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/lossless.c @@ -0,0 +1,681 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Image transforms and color space conversion methods for lossless decoder. +// +// Authors: Vikas Arora (vikaas.arora@gmail.com) +// Jyrki Alakuijala (jyrki@google.com) +// Urvang Joshi (urvang@google.com) + +#include "src/dsp/dsp.h" + +#include +#include +#include +#include "src/dec/vp8li_dec.h" +#include "src/utils/endian_inl_utils.h" +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" + +//------------------------------------------------------------------------------ +// Image transforms. + +static WEBP_INLINE uint32_t Average2(uint32_t a0, uint32_t a1) { + return (((a0 ^ a1) & 0xfefefefeu) >> 1) + (a0 & a1); +} + +static WEBP_INLINE uint32_t Average3(uint32_t a0, uint32_t a1, uint32_t a2) { + return Average2(Average2(a0, a2), a1); +} + +static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1, + uint32_t a2, uint32_t a3) { + return Average2(Average2(a0, a1), Average2(a2, a3)); +} + +static WEBP_INLINE uint32_t Clip255(uint32_t a) { + if (a < 256) { + return a; + } + // return 0, when a is a negative integer. + // return 255, when a is positive. + return ~a >> 24; +} + +static WEBP_INLINE int AddSubtractComponentFull(int a, int b, int c) { + return Clip255((uint32_t)(a + b - c)); +} + +static WEBP_INLINE uint32_t ClampedAddSubtractFull(uint32_t c0, uint32_t c1, + uint32_t c2) { + const int a = AddSubtractComponentFull(c0 >> 24, c1 >> 24, c2 >> 24); + const int r = AddSubtractComponentFull((c0 >> 16) & 0xff, + (c1 >> 16) & 0xff, + (c2 >> 16) & 0xff); + const int g = AddSubtractComponentFull((c0 >> 8) & 0xff, + (c1 >> 8) & 0xff, + (c2 >> 8) & 0xff); + const int b = AddSubtractComponentFull(c0 & 0xff, c1 & 0xff, c2 & 0xff); + return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b; +} + +static WEBP_INLINE int AddSubtractComponentHalf(int a, int b) { + return Clip255((uint32_t)(a + (a - b) / 2)); +} + +static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1, + uint32_t c2) { + const uint32_t ave = Average2(c0, c1); + const int a = AddSubtractComponentHalf(ave >> 24, c2 >> 24); + const int r = AddSubtractComponentHalf((ave >> 16) & 0xff, (c2 >> 16) & 0xff); + const int g = AddSubtractComponentHalf((ave >> 8) & 0xff, (c2 >> 8) & 0xff); + const int b = AddSubtractComponentHalf((ave >> 0) & 0xff, (c2 >> 0) & 0xff); + return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b; +} + +// gcc <= 4.9 on ARM generates incorrect code in Select() when Sub3() is +// inlined. +#if defined(__arm__) && defined(__GNUC__) && LOCAL_GCC_VERSION <= 0x409 +# define LOCAL_INLINE __attribute__ ((noinline)) +#else +# define LOCAL_INLINE WEBP_INLINE +#endif + +static LOCAL_INLINE int Sub3(int a, int b, int c) { + const int pb = b - c; + const int pa = a - c; + return abs(pb) - abs(pa); +} + +#undef LOCAL_INLINE + +static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) { + const int pa_minus_pb = + Sub3((a >> 24) , (b >> 24) , (c >> 24) ) + + Sub3((a >> 16) & 0xff, (b >> 16) & 0xff, (c >> 16) & 0xff) + + Sub3((a >> 8) & 0xff, (b >> 8) & 0xff, (c >> 8) & 0xff) + + Sub3((a ) & 0xff, (b ) & 0xff, (c ) & 0xff); + return (pa_minus_pb <= 0) ? a : b; +} + +//------------------------------------------------------------------------------ +// Predictors + +uint32_t VP8LPredictor0_C(const uint32_t* const left, + const uint32_t* const top) { + (void)top; + (void)left; + return ARGB_BLACK; +} +uint32_t VP8LPredictor1_C(const uint32_t* const left, + const uint32_t* const top) { + (void)top; + return *left; +} +uint32_t VP8LPredictor2_C(const uint32_t* const left, + const uint32_t* const top) { + (void)left; + return top[0]; +} +uint32_t VP8LPredictor3_C(const uint32_t* const left, + const uint32_t* const top) { + (void)left; + return top[1]; +} +uint32_t VP8LPredictor4_C(const uint32_t* const left, + const uint32_t* const top) { + (void)left; + return top[-1]; +} +uint32_t VP8LPredictor5_C(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average3(*left, top[0], top[1]); + return pred; +} +uint32_t VP8LPredictor6_C(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average2(*left, top[-1]); + return pred; +} +uint32_t VP8LPredictor7_C(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average2(*left, top[0]); + return pred; +} +uint32_t VP8LPredictor8_C(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average2(top[-1], top[0]); + (void)left; + return pred; +} +uint32_t VP8LPredictor9_C(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average2(top[0], top[1]); + (void)left; + return pred; +} +uint32_t VP8LPredictor10_C(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average4(*left, top[-1], top[0], top[1]); + return pred; +} +uint32_t VP8LPredictor11_C(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Select(top[0], *left, top[-1]); + return pred; +} +uint32_t VP8LPredictor12_C(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = ClampedAddSubtractFull(*left, top[0], top[-1]); + return pred; +} +uint32_t VP8LPredictor13_C(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = ClampedAddSubtractHalf(*left, top[0], top[-1]); + return pred; +} + +static void PredictorAdd0_C(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int x; + (void)upper; + for (x = 0; x < num_pixels; ++x) out[x] = VP8LAddPixels(in[x], ARGB_BLACK); +} +static void PredictorAdd1_C(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + uint32_t left = out[-1]; + (void)upper; + for (i = 0; i < num_pixels; ++i) { + out[i] = left = VP8LAddPixels(in[i], left); + } +} +GENERATE_PREDICTOR_ADD(VP8LPredictor2_C, PredictorAdd2_C) +GENERATE_PREDICTOR_ADD(VP8LPredictor3_C, PredictorAdd3_C) +GENERATE_PREDICTOR_ADD(VP8LPredictor4_C, PredictorAdd4_C) +GENERATE_PREDICTOR_ADD(VP8LPredictor5_C, PredictorAdd5_C) +GENERATE_PREDICTOR_ADD(VP8LPredictor6_C, PredictorAdd6_C) +GENERATE_PREDICTOR_ADD(VP8LPredictor7_C, PredictorAdd7_C) +GENERATE_PREDICTOR_ADD(VP8LPredictor8_C, PredictorAdd8_C) +GENERATE_PREDICTOR_ADD(VP8LPredictor9_C, PredictorAdd9_C) +GENERATE_PREDICTOR_ADD(VP8LPredictor10_C, PredictorAdd10_C) +GENERATE_PREDICTOR_ADD(VP8LPredictor11_C, PredictorAdd11_C) +GENERATE_PREDICTOR_ADD(VP8LPredictor12_C, PredictorAdd12_C) +GENERATE_PREDICTOR_ADD(VP8LPredictor13_C, PredictorAdd13_C) + +//------------------------------------------------------------------------------ + +// Inverse prediction. +static void PredictorInverseTransform_C(const VP8LTransform* const transform, + int y_start, int y_end, + const uint32_t* in, uint32_t* out) { + const int width = transform->xsize_; + if (y_start == 0) { // First Row follows the L (mode=1) mode. + PredictorAdd0_C(in, NULL, 1, out); + PredictorAdd1_C(in + 1, NULL, width - 1, out + 1); + in += width; + out += width; + ++y_start; + } + + { + int y = y_start; + const int tile_width = 1 << transform->bits_; + const int mask = tile_width - 1; + const int tiles_per_row = VP8LSubSampleSize(width, transform->bits_); + const uint32_t* pred_mode_base = + transform->data_ + (y >> transform->bits_) * tiles_per_row; + + while (y < y_end) { + const uint32_t* pred_mode_src = pred_mode_base; + int x = 1; + // First pixel follows the T (mode=2) mode. + PredictorAdd2_C(in, out - width, 1, out); + // .. the rest: + while (x < width) { + const VP8LPredictorAddSubFunc pred_func = + VP8LPredictorsAdd[((*pred_mode_src++) >> 8) & 0xf]; + int x_end = (x & ~mask) + tile_width; + if (x_end > width) x_end = width; + pred_func(in + x, out + x - width, x_end - x, out + x); + x = x_end; + } + in += width; + out += width; + ++y; + if ((y & mask) == 0) { // Use the same mask, since tiles are squares. + pred_mode_base += tiles_per_row; + } + } + } +} + +// Add green to blue and red channels (i.e. perform the inverse transform of +// 'subtract green'). +void VP8LAddGreenToBlueAndRed_C(const uint32_t* src, int num_pixels, + uint32_t* dst) { + int i; + for (i = 0; i < num_pixels; ++i) { + const uint32_t argb = src[i]; + const uint32_t green = ((argb >> 8) & 0xff); + uint32_t red_blue = (argb & 0x00ff00ffu); + red_blue += (green << 16) | green; + red_blue &= 0x00ff00ffu; + dst[i] = (argb & 0xff00ff00u) | red_blue; + } +} + +static WEBP_INLINE int ColorTransformDelta(int8_t color_pred, + int8_t color) { + return ((int)color_pred * color) >> 5; +} + +static WEBP_INLINE void ColorCodeToMultipliers(uint32_t color_code, + VP8LMultipliers* const m) { + m->green_to_red_ = (color_code >> 0) & 0xff; + m->green_to_blue_ = (color_code >> 8) & 0xff; + m->red_to_blue_ = (color_code >> 16) & 0xff; +} + +void VP8LTransformColorInverse_C(const VP8LMultipliers* const m, + const uint32_t* src, int num_pixels, + uint32_t* dst) { + int i; + for (i = 0; i < num_pixels; ++i) { + const uint32_t argb = src[i]; + const int8_t green = (int8_t)(argb >> 8); + const uint32_t red = argb >> 16; + int new_red = red & 0xff; + int new_blue = argb & 0xff; + new_red += ColorTransformDelta((int8_t)m->green_to_red_, green); + new_red &= 0xff; + new_blue += ColorTransformDelta((int8_t)m->green_to_blue_, green); + new_blue += ColorTransformDelta((int8_t)m->red_to_blue_, (int8_t)new_red); + new_blue &= 0xff; + dst[i] = (argb & 0xff00ff00u) | (new_red << 16) | (new_blue); + } +} + +// Color space inverse transform. +static void ColorSpaceInverseTransform_C(const VP8LTransform* const transform, + int y_start, int y_end, + const uint32_t* src, uint32_t* dst) { + const int width = transform->xsize_; + const int tile_width = 1 << transform->bits_; + const int mask = tile_width - 1; + const int safe_width = width & ~mask; + const int remaining_width = width - safe_width; + const int tiles_per_row = VP8LSubSampleSize(width, transform->bits_); + int y = y_start; + const uint32_t* pred_row = + transform->data_ + (y >> transform->bits_) * tiles_per_row; + + while (y < y_end) { + const uint32_t* pred = pred_row; + VP8LMultipliers m = { 0, 0, 0 }; + const uint32_t* const src_safe_end = src + safe_width; + const uint32_t* const src_end = src + width; + while (src < src_safe_end) { + ColorCodeToMultipliers(*pred++, &m); + VP8LTransformColorInverse(&m, src, tile_width, dst); + src += tile_width; + dst += tile_width; + } + if (src < src_end) { // Left-overs using C-version. + ColorCodeToMultipliers(*pred++, &m); + VP8LTransformColorInverse(&m, src, remaining_width, dst); + src += remaining_width; + dst += remaining_width; + } + ++y; + if ((y & mask) == 0) pred_row += tiles_per_row; + } +} + +// Separate out pixels packed together using pixel-bundling. +// We define two methods for ARGB data (uint32_t) and alpha-only data (uint8_t). +#define COLOR_INDEX_INVERSE(FUNC_NAME, F_NAME, STATIC_DECL, TYPE, BIT_SUFFIX, \ + GET_INDEX, GET_VALUE) \ +static void F_NAME(const TYPE* src, const uint32_t* const color_map, \ + TYPE* dst, int y_start, int y_end, int width) { \ + int y; \ + for (y = y_start; y < y_end; ++y) { \ + int x; \ + for (x = 0; x < width; ++x) { \ + *dst++ = GET_VALUE(color_map[GET_INDEX(*src++)]); \ + } \ + } \ +} \ +STATIC_DECL void FUNC_NAME(const VP8LTransform* const transform, \ + int y_start, int y_end, const TYPE* src, \ + TYPE* dst) { \ + int y; \ + const int bits_per_pixel = 8 >> transform->bits_; \ + const int width = transform->xsize_; \ + const uint32_t* const color_map = transform->data_; \ + if (bits_per_pixel < 8) { \ + const int pixels_per_byte = 1 << transform->bits_; \ + const int count_mask = pixels_per_byte - 1; \ + const uint32_t bit_mask = (1 << bits_per_pixel) - 1; \ + for (y = y_start; y < y_end; ++y) { \ + uint32_t packed_pixels = 0; \ + int x; \ + for (x = 0; x < width; ++x) { \ + /* We need to load fresh 'packed_pixels' once every */ \ + /* 'pixels_per_byte' increments of x. Fortunately, pixels_per_byte */ \ + /* is a power of 2, so can just use a mask for that, instead of */ \ + /* decrementing a counter. */ \ + if ((x & count_mask) == 0) packed_pixels = GET_INDEX(*src++); \ + *dst++ = GET_VALUE(color_map[packed_pixels & bit_mask]); \ + packed_pixels >>= bits_per_pixel; \ + } \ + } \ + } else { \ + VP8LMapColor##BIT_SUFFIX(src, color_map, dst, y_start, y_end, width); \ + } \ +} + +COLOR_INDEX_INVERSE(ColorIndexInverseTransform_C, MapARGB_C, static, + uint32_t, 32b, VP8GetARGBIndex, VP8GetARGBValue) +COLOR_INDEX_INVERSE(VP8LColorIndexInverseTransformAlpha, MapAlpha_C, , + uint8_t, 8b, VP8GetAlphaIndex, VP8GetAlphaValue) + +#undef COLOR_INDEX_INVERSE + +void VP8LInverseTransform(const VP8LTransform* const transform, + int row_start, int row_end, + const uint32_t* const in, uint32_t* const out) { + const int width = transform->xsize_; + assert(row_start < row_end); + assert(row_end <= transform->ysize_); + switch (transform->type_) { + case SUBTRACT_GREEN_TRANSFORM: + VP8LAddGreenToBlueAndRed(in, (row_end - row_start) * width, out); + break; + case PREDICTOR_TRANSFORM: + PredictorInverseTransform_C(transform, row_start, row_end, in, out); + if (row_end != transform->ysize_) { + // The last predicted row in this iteration will be the top-pred row + // for the first row in next iteration. + memcpy(out - width, out + (row_end - row_start - 1) * width, + width * sizeof(*out)); + } + break; + case CROSS_COLOR_TRANSFORM: + ColorSpaceInverseTransform_C(transform, row_start, row_end, in, out); + break; + case COLOR_INDEXING_TRANSFORM: + if (in == out && transform->bits_ > 0) { + // Move packed pixels to the end of unpacked region, so that unpacking + // can occur seamlessly. + // Also, note that this is the only transform that applies on + // the effective width of VP8LSubSampleSize(xsize_, bits_). All other + // transforms work on effective width of xsize_. + const int out_stride = (row_end - row_start) * width; + const int in_stride = (row_end - row_start) * + VP8LSubSampleSize(transform->xsize_, transform->bits_); + uint32_t* const src = out + out_stride - in_stride; + memmove(src, out, in_stride * sizeof(*src)); + ColorIndexInverseTransform_C(transform, row_start, row_end, src, out); + } else { + ColorIndexInverseTransform_C(transform, row_start, row_end, in, out); + } + break; + } +} + +//------------------------------------------------------------------------------ +// Color space conversion. + +static int is_big_endian(void) { + static const union { + uint16_t w; + uint8_t b[2]; + } tmp = { 1 }; + return (tmp.b[0] != 1); +} + +void VP8LConvertBGRAToRGB_C(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const uint32_t* const src_end = src + num_pixels; + while (src < src_end) { + const uint32_t argb = *src++; + *dst++ = (argb >> 16) & 0xff; + *dst++ = (argb >> 8) & 0xff; + *dst++ = (argb >> 0) & 0xff; + } +} + +void VP8LConvertBGRAToRGBA_C(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const uint32_t* const src_end = src + num_pixels; + while (src < src_end) { + const uint32_t argb = *src++; + *dst++ = (argb >> 16) & 0xff; + *dst++ = (argb >> 8) & 0xff; + *dst++ = (argb >> 0) & 0xff; + *dst++ = (argb >> 24) & 0xff; + } +} + +void VP8LConvertBGRAToRGBA4444_C(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const uint32_t* const src_end = src + num_pixels; + while (src < src_end) { + const uint32_t argb = *src++; + const uint8_t rg = ((argb >> 16) & 0xf0) | ((argb >> 12) & 0xf); + const uint8_t ba = ((argb >> 0) & 0xf0) | ((argb >> 28) & 0xf); +#if (WEBP_SWAP_16BIT_CSP == 1) + *dst++ = ba; + *dst++ = rg; +#else + *dst++ = rg; + *dst++ = ba; +#endif + } +} + +void VP8LConvertBGRAToRGB565_C(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const uint32_t* const src_end = src + num_pixels; + while (src < src_end) { + const uint32_t argb = *src++; + const uint8_t rg = ((argb >> 16) & 0xf8) | ((argb >> 13) & 0x7); + const uint8_t gb = ((argb >> 5) & 0xe0) | ((argb >> 3) & 0x1f); +#if (WEBP_SWAP_16BIT_CSP == 1) + *dst++ = gb; + *dst++ = rg; +#else + *dst++ = rg; + *dst++ = gb; +#endif + } +} + +void VP8LConvertBGRAToBGR_C(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const uint32_t* const src_end = src + num_pixels; + while (src < src_end) { + const uint32_t argb = *src++; + *dst++ = (argb >> 0) & 0xff; + *dst++ = (argb >> 8) & 0xff; + *dst++ = (argb >> 16) & 0xff; + } +} + +static void CopyOrSwap(const uint32_t* src, int num_pixels, uint8_t* dst, + int swap_on_big_endian) { + if (is_big_endian() == swap_on_big_endian) { + const uint32_t* const src_end = src + num_pixels; + while (src < src_end) { + const uint32_t argb = *src++; + WebPUint32ToMem(dst, BSwap32(argb)); + dst += sizeof(argb); + } + } else { + memcpy(dst, src, num_pixels * sizeof(*src)); + } +} + +void VP8LConvertFromBGRA(const uint32_t* const in_data, int num_pixels, + WEBP_CSP_MODE out_colorspace, uint8_t* const rgba) { + switch (out_colorspace) { + case MODE_RGB: + VP8LConvertBGRAToRGB(in_data, num_pixels, rgba); + break; + case MODE_RGBA: + VP8LConvertBGRAToRGBA(in_data, num_pixels, rgba); + break; + case MODE_rgbA: + VP8LConvertBGRAToRGBA(in_data, num_pixels, rgba); + WebPApplyAlphaMultiply(rgba, 0, num_pixels, 1, 0); + break; + case MODE_BGR: + VP8LConvertBGRAToBGR(in_data, num_pixels, rgba); + break; + case MODE_BGRA: + CopyOrSwap(in_data, num_pixels, rgba, 1); + break; + case MODE_bgrA: + CopyOrSwap(in_data, num_pixels, rgba, 1); + WebPApplyAlphaMultiply(rgba, 0, num_pixels, 1, 0); + break; + case MODE_ARGB: + CopyOrSwap(in_data, num_pixels, rgba, 0); + break; + case MODE_Argb: + CopyOrSwap(in_data, num_pixels, rgba, 0); + WebPApplyAlphaMultiply(rgba, 1, num_pixels, 1, 0); + break; + case MODE_RGBA_4444: + VP8LConvertBGRAToRGBA4444(in_data, num_pixels, rgba); + break; + case MODE_rgbA_4444: + VP8LConvertBGRAToRGBA4444(in_data, num_pixels, rgba); + WebPApplyAlphaMultiply4444(rgba, num_pixels, 1, 0); + break; + case MODE_RGB_565: + VP8LConvertBGRAToRGB565(in_data, num_pixels, rgba); + break; + default: + assert(0); // Code flow should not reach here. + } +} + +//------------------------------------------------------------------------------ + +VP8LProcessDecBlueAndRedFunc VP8LAddGreenToBlueAndRed; +VP8LPredictorAddSubFunc VP8LPredictorsAdd[16]; +VP8LPredictorFunc VP8LPredictors[16]; + +// exposed plain-C implementations +VP8LPredictorAddSubFunc VP8LPredictorsAdd_C[16]; + +VP8LTransformColorInverseFunc VP8LTransformColorInverse; + +VP8LConvertFunc VP8LConvertBGRAToRGB; +VP8LConvertFunc VP8LConvertBGRAToRGBA; +VP8LConvertFunc VP8LConvertBGRAToRGBA4444; +VP8LConvertFunc VP8LConvertBGRAToRGB565; +VP8LConvertFunc VP8LConvertBGRAToBGR; + +VP8LMapARGBFunc VP8LMapColor32b; +VP8LMapAlphaFunc VP8LMapColor8b; + +extern VP8CPUInfo VP8GetCPUInfo; +extern void VP8LDspInitSSE2(void); +extern void VP8LDspInitSSE41(void); +extern void VP8LDspInitNEON(void); +extern void VP8LDspInitMIPSdspR2(void); +extern void VP8LDspInitMSA(void); + +#define COPY_PREDICTOR_ARRAY(IN, OUT) do { \ + (OUT)[0] = IN##0_C; \ + (OUT)[1] = IN##1_C; \ + (OUT)[2] = IN##2_C; \ + (OUT)[3] = IN##3_C; \ + (OUT)[4] = IN##4_C; \ + (OUT)[5] = IN##5_C; \ + (OUT)[6] = IN##6_C; \ + (OUT)[7] = IN##7_C; \ + (OUT)[8] = IN##8_C; \ + (OUT)[9] = IN##9_C; \ + (OUT)[10] = IN##10_C; \ + (OUT)[11] = IN##11_C; \ + (OUT)[12] = IN##12_C; \ + (OUT)[13] = IN##13_C; \ + (OUT)[14] = IN##0_C; /* <- padding security sentinels*/ \ + (OUT)[15] = IN##0_C; \ +} while (0); + +WEBP_DSP_INIT_FUNC(VP8LDspInit) { + COPY_PREDICTOR_ARRAY(VP8LPredictor, VP8LPredictors) + COPY_PREDICTOR_ARRAY(PredictorAdd, VP8LPredictorsAdd) + COPY_PREDICTOR_ARRAY(PredictorAdd, VP8LPredictorsAdd_C) + +#if !WEBP_NEON_OMIT_C_CODE + VP8LAddGreenToBlueAndRed = VP8LAddGreenToBlueAndRed_C; + + VP8LTransformColorInverse = VP8LTransformColorInverse_C; + + VP8LConvertBGRAToRGBA = VP8LConvertBGRAToRGBA_C; + VP8LConvertBGRAToRGB = VP8LConvertBGRAToRGB_C; + VP8LConvertBGRAToBGR = VP8LConvertBGRAToBGR_C; +#endif + + VP8LConvertBGRAToRGBA4444 = VP8LConvertBGRAToRGBA4444_C; + VP8LConvertBGRAToRGB565 = VP8LConvertBGRAToRGB565_C; + + VP8LMapColor32b = MapARGB_C; + VP8LMapColor8b = MapAlpha_C; + + // If defined, use CPUInfo() to overwrite some pointers with faster versions. + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_HAVE_SSE2) + if (VP8GetCPUInfo(kSSE2)) { + VP8LDspInitSSE2(); +#if defined(WEBP_HAVE_SSE41) + if (VP8GetCPUInfo(kSSE4_1)) { + VP8LDspInitSSE41(); + } +#endif + } +#endif +#if defined(WEBP_USE_MIPS_DSP_R2) + if (VP8GetCPUInfo(kMIPSdspR2)) { + VP8LDspInitMIPSdspR2(); + } +#endif +#if defined(WEBP_USE_MSA) + if (VP8GetCPUInfo(kMSA)) { + VP8LDspInitMSA(); + } +#endif + } + +#if defined(WEBP_HAVE_NEON) + if (WEBP_NEON_OMIT_C_CODE || + (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) { + VP8LDspInitNEON(); + } +#endif + + assert(VP8LAddGreenToBlueAndRed != NULL); + assert(VP8LTransformColorInverse != NULL); + assert(VP8LConvertBGRAToRGBA != NULL); + assert(VP8LConvertBGRAToRGB != NULL); + assert(VP8LConvertBGRAToBGR != NULL); + assert(VP8LConvertBGRAToRGBA4444 != NULL); + assert(VP8LConvertBGRAToRGB565 != NULL); + assert(VP8LMapColor32b != NULL); + assert(VP8LMapColor8b != NULL); +} +#undef COPY_PREDICTOR_ARRAY + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/src/dsp/lossless.h b/third-party/webp/libwebp/src/dsp/lossless.h new file mode 100644 index 0000000000..0bf10a1a3d --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/lossless.h @@ -0,0 +1,259 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Image transforms and color space conversion methods for lossless decoder. +// +// Authors: Vikas Arora (vikaas.arora@gmail.com) +// Jyrki Alakuijala (jyrki@google.com) + +#ifndef WEBP_DSP_LOSSLESS_H_ +#define WEBP_DSP_LOSSLESS_H_ + +#include "src/webp/types.h" +#include "src/webp/decode.h" + +#include "src/enc/histogram_enc.h" +#include "src/utils/utils.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//------------------------------------------------------------------------------ +// Decoding + +typedef uint32_t (*VP8LPredictorFunc)(const uint32_t* const left, + const uint32_t* const top); +extern VP8LPredictorFunc VP8LPredictors[16]; + +uint32_t VP8LPredictor0_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor1_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor2_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor3_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor4_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor5_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor6_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor7_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor8_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor9_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor10_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor11_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor12_C(const uint32_t* const left, + const uint32_t* const top); +uint32_t VP8LPredictor13_C(const uint32_t* const left, + const uint32_t* const top); + +// These Add/Sub function expects upper[-1] and out[-1] to be readable. +typedef void (*VP8LPredictorAddSubFunc)(const uint32_t* in, + const uint32_t* upper, int num_pixels, + uint32_t* out); +extern VP8LPredictorAddSubFunc VP8LPredictorsAdd[16]; +extern VP8LPredictorAddSubFunc VP8LPredictorsAdd_C[16]; + +typedef void (*VP8LProcessDecBlueAndRedFunc)(const uint32_t* src, + int num_pixels, uint32_t* dst); +extern VP8LProcessDecBlueAndRedFunc VP8LAddGreenToBlueAndRed; + +typedef struct { + // Note: the members are uint8_t, so that any negative values are + // automatically converted to "mod 256" values. + uint8_t green_to_red_; + uint8_t green_to_blue_; + uint8_t red_to_blue_; +} VP8LMultipliers; +typedef void (*VP8LTransformColorInverseFunc)(const VP8LMultipliers* const m, + const uint32_t* src, + int num_pixels, uint32_t* dst); +extern VP8LTransformColorInverseFunc VP8LTransformColorInverse; + +struct VP8LTransform; // Defined in dec/vp8li.h. + +// Performs inverse transform of data given transform information, start and end +// rows. Transform will be applied to rows [row_start, row_end[. +// The *in and *out pointers refer to source and destination data respectively +// corresponding to the intermediate row (row_start). +void VP8LInverseTransform(const struct VP8LTransform* const transform, + int row_start, int row_end, + const uint32_t* const in, uint32_t* const out); + +// Color space conversion. +typedef void (*VP8LConvertFunc)(const uint32_t* src, int num_pixels, + uint8_t* dst); +extern VP8LConvertFunc VP8LConvertBGRAToRGB; +extern VP8LConvertFunc VP8LConvertBGRAToRGBA; +extern VP8LConvertFunc VP8LConvertBGRAToRGBA4444; +extern VP8LConvertFunc VP8LConvertBGRAToRGB565; +extern VP8LConvertFunc VP8LConvertBGRAToBGR; + +// Converts from BGRA to other color spaces. +void VP8LConvertFromBGRA(const uint32_t* const in_data, int num_pixels, + WEBP_CSP_MODE out_colorspace, uint8_t* const rgba); + +typedef void (*VP8LMapARGBFunc)(const uint32_t* src, + const uint32_t* const color_map, + uint32_t* dst, int y_start, + int y_end, int width); +typedef void (*VP8LMapAlphaFunc)(const uint8_t* src, + const uint32_t* const color_map, + uint8_t* dst, int y_start, + int y_end, int width); + +extern VP8LMapARGBFunc VP8LMapColor32b; +extern VP8LMapAlphaFunc VP8LMapColor8b; + +// Similar to the static method ColorIndexInverseTransform() that is part of +// lossless.c, but used only for alpha decoding. It takes uint8_t (rather than +// uint32_t) arguments for 'src' and 'dst'. +void VP8LColorIndexInverseTransformAlpha( + const struct VP8LTransform* const transform, int y_start, int y_end, + const uint8_t* src, uint8_t* dst); + +// Expose some C-only fallback functions +void VP8LTransformColorInverse_C(const VP8LMultipliers* const m, + const uint32_t* src, int num_pixels, + uint32_t* dst); + +void VP8LConvertBGRAToRGB_C(const uint32_t* src, int num_pixels, uint8_t* dst); +void VP8LConvertBGRAToRGBA_C(const uint32_t* src, int num_pixels, uint8_t* dst); +void VP8LConvertBGRAToRGBA4444_C(const uint32_t* src, + int num_pixels, uint8_t* dst); +void VP8LConvertBGRAToRGB565_C(const uint32_t* src, + int num_pixels, uint8_t* dst); +void VP8LConvertBGRAToBGR_C(const uint32_t* src, int num_pixels, uint8_t* dst); +void VP8LAddGreenToBlueAndRed_C(const uint32_t* src, int num_pixels, + uint32_t* dst); + +// Must be called before calling any of the above methods. +void VP8LDspInit(void); + +//------------------------------------------------------------------------------ +// Encoding + +typedef void (*VP8LProcessEncBlueAndRedFunc)(uint32_t* dst, int num_pixels); +extern VP8LProcessEncBlueAndRedFunc VP8LSubtractGreenFromBlueAndRed; +typedef void (*VP8LTransformColorFunc)(const VP8LMultipliers* const m, + uint32_t* dst, int num_pixels); +extern VP8LTransformColorFunc VP8LTransformColor; +typedef void (*VP8LCollectColorBlueTransformsFunc)( + const uint32_t* argb, int stride, + int tile_width, int tile_height, + int green_to_blue, int red_to_blue, int histo[]); +extern VP8LCollectColorBlueTransformsFunc VP8LCollectColorBlueTransforms; + +typedef void (*VP8LCollectColorRedTransformsFunc)( + const uint32_t* argb, int stride, + int tile_width, int tile_height, + int green_to_red, int histo[]); +extern VP8LCollectColorRedTransformsFunc VP8LCollectColorRedTransforms; + +// Expose some C-only fallback functions +void VP8LTransformColor_C(const VP8LMultipliers* const m, + uint32_t* data, int num_pixels); +void VP8LSubtractGreenFromBlueAndRed_C(uint32_t* argb_data, int num_pixels); +void VP8LCollectColorRedTransforms_C(const uint32_t* argb, int stride, + int tile_width, int tile_height, + int green_to_red, int histo[]); +void VP8LCollectColorBlueTransforms_C(const uint32_t* argb, int stride, + int tile_width, int tile_height, + int green_to_blue, int red_to_blue, + int histo[]); + +extern VP8LPredictorAddSubFunc VP8LPredictorsSub[16]; +extern VP8LPredictorAddSubFunc VP8LPredictorsSub_C[16]; + +// ----------------------------------------------------------------------------- +// Huffman-cost related functions. + +typedef uint32_t (*VP8LCostFunc)(const uint32_t* population, int length); +typedef uint32_t (*VP8LCostCombinedFunc)(const uint32_t* X, const uint32_t* Y, + int length); +typedef float (*VP8LCombinedShannonEntropyFunc)(const int X[256], + const int Y[256]); + +extern VP8LCostFunc VP8LExtraCost; +extern VP8LCostCombinedFunc VP8LExtraCostCombined; +extern VP8LCombinedShannonEntropyFunc VP8LCombinedShannonEntropy; + +typedef struct { // small struct to hold counters + int counts[2]; // index: 0=zero streak, 1=non-zero streak + int streaks[2][2]; // [zero/non-zero][streak<3 / streak>=3] +} VP8LStreaks; + +typedef struct { // small struct to hold bit entropy results + float entropy; // entropy + uint32_t sum; // sum of the population + int nonzeros; // number of non-zero elements in the population + uint32_t max_val; // maximum value in the population + uint32_t nonzero_code; // index of the last non-zero in the population +} VP8LBitEntropy; + +void VP8LBitEntropyInit(VP8LBitEntropy* const entropy); + +// Get the combined symbol bit entropy and Huffman cost stats for the +// distributions 'X' and 'Y'. Those results can then be refined according to +// codec specific heuristics. +typedef void (*VP8LGetCombinedEntropyUnrefinedFunc)( + const uint32_t X[], const uint32_t Y[], int length, + VP8LBitEntropy* const bit_entropy, VP8LStreaks* const stats); +extern VP8LGetCombinedEntropyUnrefinedFunc VP8LGetCombinedEntropyUnrefined; + +// Get the entropy for the distribution 'X'. +typedef void (*VP8LGetEntropyUnrefinedFunc)(const uint32_t X[], int length, + VP8LBitEntropy* const bit_entropy, + VP8LStreaks* const stats); +extern VP8LGetEntropyUnrefinedFunc VP8LGetEntropyUnrefined; + +void VP8LBitsEntropyUnrefined(const uint32_t* const array, int n, + VP8LBitEntropy* const entropy); + +typedef void (*VP8LAddVectorFunc)(const uint32_t* a, const uint32_t* b, + uint32_t* out, int size); +extern VP8LAddVectorFunc VP8LAddVector; +typedef void (*VP8LAddVectorEqFunc)(const uint32_t* a, uint32_t* out, int size); +extern VP8LAddVectorEqFunc VP8LAddVectorEq; +void VP8LHistogramAdd(const VP8LHistogram* const a, + const VP8LHistogram* const b, + VP8LHistogram* const out); + +// ----------------------------------------------------------------------------- +// PrefixEncode() + +typedef int (*VP8LVectorMismatchFunc)(const uint32_t* const array1, + const uint32_t* const array2, int length); +// Returns the first index where array1 and array2 are different. +extern VP8LVectorMismatchFunc VP8LVectorMismatch; + +typedef void (*VP8LBundleColorMapFunc)(const uint8_t* const row, int width, + int xbits, uint32_t* dst); +extern VP8LBundleColorMapFunc VP8LBundleColorMap; +void VP8LBundleColorMap_C(const uint8_t* const row, int width, int xbits, + uint32_t* dst); + +// Must be called before calling any of the above methods. +void VP8LEncDspInit(void); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_DSP_LOSSLESS_H_ diff --git a/third-party/webp/libwebp/src/dsp/lossless_common.h b/third-party/webp/libwebp/src/dsp/lossless_common.h new file mode 100644 index 0000000000..d6139b2b57 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/lossless_common.h @@ -0,0 +1,191 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Image transforms and color space conversion methods for lossless decoder. +// +// Authors: Vikas Arora (vikaas.arora@gmail.com) +// Jyrki Alakuijala (jyrki@google.com) +// Vincent Rabaud (vrabaud@google.com) + +#ifndef WEBP_DSP_LOSSLESS_COMMON_H_ +#define WEBP_DSP_LOSSLESS_COMMON_H_ + +#include "src/dsp/cpu.h" +#include "src/utils/utils.h" +#include "src/webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//------------------------------------------------------------------------------ +// Decoding + +// color mapping related functions. +static WEBP_INLINE uint32_t VP8GetARGBIndex(uint32_t idx) { + return (idx >> 8) & 0xff; +} + +static WEBP_INLINE uint8_t VP8GetAlphaIndex(uint8_t idx) { + return idx; +} + +static WEBP_INLINE uint32_t VP8GetARGBValue(uint32_t val) { + return val; +} + +static WEBP_INLINE uint8_t VP8GetAlphaValue(uint32_t val) { + return (val >> 8) & 0xff; +} + +//------------------------------------------------------------------------------ +// Misc methods. + +// Computes sampled size of 'size' when sampling using 'sampling bits'. +static WEBP_INLINE uint32_t VP8LSubSampleSize(uint32_t size, + uint32_t sampling_bits) { + return (size + (1 << sampling_bits) - 1) >> sampling_bits; +} + +// Converts near lossless quality into max number of bits shaved off. +static WEBP_INLINE int VP8LNearLosslessBits(int near_lossless_quality) { + // 100 -> 0 + // 80..99 -> 1 + // 60..79 -> 2 + // 40..59 -> 3 + // 20..39 -> 4 + // 0..19 -> 5 + return 5 - near_lossless_quality / 20; +} + +// ----------------------------------------------------------------------------- +// Faster logarithm for integers. Small values use a look-up table. + +// The threshold till approximate version of log_2 can be used. +// Practically, we can get rid of the call to log() as the two values match to +// very high degree (the ratio of these two is 0.99999x). +// Keeping a high threshold for now. +#define APPROX_LOG_WITH_CORRECTION_MAX 65536 +#define APPROX_LOG_MAX 4096 +#define LOG_2_RECIPROCAL 1.44269504088896338700465094007086 +#define LOG_LOOKUP_IDX_MAX 256 +extern const float kLog2Table[LOG_LOOKUP_IDX_MAX]; +extern const float kSLog2Table[LOG_LOOKUP_IDX_MAX]; +typedef float (*VP8LFastLog2SlowFunc)(uint32_t v); + +extern VP8LFastLog2SlowFunc VP8LFastLog2Slow; +extern VP8LFastLog2SlowFunc VP8LFastSLog2Slow; + +static WEBP_INLINE float VP8LFastLog2(uint32_t v) { + return (v < LOG_LOOKUP_IDX_MAX) ? kLog2Table[v] : VP8LFastLog2Slow(v); +} +// Fast calculation of v * log2(v) for integer input. +static WEBP_INLINE float VP8LFastSLog2(uint32_t v) { + return (v < LOG_LOOKUP_IDX_MAX) ? kSLog2Table[v] : VP8LFastSLog2Slow(v); +} + +// ----------------------------------------------------------------------------- +// PrefixEncode() + +// Splitting of distance and length codes into prefixes and +// extra bits. The prefixes are encoded with an entropy code +// while the extra bits are stored just as normal bits. +static WEBP_INLINE void VP8LPrefixEncodeBitsNoLUT(int distance, int* const code, + int* const extra_bits) { + const int highest_bit = BitsLog2Floor(--distance); + const int second_highest_bit = (distance >> (highest_bit - 1)) & 1; + *extra_bits = highest_bit - 1; + *code = 2 * highest_bit + second_highest_bit; +} + +static WEBP_INLINE void VP8LPrefixEncodeNoLUT(int distance, int* const code, + int* const extra_bits, + int* const extra_bits_value) { + const int highest_bit = BitsLog2Floor(--distance); + const int second_highest_bit = (distance >> (highest_bit - 1)) & 1; + *extra_bits = highest_bit - 1; + *extra_bits_value = distance & ((1 << *extra_bits) - 1); + *code = 2 * highest_bit + second_highest_bit; +} + +#define PREFIX_LOOKUP_IDX_MAX 512 +typedef struct { + int8_t code_; + int8_t extra_bits_; +} VP8LPrefixCode; + +// These tables are derived using VP8LPrefixEncodeNoLUT. +extern const VP8LPrefixCode kPrefixEncodeCode[PREFIX_LOOKUP_IDX_MAX]; +extern const uint8_t kPrefixEncodeExtraBitsValue[PREFIX_LOOKUP_IDX_MAX]; +static WEBP_INLINE void VP8LPrefixEncodeBits(int distance, int* const code, + int* const extra_bits) { + if (distance < PREFIX_LOOKUP_IDX_MAX) { + const VP8LPrefixCode prefix_code = kPrefixEncodeCode[distance]; + *code = prefix_code.code_; + *extra_bits = prefix_code.extra_bits_; + } else { + VP8LPrefixEncodeBitsNoLUT(distance, code, extra_bits); + } +} + +static WEBP_INLINE void VP8LPrefixEncode(int distance, int* const code, + int* const extra_bits, + int* const extra_bits_value) { + if (distance < PREFIX_LOOKUP_IDX_MAX) { + const VP8LPrefixCode prefix_code = kPrefixEncodeCode[distance]; + *code = prefix_code.code_; + *extra_bits = prefix_code.extra_bits_; + *extra_bits_value = kPrefixEncodeExtraBitsValue[distance]; + } else { + VP8LPrefixEncodeNoLUT(distance, code, extra_bits, extra_bits_value); + } +} + +// Sum of each component, mod 256. +static WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW WEBP_INLINE +uint32_t VP8LAddPixels(uint32_t a, uint32_t b) { + const uint32_t alpha_and_green = (a & 0xff00ff00u) + (b & 0xff00ff00u); + const uint32_t red_and_blue = (a & 0x00ff00ffu) + (b & 0x00ff00ffu); + return (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu); +} + +// Difference of each component, mod 256. +static WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW WEBP_INLINE +uint32_t VP8LSubPixels(uint32_t a, uint32_t b) { + const uint32_t alpha_and_green = + 0x00ff00ffu + (a & 0xff00ff00u) - (b & 0xff00ff00u); + const uint32_t red_and_blue = + 0xff00ff00u + (a & 0x00ff00ffu) - (b & 0x00ff00ffu); + return (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu); +} + +//------------------------------------------------------------------------------ +// Transform-related functions used in both encoding and decoding. + +// Macros used to create a batch predictor that iteratively uses a +// one-pixel predictor. + +// The predictor is added to the output pixel (which +// is therefore considered as a residual) to get the final prediction. +#define GENERATE_PREDICTOR_ADD(PREDICTOR, PREDICTOR_ADD) \ +static void PREDICTOR_ADD(const uint32_t* in, const uint32_t* upper, \ + int num_pixels, uint32_t* out) { \ + int x; \ + assert(upper != NULL); \ + for (x = 0; x < num_pixels; ++x) { \ + const uint32_t pred = (PREDICTOR)(&out[x - 1], upper + x); \ + out[x] = VP8LAddPixels(in[x], pred); \ + } \ +} + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_DSP_LOSSLESS_COMMON_H_ diff --git a/third-party/webp/libwebp/src/dsp/lossless_enc.c b/third-party/webp/libwebp/src/dsp/lossless_enc.c new file mode 100644 index 0000000000..997d56c2ad --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/lossless_enc.c @@ -0,0 +1,954 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Image transform methods for lossless encoder. +// +// Authors: Vikas Arora (vikaas.arora@gmail.com) +// Jyrki Alakuijala (jyrki@google.com) +// Urvang Joshi (urvang@google.com) + +#include "src/dsp/dsp.h" + +#include +#include +#include +#include "src/dec/vp8li_dec.h" +#include "src/utils/endian_inl_utils.h" +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" +#include "src/dsp/yuv.h" + +// lookup table for small values of log2(int) +const float kLog2Table[LOG_LOOKUP_IDX_MAX] = { + 0.0000000000000000f, 0.0000000000000000f, + 1.0000000000000000f, 1.5849625007211560f, + 2.0000000000000000f, 2.3219280948873621f, + 2.5849625007211560f, 2.8073549220576041f, + 3.0000000000000000f, 3.1699250014423121f, + 3.3219280948873621f, 3.4594316186372973f, + 3.5849625007211560f, 3.7004397181410921f, + 3.8073549220576041f, 3.9068905956085187f, + 4.0000000000000000f, 4.0874628412503390f, + 4.1699250014423121f, 4.2479275134435852f, + 4.3219280948873626f, 4.3923174227787606f, + 4.4594316186372973f, 4.5235619560570130f, + 4.5849625007211560f, 4.6438561897747243f, + 4.7004397181410917f, 4.7548875021634682f, + 4.8073549220576037f, 4.8579809951275718f, + 4.9068905956085187f, 4.9541963103868749f, + 5.0000000000000000f, 5.0443941193584533f, + 5.0874628412503390f, 5.1292830169449663f, + 5.1699250014423121f, 5.2094533656289501f, + 5.2479275134435852f, 5.2854022188622487f, + 5.3219280948873626f, 5.3575520046180837f, + 5.3923174227787606f, 5.4262647547020979f, + 5.4594316186372973f, 5.4918530963296747f, + 5.5235619560570130f, 5.5545888516776376f, + 5.5849625007211560f, 5.6147098441152083f, + 5.6438561897747243f, 5.6724253419714951f, + 5.7004397181410917f, 5.7279204545631987f, + 5.7548875021634682f, 5.7813597135246599f, + 5.8073549220576037f, 5.8328900141647412f, + 5.8579809951275718f, 5.8826430493618415f, + 5.9068905956085187f, 5.9307373375628866f, + 5.9541963103868749f, 5.9772799234999167f, + 6.0000000000000000f, 6.0223678130284543f, + 6.0443941193584533f, 6.0660891904577720f, + 6.0874628412503390f, 6.1085244567781691f, + 6.1292830169449663f, 6.1497471195046822f, + 6.1699250014423121f, 6.1898245588800175f, + 6.2094533656289501f, 6.2288186904958804f, + 6.2479275134435852f, 6.2667865406949010f, + 6.2854022188622487f, 6.3037807481771030f, + 6.3219280948873626f, 6.3398500028846243f, + 6.3575520046180837f, 6.3750394313469245f, + 6.3923174227787606f, 6.4093909361377017f, + 6.4262647547020979f, 6.4429434958487279f, + 6.4594316186372973f, 6.4757334309663976f, + 6.4918530963296747f, 6.5077946401986963f, + 6.5235619560570130f, 6.5391588111080309f, + 6.5545888516776376f, 6.5698556083309478f, + 6.5849625007211560f, 6.5999128421871278f, + 6.6147098441152083f, 6.6293566200796094f, + 6.6438561897747243f, 6.6582114827517946f, + 6.6724253419714951f, 6.6865005271832185f, + 6.7004397181410917f, 6.7142455176661224f, + 6.7279204545631987f, 6.7414669864011464f, + 6.7548875021634682f, 6.7681843247769259f, + 6.7813597135246599f, 6.7944158663501061f, + 6.8073549220576037f, 6.8201789624151878f, + 6.8328900141647412f, 6.8454900509443747f, + 6.8579809951275718f, 6.8703647195834047f, + 6.8826430493618415f, 6.8948177633079437f, + 6.9068905956085187f, 6.9188632372745946f, + 6.9307373375628866f, 6.9425145053392398f, + 6.9541963103868749f, 6.9657842846620869f, + 6.9772799234999167f, 6.9886846867721654f, + 7.0000000000000000f, 7.0112272554232539f, + 7.0223678130284543f, 7.0334230015374501f, + 7.0443941193584533f, 7.0552824355011898f, + 7.0660891904577720f, 7.0768155970508308f, + 7.0874628412503390f, 7.0980320829605263f, + 7.1085244567781691f, 7.1189410727235076f, + 7.1292830169449663f, 7.1395513523987936f, + 7.1497471195046822f, 7.1598713367783890f, + 7.1699250014423121f, 7.1799090900149344f, + 7.1898245588800175f, 7.1996723448363644f, + 7.2094533656289501f, 7.2191685204621611f, + 7.2288186904958804f, 7.2384047393250785f, + 7.2479275134435852f, 7.2573878426926521f, + 7.2667865406949010f, 7.2761244052742375f, + 7.2854022188622487f, 7.2946207488916270f, + 7.3037807481771030f, 7.3128829552843557f, + 7.3219280948873626f, 7.3309168781146167f, + 7.3398500028846243f, 7.3487281542310771f, + 7.3575520046180837f, 7.3663222142458160f, + 7.3750394313469245f, 7.3837042924740519f, + 7.3923174227787606f, 7.4008794362821843f, + 7.4093909361377017f, 7.4178525148858982f, + 7.4262647547020979f, 7.4346282276367245f, + 7.4429434958487279f, 7.4512111118323289f, + 7.4594316186372973f, 7.4676055500829976f, + 7.4757334309663976f, 7.4838157772642563f, + 7.4918530963296747f, 7.4998458870832056f, + 7.5077946401986963f, 7.5156998382840427f, + 7.5235619560570130f, 7.5313814605163118f, + 7.5391588111080309f, 7.5468944598876364f, + 7.5545888516776376f, 7.5622424242210728f, + 7.5698556083309478f, 7.5774288280357486f, + 7.5849625007211560f, 7.5924570372680806f, + 7.5999128421871278f, 7.6073303137496104f, + 7.6147098441152083f, 7.6220518194563764f, + 7.6293566200796094f, 7.6366246205436487f, + 7.6438561897747243f, 7.6510516911789281f, + 7.6582114827517946f, 7.6653359171851764f, + 7.6724253419714951f, 7.6794800995054464f, + 7.6865005271832185f, 7.6934869574993252f, + 7.7004397181410917f, 7.7073591320808825f, + 7.7142455176661224f, 7.7210991887071855f, + 7.7279204545631987f, 7.7347096202258383f, + 7.7414669864011464f, 7.7481928495894605f, + 7.7548875021634682f, 7.7615512324444795f, + 7.7681843247769259f, 7.7747870596011736f, + 7.7813597135246599f, 7.7879025593914317f, + 7.7944158663501061f, 7.8008998999203047f, + 7.8073549220576037f, 7.8137811912170374f, + 7.8201789624151878f, 7.8265484872909150f, + 7.8328900141647412f, 7.8392037880969436f, + 7.8454900509443747f, 7.8517490414160571f, + 7.8579809951275718f, 7.8641861446542797f, + 7.8703647195834047f, 7.8765169465649993f, + 7.8826430493618415f, 7.8887432488982591f, + 7.8948177633079437f, 7.9008668079807486f, + 7.9068905956085187f, 7.9128893362299619f, + 7.9188632372745946f, 7.9248125036057812f, + 7.9307373375628866f, 7.9366379390025709f, + 7.9425145053392398f, 7.9483672315846778f, + 7.9541963103868749f, 7.9600019320680805f, + 7.9657842846620869f, 7.9715435539507719f, + 7.9772799234999167f, 7.9829935746943103f, + 7.9886846867721654f, 7.9943534368588577f +}; + +const float kSLog2Table[LOG_LOOKUP_IDX_MAX] = { + 0.00000000f, 0.00000000f, 2.00000000f, 4.75488750f, + 8.00000000f, 11.60964047f, 15.50977500f, 19.65148445f, + 24.00000000f, 28.52932501f, 33.21928095f, 38.05374781f, + 43.01955001f, 48.10571634f, 53.30296891f, 58.60335893f, + 64.00000000f, 69.48686830f, 75.05865003f, 80.71062276f, + 86.43856190f, 92.23866588f, 98.10749561f, 104.04192499f, + 110.03910002f, 116.09640474f, 122.21143267f, 128.38196256f, + 134.60593782f, 140.88144886f, 147.20671787f, 153.58008562f, + 160.00000000f, 166.46500594f, 172.97373660f, 179.52490559f, + 186.11730005f, 192.74977453f, 199.42124551f, 206.13068654f, + 212.87712380f, 219.65963219f, 226.47733176f, 233.32938445f, + 240.21499122f, 247.13338933f, 254.08384998f, 261.06567603f, + 268.07820003f, 275.12078236f, 282.19280949f, 289.29369244f, + 296.42286534f, 303.57978409f, 310.76392512f, 317.97478424f, + 325.21187564f, 332.47473081f, 339.76289772f, 347.07593991f, + 354.41343574f, 361.77497759f, 369.16017124f, 376.56863518f, + 384.00000000f, 391.45390785f, 398.93001188f, 406.42797576f, + 413.94747321f, 421.48818752f, 429.04981119f, 436.63204548f, + 444.23460010f, 451.85719280f, 459.49954906f, 467.16140179f, + 474.84249102f, 482.54256363f, 490.26137307f, 497.99867911f, + 505.75424759f, 513.52785023f, 521.31926438f, 529.12827280f, + 536.95466351f, 544.79822957f, 552.65876890f, 560.53608414f, + 568.42998244f, 576.34027536f, 584.26677867f, 592.20931226f, + 600.16769996f, 608.14176943f, 616.13135206f, 624.13628279f, + 632.15640007f, 640.19154569f, 648.24156472f, 656.30630539f, + 664.38561898f, 672.47935976f, 680.58738488f, 688.70955430f, + 696.84573069f, 704.99577935f, 713.15956818f, 721.33696754f, + 729.52785023f, 737.73209140f, 745.94956849f, 754.18016116f, + 762.42375127f, 770.68022275f, 778.94946161f, 787.23135586f, + 795.52579543f, 803.83267219f, 812.15187982f, 820.48331383f, + 828.82687147f, 837.18245171f, 845.54995518f, 853.92928416f, + 862.32034249f, 870.72303558f, 879.13727036f, 887.56295522f, + 896.00000000f, 904.44831595f, 912.90781569f, 921.37841320f, + 929.86002376f, 938.35256392f, 946.85595152f, 955.37010560f, + 963.89494641f, 972.43039537f, 980.97637504f, 989.53280911f, + 998.09962237f, 1006.67674069f, 1015.26409097f, 1023.86160116f, + 1032.46920021f, 1041.08681805f, 1049.71438560f, 1058.35183469f, + 1066.99909811f, 1075.65610955f, 1084.32280357f, 1092.99911564f, + 1101.68498204f, 1110.38033993f, 1119.08512727f, 1127.79928282f, + 1136.52274614f, 1145.25545758f, 1153.99735821f, 1162.74838989f, + 1171.50849518f, 1180.27761738f, 1189.05570047f, 1197.84268914f, + 1206.63852876f, 1215.44316535f, 1224.25654560f, 1233.07861684f, + 1241.90932703f, 1250.74862473f, 1259.59645914f, 1268.45278005f, + 1277.31753781f, 1286.19068338f, 1295.07216828f, 1303.96194457f, + 1312.85996488f, 1321.76618236f, 1330.68055071f, 1339.60302413f, + 1348.53355734f, 1357.47210556f, 1366.41862452f, 1375.37307041f, + 1384.33539991f, 1393.30557020f, 1402.28353887f, 1411.26926400f, + 1420.26270412f, 1429.26381818f, 1438.27256558f, 1447.28890615f, + 1456.31280014f, 1465.34420819f, 1474.38309138f, 1483.42941118f, + 1492.48312945f, 1501.54420843f, 1510.61261078f, 1519.68829949f, + 1528.77123795f, 1537.86138993f, 1546.95871952f, 1556.06319119f, + 1565.17476976f, 1574.29342040f, 1583.41910860f, 1592.55180020f, + 1601.69146137f, 1610.83805860f, 1619.99155871f, 1629.15192882f, + 1638.31913637f, 1647.49314911f, 1656.67393509f, 1665.86146266f, + 1675.05570047f, 1684.25661744f, 1693.46418280f, 1702.67836605f, + 1711.89913698f, 1721.12646563f, 1730.36032233f, 1739.60067768f, + 1748.84750254f, 1758.10076802f, 1767.36044551f, 1776.62650662f, + 1785.89892323f, 1795.17766747f, 1804.46271172f, 1813.75402857f, + 1823.05159087f, 1832.35537170f, 1841.66534438f, 1850.98148244f, + 1860.30375965f, 1869.63214999f, 1878.96662767f, 1888.30716711f, + 1897.65374295f, 1907.00633003f, 1916.36490342f, 1925.72943838f, + 1935.09991037f, 1944.47629506f, 1953.85856831f, 1963.24670620f, + 1972.64068498f, 1982.04048108f, 1991.44607117f, 2000.85743204f, + 2010.27454072f, 2019.69737440f, 2029.12591044f, 2038.56012640f +}; + +const VP8LPrefixCode kPrefixEncodeCode[PREFIX_LOOKUP_IDX_MAX] = { + { 0, 0}, { 0, 0}, { 1, 0}, { 2, 0}, { 3, 0}, { 4, 1}, { 4, 1}, { 5, 1}, + { 5, 1}, { 6, 2}, { 6, 2}, { 6, 2}, { 6, 2}, { 7, 2}, { 7, 2}, { 7, 2}, + { 7, 2}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, + { 8, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, + { 9, 3}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, + {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, + {10, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, + {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, + {11, 4}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, + {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, + {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, + {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, + {12, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, + {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, + {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, + {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, + {13, 5}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, + {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, + {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, + {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, + {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, + {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, + {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, + {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, + {14, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, + {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, + {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, + {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, + {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, + {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, + {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, + {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, + {15, 6}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, + {16, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, + {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, + {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, + {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, + {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, + {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, + {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, + {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, + {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, + {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, + {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, + {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, + {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, + {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, + {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, + {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, +}; + +const uint8_t kPrefixEncodeExtraBitsValue[PREFIX_LOOKUP_IDX_MAX] = { + 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 2, 3, 0, 1, 2, 3, + 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, + 127, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126 +}; + +static float FastSLog2Slow_C(uint32_t v) { + assert(v >= LOG_LOOKUP_IDX_MAX); + if (v < APPROX_LOG_WITH_CORRECTION_MAX) { +#if !defined(WEBP_HAVE_SLOW_CLZ_CTZ) + // use clz if available + const int log_cnt = BitsLog2Floor(v) - 7; + const uint32_t y = 1 << log_cnt; + int correction = 0; + const float v_f = (float)v; + const uint32_t orig_v = v; + v >>= log_cnt; +#else + int log_cnt = 0; + uint32_t y = 1; + int correction = 0; + const float v_f = (float)v; + const uint32_t orig_v = v; + do { + ++log_cnt; + v = v >> 1; + y = y << 1; + } while (v >= LOG_LOOKUP_IDX_MAX); +#endif + // vf = (2^log_cnt) * Xf; where y = 2^log_cnt and Xf < 256 + // Xf = floor(Xf) * (1 + (v % y) / v) + // log2(Xf) = log2(floor(Xf)) + log2(1 + (v % y) / v) + // The correction factor: log(1 + d) ~ d; for very small d values, so + // log2(1 + (v % y) / v) ~ LOG_2_RECIPROCAL * (v % y)/v + // LOG_2_RECIPROCAL ~ 23/16 + correction = (23 * (orig_v & (y - 1))) >> 4; + return v_f * (kLog2Table[v] + log_cnt) + correction; + } else { + return (float)(LOG_2_RECIPROCAL * v * log((double)v)); + } +} + +static float FastLog2Slow_C(uint32_t v) { + assert(v >= LOG_LOOKUP_IDX_MAX); + if (v < APPROX_LOG_WITH_CORRECTION_MAX) { +#if !defined(WEBP_HAVE_SLOW_CLZ_CTZ) + // use clz if available + const int log_cnt = BitsLog2Floor(v) - 7; + const uint32_t y = 1 << log_cnt; + const uint32_t orig_v = v; + double log_2; + v >>= log_cnt; +#else + int log_cnt = 0; + uint32_t y = 1; + const uint32_t orig_v = v; + double log_2; + do { + ++log_cnt; + v = v >> 1; + y = y << 1; + } while (v >= LOG_LOOKUP_IDX_MAX); +#endif + log_2 = kLog2Table[v] + log_cnt; + if (orig_v >= APPROX_LOG_MAX) { + // Since the division is still expensive, add this correction factor only + // for large values of 'v'. + const int correction = (23 * (orig_v & (y - 1))) >> 4; + log_2 += (double)correction / orig_v; + } + return (float)log_2; + } else { + return (float)(LOG_2_RECIPROCAL * log((double)v)); + } +} + +//------------------------------------------------------------------------------ +// Methods to calculate Entropy (Shannon). + +// Compute the combined Shanon's entropy for distribution {X} and {X+Y} +static float CombinedShannonEntropy_C(const int X[256], const int Y[256]) { + int i; + float retval = 0.f; + int sumX = 0, sumXY = 0; + for (i = 0; i < 256; ++i) { + const int x = X[i]; + if (x != 0) { + const int xy = x + Y[i]; + sumX += x; + retval -= VP8LFastSLog2(x); + sumXY += xy; + retval -= VP8LFastSLog2(xy); + } else if (Y[i] != 0) { + sumXY += Y[i]; + retval -= VP8LFastSLog2(Y[i]); + } + } + retval += VP8LFastSLog2(sumX) + VP8LFastSLog2(sumXY); + return retval; +} + +void VP8LBitEntropyInit(VP8LBitEntropy* const entropy) { + entropy->entropy = 0.; + entropy->sum = 0; + entropy->nonzeros = 0; + entropy->max_val = 0; + entropy->nonzero_code = VP8L_NON_TRIVIAL_SYM; +} + +void VP8LBitsEntropyUnrefined(const uint32_t* const array, int n, + VP8LBitEntropy* const entropy) { + int i; + + VP8LBitEntropyInit(entropy); + + for (i = 0; i < n; ++i) { + if (array[i] != 0) { + entropy->sum += array[i]; + entropy->nonzero_code = i; + ++entropy->nonzeros; + entropy->entropy -= VP8LFastSLog2(array[i]); + if (entropy->max_val < array[i]) { + entropy->max_val = array[i]; + } + } + } + entropy->entropy += VP8LFastSLog2(entropy->sum); +} + +static WEBP_INLINE void GetEntropyUnrefinedHelper( + uint32_t val, int i, uint32_t* const val_prev, int* const i_prev, + VP8LBitEntropy* const bit_entropy, VP8LStreaks* const stats) { + const int streak = i - *i_prev; + + // Gather info for the bit entropy. + if (*val_prev != 0) { + bit_entropy->sum += (*val_prev) * streak; + bit_entropy->nonzeros += streak; + bit_entropy->nonzero_code = *i_prev; + bit_entropy->entropy -= VP8LFastSLog2(*val_prev) * streak; + if (bit_entropy->max_val < *val_prev) { + bit_entropy->max_val = *val_prev; + } + } + + // Gather info for the Huffman cost. + stats->counts[*val_prev != 0] += (streak > 3); + stats->streaks[*val_prev != 0][(streak > 3)] += streak; + + *val_prev = val; + *i_prev = i; +} + +static void GetEntropyUnrefined_C(const uint32_t X[], int length, + VP8LBitEntropy* const bit_entropy, + VP8LStreaks* const stats) { + int i; + int i_prev = 0; + uint32_t x_prev = X[0]; + + memset(stats, 0, sizeof(*stats)); + VP8LBitEntropyInit(bit_entropy); + + for (i = 1; i < length; ++i) { + const uint32_t x = X[i]; + if (x != x_prev) { + GetEntropyUnrefinedHelper(x, i, &x_prev, &i_prev, bit_entropy, stats); + } + } + GetEntropyUnrefinedHelper(0, i, &x_prev, &i_prev, bit_entropy, stats); + + bit_entropy->entropy += VP8LFastSLog2(bit_entropy->sum); +} + +static void GetCombinedEntropyUnrefined_C(const uint32_t X[], + const uint32_t Y[], + int length, + VP8LBitEntropy* const bit_entropy, + VP8LStreaks* const stats) { + int i = 1; + int i_prev = 0; + uint32_t xy_prev = X[0] + Y[0]; + + memset(stats, 0, sizeof(*stats)); + VP8LBitEntropyInit(bit_entropy); + + for (i = 1; i < length; ++i) { + const uint32_t xy = X[i] + Y[i]; + if (xy != xy_prev) { + GetEntropyUnrefinedHelper(xy, i, &xy_prev, &i_prev, bit_entropy, stats); + } + } + GetEntropyUnrefinedHelper(0, i, &xy_prev, &i_prev, bit_entropy, stats); + + bit_entropy->entropy += VP8LFastSLog2(bit_entropy->sum); +} + +//------------------------------------------------------------------------------ + +void VP8LSubtractGreenFromBlueAndRed_C(uint32_t* argb_data, int num_pixels) { + int i; + for (i = 0; i < num_pixels; ++i) { + const int argb = (int)argb_data[i]; + const int green = (argb >> 8) & 0xff; + const uint32_t new_r = (((argb >> 16) & 0xff) - green) & 0xff; + const uint32_t new_b = (((argb >> 0) & 0xff) - green) & 0xff; + argb_data[i] = ((uint32_t)argb & 0xff00ff00u) | (new_r << 16) | new_b; + } +} + +static WEBP_INLINE int ColorTransformDelta(int8_t color_pred, int8_t color) { + return ((int)color_pred * color) >> 5; +} + +static WEBP_INLINE int8_t U32ToS8(uint32_t v) { + return (int8_t)(v & 0xff); +} + +void VP8LTransformColor_C(const VP8LMultipliers* const m, uint32_t* data, + int num_pixels) { + int i; + for (i = 0; i < num_pixels; ++i) { + const uint32_t argb = data[i]; + const int8_t green = U32ToS8(argb >> 8); + const int8_t red = U32ToS8(argb >> 16); + int new_red = red & 0xff; + int new_blue = argb & 0xff; + new_red -= ColorTransformDelta((int8_t)m->green_to_red_, green); + new_red &= 0xff; + new_blue -= ColorTransformDelta((int8_t)m->green_to_blue_, green); + new_blue -= ColorTransformDelta((int8_t)m->red_to_blue_, red); + new_blue &= 0xff; + data[i] = (argb & 0xff00ff00u) | (new_red << 16) | (new_blue); + } +} + +static WEBP_INLINE uint8_t TransformColorRed(uint8_t green_to_red, + uint32_t argb) { + const int8_t green = U32ToS8(argb >> 8); + int new_red = argb >> 16; + new_red -= ColorTransformDelta((int8_t)green_to_red, green); + return (new_red & 0xff); +} + +static WEBP_INLINE uint8_t TransformColorBlue(uint8_t green_to_blue, + uint8_t red_to_blue, + uint32_t argb) { + const int8_t green = U32ToS8(argb >> 8); + const int8_t red = U32ToS8(argb >> 16); + int new_blue = argb & 0xff; + new_blue -= ColorTransformDelta((int8_t)green_to_blue, green); + new_blue -= ColorTransformDelta((int8_t)red_to_blue, red); + return (new_blue & 0xff); +} + +void VP8LCollectColorRedTransforms_C(const uint32_t* argb, int stride, + int tile_width, int tile_height, + int green_to_red, int histo[]) { + while (tile_height-- > 0) { + int x; + for (x = 0; x < tile_width; ++x) { + ++histo[TransformColorRed((uint8_t)green_to_red, argb[x])]; + } + argb += stride; + } +} + +void VP8LCollectColorBlueTransforms_C(const uint32_t* argb, int stride, + int tile_width, int tile_height, + int green_to_blue, int red_to_blue, + int histo[]) { + while (tile_height-- > 0) { + int x; + for (x = 0; x < tile_width; ++x) { + ++histo[TransformColorBlue((uint8_t)green_to_blue, (uint8_t)red_to_blue, + argb[x])]; + } + argb += stride; + } +} + +//------------------------------------------------------------------------------ + +static int VectorMismatch_C(const uint32_t* const array1, + const uint32_t* const array2, int length) { + int match_len = 0; + + while (match_len < length && array1[match_len] == array2[match_len]) { + ++match_len; + } + return match_len; +} + +// Bundles multiple (1, 2, 4 or 8) pixels into a single pixel. +void VP8LBundleColorMap_C(const uint8_t* const row, int width, int xbits, + uint32_t* dst) { + int x; + if (xbits > 0) { + const int bit_depth = 1 << (3 - xbits); + const int mask = (1 << xbits) - 1; + uint32_t code = 0xff000000; + for (x = 0; x < width; ++x) { + const int xsub = x & mask; + if (xsub == 0) { + code = 0xff000000; + } + code |= row[x] << (8 + bit_depth * xsub); + dst[x >> xbits] = code; + } + } else { + for (x = 0; x < width; ++x) dst[x] = 0xff000000 | (row[x] << 8); + } +} + +//------------------------------------------------------------------------------ + +static uint32_t ExtraCost_C(const uint32_t* population, int length) { + int i; + uint32_t cost = population[4] + population[5]; + assert(length % 2 == 0); + for (i = 2; i < length / 2 - 1; ++i) { + cost += i * (population[2 * i + 2] + population[2 * i + 3]); + } + return cost; +} + +static uint32_t ExtraCostCombined_C(const uint32_t* X, const uint32_t* Y, + int length) { + int i; + uint32_t cost = X[4] + Y[4] + X[5] + Y[5]; + assert(length % 2 == 0); + for (i = 2; i < length / 2 - 1; ++i) { + const int xy0 = X[2 * i + 2] + Y[2 * i + 2]; + const int xy1 = X[2 * i + 3] + Y[2 * i + 3]; + cost += i * (xy0 + xy1); + } + return cost; +} + +//------------------------------------------------------------------------------ + +static void AddVector_C(const uint32_t* a, const uint32_t* b, uint32_t* out, + int size) { + int i; + for (i = 0; i < size; ++i) out[i] = a[i] + b[i]; +} + +static void AddVectorEq_C(const uint32_t* a, uint32_t* out, int size) { + int i; + for (i = 0; i < size; ++i) out[i] += a[i]; +} + +#define ADD(X, ARG, LEN) do { \ + if (a->is_used_[X]) { \ + if (b->is_used_[X]) { \ + VP8LAddVector(a->ARG, b->ARG, out->ARG, (LEN)); \ + } else { \ + memcpy(&out->ARG[0], &a->ARG[0], (LEN) * sizeof(out->ARG[0])); \ + } \ + } else if (b->is_used_[X]) { \ + memcpy(&out->ARG[0], &b->ARG[0], (LEN) * sizeof(out->ARG[0])); \ + } else { \ + memset(&out->ARG[0], 0, (LEN) * sizeof(out->ARG[0])); \ + } \ +} while (0) + +#define ADD_EQ(X, ARG, LEN) do { \ + if (a->is_used_[X]) { \ + if (out->is_used_[X]) { \ + VP8LAddVectorEq(a->ARG, out->ARG, (LEN)); \ + } else { \ + memcpy(&out->ARG[0], &a->ARG[0], (LEN) * sizeof(out->ARG[0])); \ + } \ + } \ +} while (0) + +void VP8LHistogramAdd(const VP8LHistogram* const a, + const VP8LHistogram* const b, VP8LHistogram* const out) { + int i; + const int literal_size = VP8LHistogramNumCodes(a->palette_code_bits_); + assert(a->palette_code_bits_ == b->palette_code_bits_); + + if (b != out) { + ADD(0, literal_, literal_size); + ADD(1, red_, NUM_LITERAL_CODES); + ADD(2, blue_, NUM_LITERAL_CODES); + ADD(3, alpha_, NUM_LITERAL_CODES); + ADD(4, distance_, NUM_DISTANCE_CODES); + for (i = 0; i < 5; ++i) { + out->is_used_[i] = (a->is_used_[i] | b->is_used_[i]); + } + } else { + ADD_EQ(0, literal_, literal_size); + ADD_EQ(1, red_, NUM_LITERAL_CODES); + ADD_EQ(2, blue_, NUM_LITERAL_CODES); + ADD_EQ(3, alpha_, NUM_LITERAL_CODES); + ADD_EQ(4, distance_, NUM_DISTANCE_CODES); + for (i = 0; i < 5; ++i) out->is_used_[i] |= a->is_used_[i]; + } +} +#undef ADD +#undef ADD_EQ + +//------------------------------------------------------------------------------ +// Image transforms. + +static void PredictorSub0_C(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + for (i = 0; i < num_pixels; ++i) out[i] = VP8LSubPixels(in[i], ARGB_BLACK); + (void)upper; +} + +static void PredictorSub1_C(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + for (i = 0; i < num_pixels; ++i) out[i] = VP8LSubPixels(in[i], in[i - 1]); + (void)upper; +} + +// It subtracts the prediction from the input pixel and stores the residual +// in the output pixel. +#define GENERATE_PREDICTOR_SUB(PREDICTOR_I) \ +static void PredictorSub##PREDICTOR_I##_C(const uint32_t* in, \ + const uint32_t* upper, \ + int num_pixels, uint32_t* out) { \ + int x; \ + assert(upper != NULL); \ + for (x = 0; x < num_pixels; ++x) { \ + const uint32_t pred = \ + VP8LPredictor##PREDICTOR_I##_C(&in[x - 1], upper + x); \ + out[x] = VP8LSubPixels(in[x], pred); \ + } \ +} + +GENERATE_PREDICTOR_SUB(2) +GENERATE_PREDICTOR_SUB(3) +GENERATE_PREDICTOR_SUB(4) +GENERATE_PREDICTOR_SUB(5) +GENERATE_PREDICTOR_SUB(6) +GENERATE_PREDICTOR_SUB(7) +GENERATE_PREDICTOR_SUB(8) +GENERATE_PREDICTOR_SUB(9) +GENERATE_PREDICTOR_SUB(10) +GENERATE_PREDICTOR_SUB(11) +GENERATE_PREDICTOR_SUB(12) +GENERATE_PREDICTOR_SUB(13) + +//------------------------------------------------------------------------------ + +VP8LProcessEncBlueAndRedFunc VP8LSubtractGreenFromBlueAndRed; + +VP8LTransformColorFunc VP8LTransformColor; + +VP8LCollectColorBlueTransformsFunc VP8LCollectColorBlueTransforms; +VP8LCollectColorRedTransformsFunc VP8LCollectColorRedTransforms; + +VP8LFastLog2SlowFunc VP8LFastLog2Slow; +VP8LFastLog2SlowFunc VP8LFastSLog2Slow; + +VP8LCostFunc VP8LExtraCost; +VP8LCostCombinedFunc VP8LExtraCostCombined; +VP8LCombinedShannonEntropyFunc VP8LCombinedShannonEntropy; + +VP8LGetEntropyUnrefinedFunc VP8LGetEntropyUnrefined; +VP8LGetCombinedEntropyUnrefinedFunc VP8LGetCombinedEntropyUnrefined; + +VP8LAddVectorFunc VP8LAddVector; +VP8LAddVectorEqFunc VP8LAddVectorEq; + +VP8LVectorMismatchFunc VP8LVectorMismatch; +VP8LBundleColorMapFunc VP8LBundleColorMap; + +VP8LPredictorAddSubFunc VP8LPredictorsSub[16]; +VP8LPredictorAddSubFunc VP8LPredictorsSub_C[16]; + +extern VP8CPUInfo VP8GetCPUInfo; +extern void VP8LEncDspInitSSE2(void); +extern void VP8LEncDspInitSSE41(void); +extern void VP8LEncDspInitNEON(void); +extern void VP8LEncDspInitMIPS32(void); +extern void VP8LEncDspInitMIPSdspR2(void); +extern void VP8LEncDspInitMSA(void); + +WEBP_DSP_INIT_FUNC(VP8LEncDspInit) { + VP8LDspInit(); + +#if !WEBP_NEON_OMIT_C_CODE + VP8LSubtractGreenFromBlueAndRed = VP8LSubtractGreenFromBlueAndRed_C; + + VP8LTransformColor = VP8LTransformColor_C; +#endif + + VP8LCollectColorBlueTransforms = VP8LCollectColorBlueTransforms_C; + VP8LCollectColorRedTransforms = VP8LCollectColorRedTransforms_C; + + VP8LFastLog2Slow = FastLog2Slow_C; + VP8LFastSLog2Slow = FastSLog2Slow_C; + + VP8LExtraCost = ExtraCost_C; + VP8LExtraCostCombined = ExtraCostCombined_C; + VP8LCombinedShannonEntropy = CombinedShannonEntropy_C; + + VP8LGetEntropyUnrefined = GetEntropyUnrefined_C; + VP8LGetCombinedEntropyUnrefined = GetCombinedEntropyUnrefined_C; + + VP8LAddVector = AddVector_C; + VP8LAddVectorEq = AddVectorEq_C; + + VP8LVectorMismatch = VectorMismatch_C; + VP8LBundleColorMap = VP8LBundleColorMap_C; + + VP8LPredictorsSub[0] = PredictorSub0_C; + VP8LPredictorsSub[1] = PredictorSub1_C; + VP8LPredictorsSub[2] = PredictorSub2_C; + VP8LPredictorsSub[3] = PredictorSub3_C; + VP8LPredictorsSub[4] = PredictorSub4_C; + VP8LPredictorsSub[5] = PredictorSub5_C; + VP8LPredictorsSub[6] = PredictorSub6_C; + VP8LPredictorsSub[7] = PredictorSub7_C; + VP8LPredictorsSub[8] = PredictorSub8_C; + VP8LPredictorsSub[9] = PredictorSub9_C; + VP8LPredictorsSub[10] = PredictorSub10_C; + VP8LPredictorsSub[11] = PredictorSub11_C; + VP8LPredictorsSub[12] = PredictorSub12_C; + VP8LPredictorsSub[13] = PredictorSub13_C; + VP8LPredictorsSub[14] = PredictorSub0_C; // <- padding security sentinels + VP8LPredictorsSub[15] = PredictorSub0_C; + + VP8LPredictorsSub_C[0] = PredictorSub0_C; + VP8LPredictorsSub_C[1] = PredictorSub1_C; + VP8LPredictorsSub_C[2] = PredictorSub2_C; + VP8LPredictorsSub_C[3] = PredictorSub3_C; + VP8LPredictorsSub_C[4] = PredictorSub4_C; + VP8LPredictorsSub_C[5] = PredictorSub5_C; + VP8LPredictorsSub_C[6] = PredictorSub6_C; + VP8LPredictorsSub_C[7] = PredictorSub7_C; + VP8LPredictorsSub_C[8] = PredictorSub8_C; + VP8LPredictorsSub_C[9] = PredictorSub9_C; + VP8LPredictorsSub_C[10] = PredictorSub10_C; + VP8LPredictorsSub_C[11] = PredictorSub11_C; + VP8LPredictorsSub_C[12] = PredictorSub12_C; + VP8LPredictorsSub_C[13] = PredictorSub13_C; + VP8LPredictorsSub_C[14] = PredictorSub0_C; // <- padding security sentinels + VP8LPredictorsSub_C[15] = PredictorSub0_C; + + // If defined, use CPUInfo() to overwrite some pointers with faster versions. + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_HAVE_SSE2) + if (VP8GetCPUInfo(kSSE2)) { + VP8LEncDspInitSSE2(); +#if defined(WEBP_HAVE_SSE41) + if (VP8GetCPUInfo(kSSE4_1)) { + VP8LEncDspInitSSE41(); + } +#endif + } +#endif +#if defined(WEBP_USE_MIPS32) + if (VP8GetCPUInfo(kMIPS32)) { + VP8LEncDspInitMIPS32(); + } +#endif +#if defined(WEBP_USE_MIPS_DSP_R2) + if (VP8GetCPUInfo(kMIPSdspR2)) { + VP8LEncDspInitMIPSdspR2(); + } +#endif +#if defined(WEBP_USE_MSA) + if (VP8GetCPUInfo(kMSA)) { + VP8LEncDspInitMSA(); + } +#endif + } + +#if defined(WEBP_HAVE_NEON) + if (WEBP_NEON_OMIT_C_CODE || + (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) { + VP8LEncDspInitNEON(); + } +#endif + + assert(VP8LSubtractGreenFromBlueAndRed != NULL); + assert(VP8LTransformColor != NULL); + assert(VP8LCollectColorBlueTransforms != NULL); + assert(VP8LCollectColorRedTransforms != NULL); + assert(VP8LFastLog2Slow != NULL); + assert(VP8LFastSLog2Slow != NULL); + assert(VP8LExtraCost != NULL); + assert(VP8LExtraCostCombined != NULL); + assert(VP8LCombinedShannonEntropy != NULL); + assert(VP8LGetEntropyUnrefined != NULL); + assert(VP8LGetCombinedEntropyUnrefined != NULL); + assert(VP8LAddVector != NULL); + assert(VP8LAddVectorEq != NULL); + assert(VP8LVectorMismatch != NULL); + assert(VP8LBundleColorMap != NULL); + assert(VP8LPredictorsSub[0] != NULL); + assert(VP8LPredictorsSub[1] != NULL); + assert(VP8LPredictorsSub[2] != NULL); + assert(VP8LPredictorsSub[3] != NULL); + assert(VP8LPredictorsSub[4] != NULL); + assert(VP8LPredictorsSub[5] != NULL); + assert(VP8LPredictorsSub[6] != NULL); + assert(VP8LPredictorsSub[7] != NULL); + assert(VP8LPredictorsSub[8] != NULL); + assert(VP8LPredictorsSub[9] != NULL); + assert(VP8LPredictorsSub[10] != NULL); + assert(VP8LPredictorsSub[11] != NULL); + assert(VP8LPredictorsSub[12] != NULL); + assert(VP8LPredictorsSub[13] != NULL); + assert(VP8LPredictorsSub[14] != NULL); + assert(VP8LPredictorsSub[15] != NULL); + assert(VP8LPredictorsSub_C[0] != NULL); + assert(VP8LPredictorsSub_C[1] != NULL); + assert(VP8LPredictorsSub_C[2] != NULL); + assert(VP8LPredictorsSub_C[3] != NULL); + assert(VP8LPredictorsSub_C[4] != NULL); + assert(VP8LPredictorsSub_C[5] != NULL); + assert(VP8LPredictorsSub_C[6] != NULL); + assert(VP8LPredictorsSub_C[7] != NULL); + assert(VP8LPredictorsSub_C[8] != NULL); + assert(VP8LPredictorsSub_C[9] != NULL); + assert(VP8LPredictorsSub_C[10] != NULL); + assert(VP8LPredictorsSub_C[11] != NULL); + assert(VP8LPredictorsSub_C[12] != NULL); + assert(VP8LPredictorsSub_C[13] != NULL); + assert(VP8LPredictorsSub_C[14] != NULL); + assert(VP8LPredictorsSub_C[15] != NULL); +} + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/src/dsp/lossless_enc_mips32.c b/third-party/webp/libwebp/src/dsp/lossless_enc_mips32.c new file mode 100644 index 0000000000..e10f12da9d --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/lossless_enc_mips32.c @@ -0,0 +1,397 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MIPS version of lossless functions +// +// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) +// Jovan Zelincevic (jovan.zelincevic@imgtec.com) + +#include "src/dsp/dsp.h" +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" + +#if defined(WEBP_USE_MIPS32) + +#include +#include +#include +#include + +static float FastSLog2Slow_MIPS32(uint32_t v) { + assert(v >= LOG_LOOKUP_IDX_MAX); + if (v < APPROX_LOG_WITH_CORRECTION_MAX) { + uint32_t log_cnt, y, correction; + const int c24 = 24; + const float v_f = (float)v; + uint32_t temp; + + // Xf = 256 = 2^8 + // log_cnt is index of leading one in upper 24 bits + __asm__ volatile( + "clz %[log_cnt], %[v] \n\t" + "addiu %[y], $zero, 1 \n\t" + "subu %[log_cnt], %[c24], %[log_cnt] \n\t" + "sllv %[y], %[y], %[log_cnt] \n\t" + "srlv %[temp], %[v], %[log_cnt] \n\t" + : [log_cnt]"=&r"(log_cnt), [y]"=&r"(y), + [temp]"=r"(temp) + : [c24]"r"(c24), [v]"r"(v) + ); + + // vf = (2^log_cnt) * Xf; where y = 2^log_cnt and Xf < 256 + // Xf = floor(Xf) * (1 + (v % y) / v) + // log2(Xf) = log2(floor(Xf)) + log2(1 + (v % y) / v) + // The correction factor: log(1 + d) ~ d; for very small d values, so + // log2(1 + (v % y) / v) ~ LOG_2_RECIPROCAL * (v % y)/v + // LOG_2_RECIPROCAL ~ 23/16 + + // (v % y) = (v % 2^log_cnt) = v & (2^log_cnt - 1) + correction = (23 * (v & (y - 1))) >> 4; + return v_f * (kLog2Table[temp] + log_cnt) + correction; + } else { + return (float)(LOG_2_RECIPROCAL * v * log((double)v)); + } +} + +static float FastLog2Slow_MIPS32(uint32_t v) { + assert(v >= LOG_LOOKUP_IDX_MAX); + if (v < APPROX_LOG_WITH_CORRECTION_MAX) { + uint32_t log_cnt, y; + const int c24 = 24; + double log_2; + uint32_t temp; + + __asm__ volatile( + "clz %[log_cnt], %[v] \n\t" + "addiu %[y], $zero, 1 \n\t" + "subu %[log_cnt], %[c24], %[log_cnt] \n\t" + "sllv %[y], %[y], %[log_cnt] \n\t" + "srlv %[temp], %[v], %[log_cnt] \n\t" + : [log_cnt]"=&r"(log_cnt), [y]"=&r"(y), + [temp]"=r"(temp) + : [c24]"r"(c24), [v]"r"(v) + ); + + log_2 = kLog2Table[temp] + log_cnt; + if (v >= APPROX_LOG_MAX) { + // Since the division is still expensive, add this correction factor only + // for large values of 'v'. + + const uint32_t correction = (23 * (v & (y - 1))) >> 4; + log_2 += (double)correction / v; + } + return (float)log_2; + } else { + return (float)(LOG_2_RECIPROCAL * log((double)v)); + } +} + +// C version of this function: +// int i = 0; +// int64_t cost = 0; +// const uint32_t* pop = &population[4]; +// const uint32_t* LoopEnd = &population[length]; +// while (pop != LoopEnd) { +// ++i; +// cost += i * *pop; +// cost += i * *(pop + 1); +// pop += 2; +// } +// return cost; +static uint32_t ExtraCost_MIPS32(const uint32_t* const population, int length) { + int i, temp0, temp1; + const uint32_t* pop = &population[4]; + const uint32_t* const LoopEnd = &population[length]; + + __asm__ volatile( + "mult $zero, $zero \n\t" + "xor %[i], %[i], %[i] \n\t" + "beq %[pop], %[LoopEnd], 2f \n\t" + "1: \n\t" + "lw %[temp0], 0(%[pop]) \n\t" + "lw %[temp1], 4(%[pop]) \n\t" + "addiu %[i], %[i], 1 \n\t" + "addiu %[pop], %[pop], 8 \n\t" + "madd %[i], %[temp0] \n\t" + "madd %[i], %[temp1] \n\t" + "bne %[pop], %[LoopEnd], 1b \n\t" + "2: \n\t" + "mfhi %[temp0] \n\t" + "mflo %[temp1] \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [i]"=&r"(i), [pop]"+r"(pop) + : [LoopEnd]"r"(LoopEnd) + : "memory", "hi", "lo" + ); + + return ((int64_t)temp0 << 32 | temp1); +} + +// C version of this function: +// int i = 0; +// int64_t cost = 0; +// const uint32_t* pX = &X[4]; +// const uint32_t* pY = &Y[4]; +// const uint32_t* LoopEnd = &X[length]; +// while (pX != LoopEnd) { +// const uint32_t xy0 = *pX + *pY; +// const uint32_t xy1 = *(pX + 1) + *(pY + 1); +// ++i; +// cost += i * xy0; +// cost += i * xy1; +// pX += 2; +// pY += 2; +// } +// return cost; +static uint32_t ExtraCostCombined_MIPS32(const uint32_t* const X, + const uint32_t* const Y, int length) { + int i, temp0, temp1, temp2, temp3; + const uint32_t* pX = &X[4]; + const uint32_t* pY = &Y[4]; + const uint32_t* const LoopEnd = &X[length]; + + __asm__ volatile( + "mult $zero, $zero \n\t" + "xor %[i], %[i], %[i] \n\t" + "beq %[pX], %[LoopEnd], 2f \n\t" + "1: \n\t" + "lw %[temp0], 0(%[pX]) \n\t" + "lw %[temp1], 0(%[pY]) \n\t" + "lw %[temp2], 4(%[pX]) \n\t" + "lw %[temp3], 4(%[pY]) \n\t" + "addiu %[i], %[i], 1 \n\t" + "addu %[temp0], %[temp0], %[temp1] \n\t" + "addu %[temp2], %[temp2], %[temp3] \n\t" + "addiu %[pX], %[pX], 8 \n\t" + "addiu %[pY], %[pY], 8 \n\t" + "madd %[i], %[temp0] \n\t" + "madd %[i], %[temp2] \n\t" + "bne %[pX], %[LoopEnd], 1b \n\t" + "2: \n\t" + "mfhi %[temp0] \n\t" + "mflo %[temp1] \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), + [i]"=&r"(i), [pX]"+r"(pX), [pY]"+r"(pY) + : [LoopEnd]"r"(LoopEnd) + : "memory", "hi", "lo" + ); + + return ((int64_t)temp0 << 32 | temp1); +} + +#define HUFFMAN_COST_PASS \ + __asm__ volatile( \ + "sll %[temp1], %[temp0], 3 \n\t" \ + "addiu %[temp3], %[streak], -3 \n\t" \ + "addu %[temp2], %[pstreaks], %[temp1] \n\t" \ + "blez %[temp3], 1f \n\t" \ + "srl %[temp1], %[temp1], 1 \n\t" \ + "addu %[temp3], %[pcnts], %[temp1] \n\t" \ + "lw %[temp0], 4(%[temp2]) \n\t" \ + "lw %[temp1], 0(%[temp3]) \n\t" \ + "addu %[temp0], %[temp0], %[streak] \n\t" \ + "addiu %[temp1], %[temp1], 1 \n\t" \ + "sw %[temp0], 4(%[temp2]) \n\t" \ + "sw %[temp1], 0(%[temp3]) \n\t" \ + "b 2f \n\t" \ + "1: \n\t" \ + "lw %[temp0], 0(%[temp2]) \n\t" \ + "addu %[temp0], %[temp0], %[streak] \n\t" \ + "sw %[temp0], 0(%[temp2]) \n\t" \ + "2: \n\t" \ + : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), \ + [temp3]"=&r"(temp3), [temp0]"+r"(temp0) \ + : [pstreaks]"r"(pstreaks), [pcnts]"r"(pcnts), \ + [streak]"r"(streak) \ + : "memory" \ + ); + +// Returns the various RLE counts +static WEBP_INLINE void GetEntropyUnrefinedHelper( + uint32_t val, int i, uint32_t* const val_prev, int* const i_prev, + VP8LBitEntropy* const bit_entropy, VP8LStreaks* const stats) { + int* const pstreaks = &stats->streaks[0][0]; + int* const pcnts = &stats->counts[0]; + int temp0, temp1, temp2, temp3; + const int streak = i - *i_prev; + + // Gather info for the bit entropy. + if (*val_prev != 0) { + bit_entropy->sum += (*val_prev) * streak; + bit_entropy->nonzeros += streak; + bit_entropy->nonzero_code = *i_prev; + bit_entropy->entropy -= VP8LFastSLog2(*val_prev) * streak; + if (bit_entropy->max_val < *val_prev) { + bit_entropy->max_val = *val_prev; + } + } + + // Gather info for the Huffman cost. + temp0 = (*val_prev != 0); + HUFFMAN_COST_PASS + + *val_prev = val; + *i_prev = i; +} + +static void GetEntropyUnrefined_MIPS32(const uint32_t X[], int length, + VP8LBitEntropy* const bit_entropy, + VP8LStreaks* const stats) { + int i; + int i_prev = 0; + uint32_t x_prev = X[0]; + + memset(stats, 0, sizeof(*stats)); + VP8LBitEntropyInit(bit_entropy); + + for (i = 1; i < length; ++i) { + const uint32_t x = X[i]; + if (x != x_prev) { + GetEntropyUnrefinedHelper(x, i, &x_prev, &i_prev, bit_entropy, stats); + } + } + GetEntropyUnrefinedHelper(0, i, &x_prev, &i_prev, bit_entropy, stats); + + bit_entropy->entropy += VP8LFastSLog2(bit_entropy->sum); +} + +static void GetCombinedEntropyUnrefined_MIPS32(const uint32_t X[], + const uint32_t Y[], + int length, + VP8LBitEntropy* const entropy, + VP8LStreaks* const stats) { + int i = 1; + int i_prev = 0; + uint32_t xy_prev = X[0] + Y[0]; + + memset(stats, 0, sizeof(*stats)); + VP8LBitEntropyInit(entropy); + + for (i = 1; i < length; ++i) { + const uint32_t xy = X[i] + Y[i]; + if (xy != xy_prev) { + GetEntropyUnrefinedHelper(xy, i, &xy_prev, &i_prev, entropy, stats); + } + } + GetEntropyUnrefinedHelper(0, i, &xy_prev, &i_prev, entropy, stats); + + entropy->entropy += VP8LFastSLog2(entropy->sum); +} + +#define ASM_START \ + __asm__ volatile( \ + ".set push \n\t" \ + ".set at \n\t" \ + ".set macro \n\t" \ + "1: \n\t" + +// P2 = P0 + P1 +// A..D - offsets +// E - temp variable to tell macro +// if pointer should be incremented +// literal_ and successive histograms could be unaligned +// so we must use ulw and usw +#define ADD_TO_OUT(A, B, C, D, E, P0, P1, P2) \ + "ulw %[temp0], " #A "(%[" #P0 "]) \n\t" \ + "ulw %[temp1], " #B "(%[" #P0 "]) \n\t" \ + "ulw %[temp2], " #C "(%[" #P0 "]) \n\t" \ + "ulw %[temp3], " #D "(%[" #P0 "]) \n\t" \ + "ulw %[temp4], " #A "(%[" #P1 "]) \n\t" \ + "ulw %[temp5], " #B "(%[" #P1 "]) \n\t" \ + "ulw %[temp6], " #C "(%[" #P1 "]) \n\t" \ + "ulw %[temp7], " #D "(%[" #P1 "]) \n\t" \ + "addu %[temp4], %[temp4], %[temp0] \n\t" \ + "addu %[temp5], %[temp5], %[temp1] \n\t" \ + "addu %[temp6], %[temp6], %[temp2] \n\t" \ + "addu %[temp7], %[temp7], %[temp3] \n\t" \ + "addiu %[" #P0 "], %[" #P0 "], 16 \n\t" \ + ".if " #E " == 1 \n\t" \ + "addiu %[" #P1 "], %[" #P1 "], 16 \n\t" \ + ".endif \n\t" \ + "usw %[temp4], " #A "(%[" #P2 "]) \n\t" \ + "usw %[temp5], " #B "(%[" #P2 "]) \n\t" \ + "usw %[temp6], " #C "(%[" #P2 "]) \n\t" \ + "usw %[temp7], " #D "(%[" #P2 "]) \n\t" \ + "addiu %[" #P2 "], %[" #P2 "], 16 \n\t" \ + "bne %[" #P0 "], %[LoopEnd], 1b \n\t" \ + ".set pop \n\t" \ + +#define ASM_END_COMMON_0 \ + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), \ + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), \ + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), \ + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), \ + [pa]"+r"(pa), [pout]"+r"(pout) + +#define ASM_END_COMMON_1 \ + : [LoopEnd]"r"(LoopEnd) \ + : "memory", "at" \ + ); + +#define ASM_END_0 \ + ASM_END_COMMON_0 \ + , [pb]"+r"(pb) \ + ASM_END_COMMON_1 + +#define ASM_END_1 \ + ASM_END_COMMON_0 \ + ASM_END_COMMON_1 + +static void AddVector_MIPS32(const uint32_t* pa, const uint32_t* pb, + uint32_t* pout, int size) { + uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + const int end = ((size) / 4) * 4; + const uint32_t* const LoopEnd = pa + end; + int i; + ASM_START + ADD_TO_OUT(0, 4, 8, 12, 1, pa, pb, pout) + ASM_END_0 + for (i = 0; i < size - end; ++i) pout[i] = pa[i] + pb[i]; +} + +static void AddVectorEq_MIPS32(const uint32_t* pa, uint32_t* pout, int size) { + uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + const int end = ((size) / 4) * 4; + const uint32_t* const LoopEnd = pa + end; + int i; + ASM_START + ADD_TO_OUT(0, 4, 8, 12, 0, pa, pout, pout) + ASM_END_1 + for (i = 0; i < size - end; ++i) pout[i] += pa[i]; +} + +#undef ASM_END_1 +#undef ASM_END_0 +#undef ASM_END_COMMON_1 +#undef ASM_END_COMMON_0 +#undef ADD_TO_OUT +#undef ASM_START + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8LEncDspInitMIPS32(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitMIPS32(void) { + VP8LFastSLog2Slow = FastSLog2Slow_MIPS32; + VP8LFastLog2Slow = FastLog2Slow_MIPS32; + VP8LExtraCost = ExtraCost_MIPS32; + VP8LExtraCostCombined = ExtraCostCombined_MIPS32; + VP8LGetEntropyUnrefined = GetEntropyUnrefined_MIPS32; + VP8LGetCombinedEntropyUnrefined = GetCombinedEntropyUnrefined_MIPS32; + VP8LAddVector = AddVector_MIPS32; + VP8LAddVectorEq = AddVectorEq_MIPS32; +} + +#else // !WEBP_USE_MIPS32 + +WEBP_DSP_INIT_STUB(VP8LEncDspInitMIPS32) + +#endif // WEBP_USE_MIPS32 diff --git a/third-party/webp/libwebp/src/dsp/lossless_enc_mips_dsp_r2.c b/third-party/webp/libwebp/src/dsp/lossless_enc_mips_dsp_r2.c new file mode 100644 index 0000000000..5855e6ae15 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/lossless_enc_mips_dsp_r2.c @@ -0,0 +1,281 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Image transform methods for lossless encoder. +// +// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) +// Jovan Zelincevic (jovan.zelincevic@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MIPS_DSP_R2) + +#include "src/dsp/lossless.h" + +static void SubtractGreenFromBlueAndRed_MIPSdspR2(uint32_t* argb_data, + int num_pixels) { + uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + uint32_t* const p_loop1_end = argb_data + (num_pixels & ~3); + uint32_t* const p_loop2_end = p_loop1_end + (num_pixels & 3); + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "beq %[argb_data], %[p_loop1_end], 3f \n\t" + " nop \n\t" + "0: \n\t" + "lw %[temp0], 0(%[argb_data]) \n\t" + "lw %[temp1], 4(%[argb_data]) \n\t" + "lw %[temp2], 8(%[argb_data]) \n\t" + "lw %[temp3], 12(%[argb_data]) \n\t" + "ext %[temp4], %[temp0], 8, 8 \n\t" + "ext %[temp5], %[temp1], 8, 8 \n\t" + "ext %[temp6], %[temp2], 8, 8 \n\t" + "ext %[temp7], %[temp3], 8, 8 \n\t" + "addiu %[argb_data], %[argb_data], 16 \n\t" + "replv.ph %[temp4], %[temp4] \n\t" + "replv.ph %[temp5], %[temp5] \n\t" + "replv.ph %[temp6], %[temp6] \n\t" + "replv.ph %[temp7], %[temp7] \n\t" + "subu.qb %[temp0], %[temp0], %[temp4] \n\t" + "subu.qb %[temp1], %[temp1], %[temp5] \n\t" + "subu.qb %[temp2], %[temp2], %[temp6] \n\t" + "subu.qb %[temp3], %[temp3], %[temp7] \n\t" + "sw %[temp0], -16(%[argb_data]) \n\t" + "sw %[temp1], -12(%[argb_data]) \n\t" + "sw %[temp2], -8(%[argb_data]) \n\t" + "bne %[argb_data], %[p_loop1_end], 0b \n\t" + " sw %[temp3], -4(%[argb_data]) \n\t" + "3: \n\t" + "beq %[argb_data], %[p_loop2_end], 2f \n\t" + " nop \n\t" + "1: \n\t" + "lw %[temp0], 0(%[argb_data]) \n\t" + "addiu %[argb_data], %[argb_data], 4 \n\t" + "ext %[temp4], %[temp0], 8, 8 \n\t" + "replv.ph %[temp4], %[temp4] \n\t" + "subu.qb %[temp0], %[temp0], %[temp4] \n\t" + "bne %[argb_data], %[p_loop2_end], 1b \n\t" + " sw %[temp0], -4(%[argb_data]) \n\t" + "2: \n\t" + ".set pop \n\t" + : [argb_data]"+&r"(argb_data), [temp0]"=&r"(temp0), + [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [temp6]"=&r"(temp6), + [temp7]"=&r"(temp7) + : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end) + : "memory" + ); +} + +static WEBP_INLINE uint32_t ColorTransformDelta(int8_t color_pred, + int8_t color) { + return (uint32_t)((int)(color_pred) * color) >> 5; +} + +static void TransformColor_MIPSdspR2(const VP8LMultipliers* const m, + uint32_t* data, int num_pixels) { + int temp0, temp1, temp2, temp3, temp4, temp5; + uint32_t argb, argb1, new_red, new_red1; + const uint32_t G_to_R = m->green_to_red_; + const uint32_t G_to_B = m->green_to_blue_; + const uint32_t R_to_B = m->red_to_blue_; + uint32_t* const p_loop_end = data + (num_pixels & ~1); + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "beq %[data], %[p_loop_end], 1f \n\t" + " nop \n\t" + "replv.ph %[temp0], %[G_to_R] \n\t" + "replv.ph %[temp1], %[G_to_B] \n\t" + "replv.ph %[temp2], %[R_to_B] \n\t" + "shll.ph %[temp0], %[temp0], 8 \n\t" + "shll.ph %[temp1], %[temp1], 8 \n\t" + "shll.ph %[temp2], %[temp2], 8 \n\t" + "shra.ph %[temp0], %[temp0], 8 \n\t" + "shra.ph %[temp1], %[temp1], 8 \n\t" + "shra.ph %[temp2], %[temp2], 8 \n\t" + "0: \n\t" + "lw %[argb], 0(%[data]) \n\t" + "lw %[argb1], 4(%[data]) \n\t" + "lhu %[new_red], 2(%[data]) \n\t" + "lhu %[new_red1], 6(%[data]) \n\t" + "precrq.qb.ph %[temp3], %[argb], %[argb1] \n\t" + "precr.qb.ph %[temp4], %[argb], %[argb1] \n\t" + "preceu.ph.qbra %[temp3], %[temp3] \n\t" + "preceu.ph.qbla %[temp4], %[temp4] \n\t" + "shll.ph %[temp3], %[temp3], 8 \n\t" + "shll.ph %[temp4], %[temp4], 8 \n\t" + "shra.ph %[temp3], %[temp3], 8 \n\t" + "shra.ph %[temp4], %[temp4], 8 \n\t" + "mul.ph %[temp5], %[temp3], %[temp0] \n\t" + "mul.ph %[temp3], %[temp3], %[temp1] \n\t" + "mul.ph %[temp4], %[temp4], %[temp2] \n\t" + "addiu %[data], %[data], 8 \n\t" + "ins %[new_red1], %[new_red], 16, 16 \n\t" + "ins %[argb1], %[argb], 16, 16 \n\t" + "shra.ph %[temp5], %[temp5], 5 \n\t" + "shra.ph %[temp3], %[temp3], 5 \n\t" + "shra.ph %[temp4], %[temp4], 5 \n\t" + "subu.ph %[new_red1], %[new_red1], %[temp5] \n\t" + "subu.ph %[argb1], %[argb1], %[temp3] \n\t" + "preceu.ph.qbra %[temp5], %[new_red1] \n\t" + "subu.ph %[argb1], %[argb1], %[temp4] \n\t" + "preceu.ph.qbra %[temp3], %[argb1] \n\t" + "sb %[temp5], -2(%[data]) \n\t" + "sb %[temp3], -4(%[data]) \n\t" + "sra %[temp5], %[temp5], 16 \n\t" + "sra %[temp3], %[temp3], 16 \n\t" + "sb %[temp5], -6(%[data]) \n\t" + "bne %[data], %[p_loop_end], 0b \n\t" + " sb %[temp3], -8(%[data]) \n\t" + "1: \n\t" + ".set pop \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [new_red1]"=&r"(new_red1), [new_red]"=&r"(new_red), + [argb]"=&r"(argb), [argb1]"=&r"(argb1), [data]"+&r"(data) + : [G_to_R]"r"(G_to_R), [R_to_B]"r"(R_to_B), + [G_to_B]"r"(G_to_B), [p_loop_end]"r"(p_loop_end) + : "memory", "hi", "lo" + ); + + if (num_pixels & 1) { + const uint32_t argb_ = data[0]; + const uint32_t green = argb_ >> 8; + const uint32_t red = argb_ >> 16; + uint32_t new_blue = argb_; + new_red = red; + new_red -= ColorTransformDelta(m->green_to_red_, green); + new_red &= 0xff; + new_blue -= ColorTransformDelta(m->green_to_blue_, green); + new_blue -= ColorTransformDelta(m->red_to_blue_, red); + new_blue &= 0xff; + data[0] = (argb_ & 0xff00ff00u) | (new_red << 16) | (new_blue); + } +} + +static WEBP_INLINE uint8_t TransformColorBlue(uint8_t green_to_blue, + uint8_t red_to_blue, + uint32_t argb) { + const uint32_t green = argb >> 8; + const uint32_t red = argb >> 16; + uint8_t new_blue = argb; + new_blue -= ColorTransformDelta(green_to_blue, green); + new_blue -= ColorTransformDelta(red_to_blue, red); + return (new_blue & 0xff); +} + +static void CollectColorBlueTransforms_MIPSdspR2(const uint32_t* argb, + int stride, + int tile_width, + int tile_height, + int green_to_blue, + int red_to_blue, + int histo[]) { + const int rtb = (red_to_blue << 16) | (red_to_blue & 0xffff); + const int gtb = (green_to_blue << 16) | (green_to_blue & 0xffff); + const uint32_t mask = 0xff00ffu; + while (tile_height-- > 0) { + int x; + const uint32_t* p_argb = argb; + argb += stride; + for (x = 0; x < (tile_width >> 1); ++x) { + int temp0, temp1, temp2, temp3, temp4, temp5, temp6; + __asm__ volatile ( + "lw %[temp0], 0(%[p_argb]) \n\t" + "lw %[temp1], 4(%[p_argb]) \n\t" + "precr.qb.ph %[temp2], %[temp0], %[temp1] \n\t" + "ins %[temp1], %[temp0], 16, 16 \n\t" + "shra.ph %[temp2], %[temp2], 8 \n\t" + "shra.ph %[temp3], %[temp1], 8 \n\t" + "mul.ph %[temp5], %[temp2], %[rtb] \n\t" + "mul.ph %[temp6], %[temp3], %[gtb] \n\t" + "and %[temp4], %[temp1], %[mask] \n\t" + "addiu %[p_argb], %[p_argb], 8 \n\t" + "shra.ph %[temp5], %[temp5], 5 \n\t" + "shra.ph %[temp6], %[temp6], 5 \n\t" + "subu.qb %[temp2], %[temp4], %[temp5] \n\t" + "subu.qb %[temp2], %[temp2], %[temp6] \n\t" + : [p_argb]"+&r"(p_argb), [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), + [temp5]"=&r"(temp5), [temp6]"=&r"(temp6) + : [rtb]"r"(rtb), [gtb]"r"(gtb), [mask]"r"(mask) + : "memory", "hi", "lo" + ); + ++histo[(uint8_t)(temp2 >> 16)]; + ++histo[(uint8_t)temp2]; + } + if (tile_width & 1) { + ++histo[TransformColorBlue(green_to_blue, red_to_blue, *p_argb)]; + } + } +} + +static WEBP_INLINE uint8_t TransformColorRed(uint8_t green_to_red, + uint32_t argb) { + const uint32_t green = argb >> 8; + uint32_t new_red = argb >> 16; + new_red -= ColorTransformDelta(green_to_red, green); + return (new_red & 0xff); +} + +static void CollectColorRedTransforms_MIPSdspR2(const uint32_t* argb, + int stride, + int tile_width, + int tile_height, + int green_to_red, + int histo[]) { + const int gtr = (green_to_red << 16) | (green_to_red & 0xffff); + while (tile_height-- > 0) { + int x; + const uint32_t* p_argb = argb; + argb += stride; + for (x = 0; x < (tile_width >> 1); ++x) { + int temp0, temp1, temp2, temp3, temp4; + __asm__ volatile ( + "lw %[temp0], 0(%[p_argb]) \n\t" + "lw %[temp1], 4(%[p_argb]) \n\t" + "precrq.ph.w %[temp4], %[temp0], %[temp1] \n\t" + "ins %[temp1], %[temp0], 16, 16 \n\t" + "shra.ph %[temp3], %[temp1], 8 \n\t" + "mul.ph %[temp2], %[temp3], %[gtr] \n\t" + "addiu %[p_argb], %[p_argb], 8 \n\t" + "shra.ph %[temp2], %[temp2], 5 \n\t" + "subu.qb %[temp2], %[temp4], %[temp2] \n\t" + : [p_argb]"+&r"(p_argb), [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [temp4]"=&r"(temp4) + : [gtr]"r"(gtr) + : "memory", "hi", "lo" + ); + ++histo[(uint8_t)(temp2 >> 16)]; + ++histo[(uint8_t)temp2]; + } + if (tile_width & 1) { + ++histo[TransformColorRed(green_to_red, *p_argb)]; + } + } +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8LEncDspInitMIPSdspR2(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitMIPSdspR2(void) { + VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed_MIPSdspR2; + VP8LTransformColor = TransformColor_MIPSdspR2; + VP8LCollectColorBlueTransforms = CollectColorBlueTransforms_MIPSdspR2; + VP8LCollectColorRedTransforms = CollectColorRedTransforms_MIPSdspR2; +} + +#else // !WEBP_USE_MIPS_DSP_R2 + +WEBP_DSP_INIT_STUB(VP8LEncDspInitMIPSdspR2) + +#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/third-party/webp/libwebp/src/dsp/lossless_enc_msa.c b/third-party/webp/libwebp/src/dsp/lossless_enc_msa.c new file mode 100644 index 0000000000..600dddfb59 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/lossless_enc_msa.c @@ -0,0 +1,148 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MSA variant of Image transform methods for lossless encoder. +// +// Authors: Prashant Patil (Prashant.Patil@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MSA) + +#include "src/dsp/lossless.h" +#include "src/dsp/msa_macro.h" + +#define TRANSFORM_COLOR_8(src0, src1, dst0, dst1, c0, c1, mask0, mask1) do { \ + v8i16 g0, g1, t0, t1, t2, t3; \ + v4i32 t4, t5; \ + VSHF_B2_SH(src0, src0, src1, src1, mask0, mask0, g0, g1); \ + DOTP_SB2_SH(g0, g1, c0, c0, t0, t1); \ + SRAI_H2_SH(t0, t1, 5); \ + t0 = __msa_subv_h((v8i16)src0, t0); \ + t1 = __msa_subv_h((v8i16)src1, t1); \ + t4 = __msa_srli_w((v4i32)src0, 16); \ + t5 = __msa_srli_w((v4i32)src1, 16); \ + DOTP_SB2_SH(t4, t5, c1, c1, t2, t3); \ + SRAI_H2_SH(t2, t3, 5); \ + SUB2(t0, t2, t1, t3, t0, t1); \ + VSHF_B2_UB(src0, t0, src1, t1, mask1, mask1, dst0, dst1); \ +} while (0) + +#define TRANSFORM_COLOR_4(src, dst, c0, c1, mask0, mask1) do { \ + const v16i8 g0 = VSHF_SB(src, src, mask0); \ + v8i16 t0 = __msa_dotp_s_h(c0, g0); \ + v8i16 t1; \ + v4i32 t2; \ + t0 = SRAI_H(t0, 5); \ + t0 = __msa_subv_h((v8i16)src, t0); \ + t2 = __msa_srli_w((v4i32)src, 16); \ + t1 = __msa_dotp_s_h(c1, (v16i8)t2); \ + t1 = SRAI_H(t1, 5); \ + t0 = t0 - t1; \ + dst = VSHF_UB(src, t0, mask1); \ +} while (0) + +static void TransformColor_MSA(const VP8LMultipliers* const m, uint32_t* data, + int num_pixels) { + v16u8 src0, dst0; + const v16i8 g2br = (v16i8)__msa_fill_w(m->green_to_blue_ | + (m->green_to_red_ << 16)); + const v16i8 r2b = (v16i8)__msa_fill_w(m->red_to_blue_); + const v16u8 mask0 = { 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, + 13, 255, 13, 255 }; + const v16u8 mask1 = { 16, 1, 18, 3, 20, 5, 22, 7, 24, 9, 26, 11, + 28, 13, 30, 15 }; + + while (num_pixels >= 8) { + v16u8 src1, dst1; + LD_UB2(data, 4, src0, src1); + TRANSFORM_COLOR_8(src0, src1, dst0, dst1, g2br, r2b, mask0, mask1); + ST_UB2(dst0, dst1, data, 4); + data += 8; + num_pixels -= 8; + } + if (num_pixels > 0) { + if (num_pixels >= 4) { + src0 = LD_UB(data); + TRANSFORM_COLOR_4(src0, dst0, g2br, r2b, mask0, mask1); + ST_UB(dst0, data); + data += 4; + num_pixels -= 4; + } + if (num_pixels > 0) { + src0 = LD_UB(data); + TRANSFORM_COLOR_4(src0, dst0, g2br, r2b, mask0, mask1); + if (num_pixels == 3) { + const uint64_t pix_d = __msa_copy_s_d((v2i64)dst0, 0); + const uint32_t pix_w = __msa_copy_s_w((v4i32)dst0, 2); + SD(pix_d, data + 0); + SW(pix_w, data + 2); + } else if (num_pixels == 2) { + const uint64_t pix_d = __msa_copy_s_d((v2i64)dst0, 0); + SD(pix_d, data); + } else { + const uint32_t pix_w = __msa_copy_s_w((v4i32)dst0, 0); + SW(pix_w, data); + } + } + } +} + +static void SubtractGreenFromBlueAndRed_MSA(uint32_t* argb_data, + int num_pixels) { + int i; + uint8_t* ptemp_data = (uint8_t*)argb_data; + v16u8 src0, dst0, tmp0; + const v16u8 mask = { 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, + 13, 255, 13, 255 }; + + while (num_pixels >= 8) { + v16u8 src1, dst1, tmp1; + LD_UB2(ptemp_data, 16, src0, src1); + VSHF_B2_UB(src0, src1, src1, src0, mask, mask, tmp0, tmp1); + SUB2(src0, tmp0, src1, tmp1, dst0, dst1); + ST_UB2(dst0, dst1, ptemp_data, 16); + ptemp_data += 8 * 4; + num_pixels -= 8; + } + if (num_pixels > 0) { + if (num_pixels >= 4) { + src0 = LD_UB(ptemp_data); + tmp0 = VSHF_UB(src0, src0, mask); + dst0 = src0 - tmp0; + ST_UB(dst0, ptemp_data); + ptemp_data += 4 * 4; + num_pixels -= 4; + } + for (i = 0; i < num_pixels; i++) { + const uint8_t b = ptemp_data[0]; + const uint8_t g = ptemp_data[1]; + const uint8_t r = ptemp_data[2]; + ptemp_data[0] = (b - g) & 0xff; + ptemp_data[2] = (r - g) & 0xff; + ptemp_data += 4; + } + } +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8LEncDspInitMSA(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitMSA(void) { + VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed_MSA; + VP8LTransformColor = TransformColor_MSA; +} + +#else // !WEBP_USE_MSA + +WEBP_DSP_INIT_STUB(VP8LEncDspInitMSA) + +#endif // WEBP_USE_MSA diff --git a/third-party/webp/libwebp/src/dsp/lossless_enc_neon.c b/third-party/webp/libwebp/src/dsp/lossless_enc_neon.c new file mode 100644 index 0000000000..e32c7961a2 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/lossless_enc_neon.c @@ -0,0 +1,144 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// NEON variant of methods for lossless encoder +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_NEON) + +#include + +#include "src/dsp/lossless.h" +#include "src/dsp/neon.h" + +//------------------------------------------------------------------------------ +// Subtract-Green Transform + +// vtbl?_u8 are marked unavailable for iOS arm64 with Xcode < 6.3, use +// non-standard versions there. +#if defined(__APPLE__) && WEBP_AARCH64 && \ + defined(__apple_build_version__) && (__apple_build_version__< 6020037) +#define USE_VTBLQ +#endif + +#ifdef USE_VTBLQ +// 255 = byte will be zeroed +static const uint8_t kGreenShuffle[16] = { + 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13, 255 +}; + +static WEBP_INLINE uint8x16_t DoGreenShuffle_NEON(const uint8x16_t argb, + const uint8x16_t shuffle) { + return vcombine_u8(vtbl1q_u8(argb, vget_low_u8(shuffle)), + vtbl1q_u8(argb, vget_high_u8(shuffle))); +} +#else // !USE_VTBLQ +// 255 = byte will be zeroed +static const uint8_t kGreenShuffle[8] = { 1, 255, 1, 255, 5, 255, 5, 255 }; + +static WEBP_INLINE uint8x16_t DoGreenShuffle_NEON(const uint8x16_t argb, + const uint8x8_t shuffle) { + return vcombine_u8(vtbl1_u8(vget_low_u8(argb), shuffle), + vtbl1_u8(vget_high_u8(argb), shuffle)); +} +#endif // USE_VTBLQ + +static void SubtractGreenFromBlueAndRed_NEON(uint32_t* argb_data, + int num_pixels) { + const uint32_t* const end = argb_data + (num_pixels & ~3); +#ifdef USE_VTBLQ + const uint8x16_t shuffle = vld1q_u8(kGreenShuffle); +#else + const uint8x8_t shuffle = vld1_u8(kGreenShuffle); +#endif + for (; argb_data < end; argb_data += 4) { + const uint8x16_t argb = vld1q_u8((uint8_t*)argb_data); + const uint8x16_t greens = DoGreenShuffle_NEON(argb, shuffle); + vst1q_u8((uint8_t*)argb_data, vsubq_u8(argb, greens)); + } + // fallthrough and finish off with plain-C + VP8LSubtractGreenFromBlueAndRed_C(argb_data, num_pixels & 3); +} + +//------------------------------------------------------------------------------ +// Color Transform + +static void TransformColor_NEON(const VP8LMultipliers* const m, + uint32_t* argb_data, int num_pixels) { + // sign-extended multiplying constants, pre-shifted by 6. +#define CST(X) (((int16_t)(m->X << 8)) >> 6) + const int16_t rb[8] = { + CST(green_to_blue_), CST(green_to_red_), + CST(green_to_blue_), CST(green_to_red_), + CST(green_to_blue_), CST(green_to_red_), + CST(green_to_blue_), CST(green_to_red_) + }; + const int16x8_t mults_rb = vld1q_s16(rb); + const int16_t b2[8] = { + 0, CST(red_to_blue_), 0, CST(red_to_blue_), + 0, CST(red_to_blue_), 0, CST(red_to_blue_), + }; + const int16x8_t mults_b2 = vld1q_s16(b2); +#undef CST +#ifdef USE_VTBLQ + static const uint8_t kg0g0[16] = { + 255, 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13 + }; + const uint8x16_t shuffle = vld1q_u8(kg0g0); +#else + static const uint8_t k0g0g[8] = { 255, 1, 255, 1, 255, 5, 255, 5 }; + const uint8x8_t shuffle = vld1_u8(k0g0g); +#endif + const uint32x4_t mask_rb = vdupq_n_u32(0x00ff00ffu); // red-blue masks + int i; + for (i = 0; i + 4 <= num_pixels; i += 4) { + const uint8x16_t in = vld1q_u8((uint8_t*)(argb_data + i)); + // 0 g 0 g + const uint8x16_t greens = DoGreenShuffle_NEON(in, shuffle); + // x dr x db1 + const int16x8_t A = vqdmulhq_s16(vreinterpretq_s16_u8(greens), mults_rb); + // r 0 b 0 + const int16x8_t B = vshlq_n_s16(vreinterpretq_s16_u8(in), 8); + // x db2 0 0 + const int16x8_t C = vqdmulhq_s16(B, mults_b2); + // 0 0 x db2 + const uint32x4_t D = vshrq_n_u32(vreinterpretq_u32_s16(C), 16); + // x dr x db + const int8x16_t E = vaddq_s8(vreinterpretq_s8_u32(D), + vreinterpretq_s8_s16(A)); + // 0 dr 0 db + const uint32x4_t F = vandq_u32(vreinterpretq_u32_s8(E), mask_rb); + const int8x16_t out = vsubq_s8(vreinterpretq_s8_u8(in), + vreinterpretq_s8_u32(F)); + vst1q_s8((int8_t*)(argb_data + i), out); + } + // fallthrough and finish off with plain-C + VP8LTransformColor_C(m, argb_data + i, num_pixels - i); +} + +#undef USE_VTBLQ + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8LEncDspInitNEON(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitNEON(void) { + VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed_NEON; + VP8LTransformColor = TransformColor_NEON; +} + +#else // !WEBP_USE_NEON + +WEBP_DSP_INIT_STUB(VP8LEncDspInitNEON) + +#endif // WEBP_USE_NEON diff --git a/third-party/webp/libwebp/src/dsp/lossless_enc_sse2.c b/third-party/webp/libwebp/src/dsp/lossless_enc_sse2.c new file mode 100644 index 0000000000..66cbaab772 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/lossless_enc_sse2.c @@ -0,0 +1,669 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE2 variant of methods for lossless encoder +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE2) +#include +#include +#include "src/dsp/lossless.h" +#include "src/dsp/common_sse2.h" +#include "src/dsp/lossless_common.h" + +// For sign-extended multiplying constants, pre-shifted by 5: +#define CST_5b(X) (((int16_t)((uint16_t)(X) << 8)) >> 5) + +//------------------------------------------------------------------------------ +// Subtract-Green Transform + +static void SubtractGreenFromBlueAndRed_SSE2(uint32_t* argb_data, + int num_pixels) { + int i; + for (i = 0; i + 4 <= num_pixels; i += 4) { + const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); // argb + const __m128i A = _mm_srli_epi16(in, 8); // 0 a 0 g + const __m128i B = _mm_shufflelo_epi16(A, _MM_SHUFFLE(2, 2, 0, 0)); + const __m128i C = _mm_shufflehi_epi16(B, _MM_SHUFFLE(2, 2, 0, 0)); // 0g0g + const __m128i out = _mm_sub_epi8(in, C); + _mm_storeu_si128((__m128i*)&argb_data[i], out); + } + // fallthrough and finish off with plain-C + if (i != num_pixels) { + VP8LSubtractGreenFromBlueAndRed_C(argb_data + i, num_pixels - i); + } +} + +//------------------------------------------------------------------------------ +// Color Transform + +#define MK_CST_16(HI, LO) \ + _mm_set1_epi32((int)(((uint32_t)(HI) << 16) | ((LO) & 0xffff))) + +static void TransformColor_SSE2(const VP8LMultipliers* const m, + uint32_t* argb_data, int num_pixels) { + const __m128i mults_rb = MK_CST_16(CST_5b(m->green_to_red_), + CST_5b(m->green_to_blue_)); + const __m128i mults_b2 = MK_CST_16(CST_5b(m->red_to_blue_), 0); + const __m128i mask_ag = _mm_set1_epi32((int)0xff00ff00); // alpha-green masks + const __m128i mask_rb = _mm_set1_epi32(0x00ff00ff); // red-blue masks + int i; + for (i = 0; i + 4 <= num_pixels; i += 4) { + const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); // argb + const __m128i A = _mm_and_si128(in, mask_ag); // a 0 g 0 + const __m128i B = _mm_shufflelo_epi16(A, _MM_SHUFFLE(2, 2, 0, 0)); + const __m128i C = _mm_shufflehi_epi16(B, _MM_SHUFFLE(2, 2, 0, 0)); // g0g0 + const __m128i D = _mm_mulhi_epi16(C, mults_rb); // x dr x db1 + const __m128i E = _mm_slli_epi16(in, 8); // r 0 b 0 + const __m128i F = _mm_mulhi_epi16(E, mults_b2); // x db2 0 0 + const __m128i G = _mm_srli_epi32(F, 16); // 0 0 x db2 + const __m128i H = _mm_add_epi8(G, D); // x dr x db + const __m128i I = _mm_and_si128(H, mask_rb); // 0 dr 0 db + const __m128i out = _mm_sub_epi8(in, I); + _mm_storeu_si128((__m128i*)&argb_data[i], out); + } + // fallthrough and finish off with plain-C + if (i != num_pixels) { + VP8LTransformColor_C(m, argb_data + i, num_pixels - i); + } +} + +//------------------------------------------------------------------------------ +#define SPAN 8 +static void CollectColorBlueTransforms_SSE2(const uint32_t* argb, int stride, + int tile_width, int tile_height, + int green_to_blue, int red_to_blue, + int histo[]) { + const __m128i mults_r = MK_CST_16(CST_5b(red_to_blue), 0); + const __m128i mults_g = MK_CST_16(0, CST_5b(green_to_blue)); + const __m128i mask_g = _mm_set1_epi32(0x00ff00); // green mask + const __m128i mask_b = _mm_set1_epi32(0x0000ff); // blue mask + int y; + for (y = 0; y < tile_height; ++y) { + const uint32_t* const src = argb + y * stride; + int i, x; + for (x = 0; x + SPAN <= tile_width; x += SPAN) { + uint16_t values[SPAN]; + const __m128i in0 = _mm_loadu_si128((__m128i*)&src[x + 0]); + const __m128i in1 = _mm_loadu_si128((__m128i*)&src[x + SPAN / 2]); + const __m128i A0 = _mm_slli_epi16(in0, 8); // r 0 | b 0 + const __m128i A1 = _mm_slli_epi16(in1, 8); + const __m128i B0 = _mm_and_si128(in0, mask_g); // 0 0 | g 0 + const __m128i B1 = _mm_and_si128(in1, mask_g); + const __m128i C0 = _mm_mulhi_epi16(A0, mults_r); // x db | 0 0 + const __m128i C1 = _mm_mulhi_epi16(A1, mults_r); + const __m128i D0 = _mm_mulhi_epi16(B0, mults_g); // 0 0 | x db + const __m128i D1 = _mm_mulhi_epi16(B1, mults_g); + const __m128i E0 = _mm_sub_epi8(in0, D0); // x x | x b' + const __m128i E1 = _mm_sub_epi8(in1, D1); + const __m128i F0 = _mm_srli_epi32(C0, 16); // 0 0 | x db + const __m128i F1 = _mm_srli_epi32(C1, 16); + const __m128i G0 = _mm_sub_epi8(E0, F0); // 0 0 | x b' + const __m128i G1 = _mm_sub_epi8(E1, F1); + const __m128i H0 = _mm_and_si128(G0, mask_b); // 0 0 | 0 b + const __m128i H1 = _mm_and_si128(G1, mask_b); + const __m128i I = _mm_packs_epi32(H0, H1); // 0 b' | 0 b' + _mm_storeu_si128((__m128i*)values, I); + for (i = 0; i < SPAN; ++i) ++histo[values[i]]; + } + } + { + const int left_over = tile_width & (SPAN - 1); + if (left_over > 0) { + VP8LCollectColorBlueTransforms_C(argb + tile_width - left_over, stride, + left_over, tile_height, + green_to_blue, red_to_blue, histo); + } + } +} + +static void CollectColorRedTransforms_SSE2(const uint32_t* argb, int stride, + int tile_width, int tile_height, + int green_to_red, int histo[]) { + const __m128i mults_g = MK_CST_16(0, CST_5b(green_to_red)); + const __m128i mask_g = _mm_set1_epi32(0x00ff00); // green mask + const __m128i mask = _mm_set1_epi32(0xff); + + int y; + for (y = 0; y < tile_height; ++y) { + const uint32_t* const src = argb + y * stride; + int i, x; + for (x = 0; x + SPAN <= tile_width; x += SPAN) { + uint16_t values[SPAN]; + const __m128i in0 = _mm_loadu_si128((__m128i*)&src[x + 0]); + const __m128i in1 = _mm_loadu_si128((__m128i*)&src[x + SPAN / 2]); + const __m128i A0 = _mm_and_si128(in0, mask_g); // 0 0 | g 0 + const __m128i A1 = _mm_and_si128(in1, mask_g); + const __m128i B0 = _mm_srli_epi32(in0, 16); // 0 0 | x r + const __m128i B1 = _mm_srli_epi32(in1, 16); + const __m128i C0 = _mm_mulhi_epi16(A0, mults_g); // 0 0 | x dr + const __m128i C1 = _mm_mulhi_epi16(A1, mults_g); + const __m128i E0 = _mm_sub_epi8(B0, C0); // x x | x r' + const __m128i E1 = _mm_sub_epi8(B1, C1); + const __m128i F0 = _mm_and_si128(E0, mask); // 0 0 | 0 r' + const __m128i F1 = _mm_and_si128(E1, mask); + const __m128i I = _mm_packs_epi32(F0, F1); + _mm_storeu_si128((__m128i*)values, I); + for (i = 0; i < SPAN; ++i) ++histo[values[i]]; + } + } + { + const int left_over = tile_width & (SPAN - 1); + if (left_over > 0) { + VP8LCollectColorRedTransforms_C(argb + tile_width - left_over, stride, + left_over, tile_height, + green_to_red, histo); + } + } +} +#undef SPAN +#undef MK_CST_16 + +//------------------------------------------------------------------------------ + +// Note we are adding uint32_t's as *signed* int32's (using _mm_add_epi32). But +// that's ok since the histogram values are less than 1<<28 (max picture size). +#define LINE_SIZE 16 // 8 or 16 +static void AddVector_SSE2(const uint32_t* a, const uint32_t* b, uint32_t* out, + int size) { + int i; + for (i = 0; i + LINE_SIZE <= size; i += LINE_SIZE) { + const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[i + 0]); + const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[i + 4]); +#if (LINE_SIZE == 16) + const __m128i a2 = _mm_loadu_si128((const __m128i*)&a[i + 8]); + const __m128i a3 = _mm_loadu_si128((const __m128i*)&a[i + 12]); +#endif + const __m128i b0 = _mm_loadu_si128((const __m128i*)&b[i + 0]); + const __m128i b1 = _mm_loadu_si128((const __m128i*)&b[i + 4]); +#if (LINE_SIZE == 16) + const __m128i b2 = _mm_loadu_si128((const __m128i*)&b[i + 8]); + const __m128i b3 = _mm_loadu_si128((const __m128i*)&b[i + 12]); +#endif + _mm_storeu_si128((__m128i*)&out[i + 0], _mm_add_epi32(a0, b0)); + _mm_storeu_si128((__m128i*)&out[i + 4], _mm_add_epi32(a1, b1)); +#if (LINE_SIZE == 16) + _mm_storeu_si128((__m128i*)&out[i + 8], _mm_add_epi32(a2, b2)); + _mm_storeu_si128((__m128i*)&out[i + 12], _mm_add_epi32(a3, b3)); +#endif + } + for (; i < size; ++i) { + out[i] = a[i] + b[i]; + } +} + +static void AddVectorEq_SSE2(const uint32_t* a, uint32_t* out, int size) { + int i; + for (i = 0; i + LINE_SIZE <= size; i += LINE_SIZE) { + const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[i + 0]); + const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[i + 4]); +#if (LINE_SIZE == 16) + const __m128i a2 = _mm_loadu_si128((const __m128i*)&a[i + 8]); + const __m128i a3 = _mm_loadu_si128((const __m128i*)&a[i + 12]); +#endif + const __m128i b0 = _mm_loadu_si128((const __m128i*)&out[i + 0]); + const __m128i b1 = _mm_loadu_si128((const __m128i*)&out[i + 4]); +#if (LINE_SIZE == 16) + const __m128i b2 = _mm_loadu_si128((const __m128i*)&out[i + 8]); + const __m128i b3 = _mm_loadu_si128((const __m128i*)&out[i + 12]); +#endif + _mm_storeu_si128((__m128i*)&out[i + 0], _mm_add_epi32(a0, b0)); + _mm_storeu_si128((__m128i*)&out[i + 4], _mm_add_epi32(a1, b1)); +#if (LINE_SIZE == 16) + _mm_storeu_si128((__m128i*)&out[i + 8], _mm_add_epi32(a2, b2)); + _mm_storeu_si128((__m128i*)&out[i + 12], _mm_add_epi32(a3, b3)); +#endif + } + for (; i < size; ++i) { + out[i] += a[i]; + } +} +#undef LINE_SIZE + +//------------------------------------------------------------------------------ +// Entropy + +// TODO(https://crbug.com/webp/499): this function produces different results +// from the C code due to use of double/float resulting in output differences +// when compared to -noasm. +#if !(defined(WEBP_HAVE_SLOW_CLZ_CTZ) || defined(__i386__) || defined(_M_IX86)) + +static float CombinedShannonEntropy_SSE2(const int X[256], const int Y[256]) { + int i; + float retval = 0.f; + int sumX = 0, sumXY = 0; + const __m128i zero = _mm_setzero_si128(); + + for (i = 0; i < 256; i += 16) { + const __m128i x0 = _mm_loadu_si128((const __m128i*)(X + i + 0)); + const __m128i y0 = _mm_loadu_si128((const __m128i*)(Y + i + 0)); + const __m128i x1 = _mm_loadu_si128((const __m128i*)(X + i + 4)); + const __m128i y1 = _mm_loadu_si128((const __m128i*)(Y + i + 4)); + const __m128i x2 = _mm_loadu_si128((const __m128i*)(X + i + 8)); + const __m128i y2 = _mm_loadu_si128((const __m128i*)(Y + i + 8)); + const __m128i x3 = _mm_loadu_si128((const __m128i*)(X + i + 12)); + const __m128i y3 = _mm_loadu_si128((const __m128i*)(Y + i + 12)); + const __m128i x4 = _mm_packs_epi16(_mm_packs_epi32(x0, x1), + _mm_packs_epi32(x2, x3)); + const __m128i y4 = _mm_packs_epi16(_mm_packs_epi32(y0, y1), + _mm_packs_epi32(y2, y3)); + const int32_t mx = _mm_movemask_epi8(_mm_cmpgt_epi8(x4, zero)); + int32_t my = _mm_movemask_epi8(_mm_cmpgt_epi8(y4, zero)) | mx; + while (my) { + const int32_t j = BitsCtz(my); + int xy; + if ((mx >> j) & 1) { + const int x = X[i + j]; + sumXY += x; + retval -= VP8LFastSLog2(x); + } + xy = X[i + j] + Y[i + j]; + sumX += xy; + retval -= VP8LFastSLog2(xy); + my &= my - 1; + } + } + retval += VP8LFastSLog2(sumX) + VP8LFastSLog2(sumXY); + return retval; +} + +#else + +#define DONT_USE_COMBINED_SHANNON_ENTROPY_SSE2_FUNC // won't be faster + +#endif + +//------------------------------------------------------------------------------ + +static int VectorMismatch_SSE2(const uint32_t* const array1, + const uint32_t* const array2, int length) { + int match_len; + + if (length >= 12) { + __m128i A0 = _mm_loadu_si128((const __m128i*)&array1[0]); + __m128i A1 = _mm_loadu_si128((const __m128i*)&array2[0]); + match_len = 0; + do { + // Loop unrolling and early load both provide a speedup of 10% for the + // current function. Also, max_limit can be MAX_LENGTH=4096 at most. + const __m128i cmpA = _mm_cmpeq_epi32(A0, A1); + const __m128i B0 = + _mm_loadu_si128((const __m128i*)&array1[match_len + 4]); + const __m128i B1 = + _mm_loadu_si128((const __m128i*)&array2[match_len + 4]); + if (_mm_movemask_epi8(cmpA) != 0xffff) break; + match_len += 4; + + { + const __m128i cmpB = _mm_cmpeq_epi32(B0, B1); + A0 = _mm_loadu_si128((const __m128i*)&array1[match_len + 4]); + A1 = _mm_loadu_si128((const __m128i*)&array2[match_len + 4]); + if (_mm_movemask_epi8(cmpB) != 0xffff) break; + match_len += 4; + } + } while (match_len + 12 < length); + } else { + match_len = 0; + // Unroll the potential first two loops. + if (length >= 4 && + _mm_movemask_epi8(_mm_cmpeq_epi32( + _mm_loadu_si128((const __m128i*)&array1[0]), + _mm_loadu_si128((const __m128i*)&array2[0]))) == 0xffff) { + match_len = 4; + if (length >= 8 && + _mm_movemask_epi8(_mm_cmpeq_epi32( + _mm_loadu_si128((const __m128i*)&array1[4]), + _mm_loadu_si128((const __m128i*)&array2[4]))) == 0xffff) { + match_len = 8; + } + } + } + + while (match_len < length && array1[match_len] == array2[match_len]) { + ++match_len; + } + return match_len; +} + +// Bundles multiple (1, 2, 4 or 8) pixels into a single pixel. +static void BundleColorMap_SSE2(const uint8_t* const row, int width, int xbits, + uint32_t* dst) { + int x; + assert(xbits >= 0); + assert(xbits <= 3); + switch (xbits) { + case 0: { + const __m128i ff = _mm_set1_epi16((short)0xff00); + const __m128i zero = _mm_setzero_si128(); + // Store 0xff000000 | (row[x] << 8). + for (x = 0; x + 16 <= width; x += 16, dst += 16) { + const __m128i in = _mm_loadu_si128((const __m128i*)&row[x]); + const __m128i in_lo = _mm_unpacklo_epi8(zero, in); + const __m128i dst0 = _mm_unpacklo_epi16(in_lo, ff); + const __m128i dst1 = _mm_unpackhi_epi16(in_lo, ff); + const __m128i in_hi = _mm_unpackhi_epi8(zero, in); + const __m128i dst2 = _mm_unpacklo_epi16(in_hi, ff); + const __m128i dst3 = _mm_unpackhi_epi16(in_hi, ff); + _mm_storeu_si128((__m128i*)&dst[0], dst0); + _mm_storeu_si128((__m128i*)&dst[4], dst1); + _mm_storeu_si128((__m128i*)&dst[8], dst2); + _mm_storeu_si128((__m128i*)&dst[12], dst3); + } + break; + } + case 1: { + const __m128i ff = _mm_set1_epi16((short)0xff00); + const __m128i mul = _mm_set1_epi16(0x110); + for (x = 0; x + 16 <= width; x += 16, dst += 8) { + // 0a0b | (where a/b are 4 bits). + const __m128i in = _mm_loadu_si128((const __m128i*)&row[x]); + const __m128i tmp = _mm_mullo_epi16(in, mul); // aba0 + const __m128i pack = _mm_and_si128(tmp, ff); // ab00 + const __m128i dst0 = _mm_unpacklo_epi16(pack, ff); + const __m128i dst1 = _mm_unpackhi_epi16(pack, ff); + _mm_storeu_si128((__m128i*)&dst[0], dst0); + _mm_storeu_si128((__m128i*)&dst[4], dst1); + } + break; + } + case 2: { + const __m128i mask_or = _mm_set1_epi32((int)0xff000000); + const __m128i mul_cst = _mm_set1_epi16(0x0104); + const __m128i mask_mul = _mm_set1_epi16(0x0f00); + for (x = 0; x + 16 <= width; x += 16, dst += 4) { + // 000a000b000c000d | (where a/b/c/d are 2 bits). + const __m128i in = _mm_loadu_si128((const __m128i*)&row[x]); + const __m128i mul = _mm_mullo_epi16(in, mul_cst); // 00ab00b000cd00d0 + const __m128i tmp = _mm_and_si128(mul, mask_mul); // 00ab000000cd0000 + const __m128i shift = _mm_srli_epi32(tmp, 12); // 00000000ab000000 + const __m128i pack = _mm_or_si128(shift, tmp); // 00000000abcd0000 + // Convert to 0xff00**00. + const __m128i res = _mm_or_si128(pack, mask_or); + _mm_storeu_si128((__m128i*)dst, res); + } + break; + } + default: { + assert(xbits == 3); + for (x = 0; x + 16 <= width; x += 16, dst += 2) { + // 0000000a00000000b... | (where a/b are 1 bit). + const __m128i in = _mm_loadu_si128((const __m128i*)&row[x]); + const __m128i shift = _mm_slli_epi64(in, 7); + const uint32_t move = _mm_movemask_epi8(shift); + dst[0] = 0xff000000 | ((move & 0xff) << 8); + dst[1] = 0xff000000 | (move & 0xff00); + } + break; + } + } + if (x != width) { + VP8LBundleColorMap_C(row + x, width - x, xbits, dst); + } +} + +//------------------------------------------------------------------------------ +// Batch version of Predictor Transform subtraction + +static WEBP_INLINE void Average2_m128i(const __m128i* const a0, + const __m128i* const a1, + __m128i* const avg) { + // (a + b) >> 1 = ((a + b + 1) >> 1) - ((a ^ b) & 1) + const __m128i ones = _mm_set1_epi8(1); + const __m128i avg1 = _mm_avg_epu8(*a0, *a1); + const __m128i one = _mm_and_si128(_mm_xor_si128(*a0, *a1), ones); + *avg = _mm_sub_epi8(avg1, one); +} + +// Predictor0: ARGB_BLACK. +static void PredictorSub0_SSE2(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + const __m128i black = _mm_set1_epi32((int)ARGB_BLACK); + for (i = 0; i + 4 <= num_pixels; i += 4) { + const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); + const __m128i res = _mm_sub_epi8(src, black); + _mm_storeu_si128((__m128i*)&out[i], res); + } + if (i != num_pixels) { + VP8LPredictorsSub_C[0](in + i, NULL, num_pixels - i, out + i); + } + (void)upper; +} + +#define GENERATE_PREDICTOR_1(X, IN) \ + static void PredictorSub##X##_SSE2(const uint32_t* const in, \ + const uint32_t* const upper, \ + int num_pixels, uint32_t* const out) { \ + int i; \ + for (i = 0; i + 4 <= num_pixels; i += 4) { \ + const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); \ + const __m128i pred = _mm_loadu_si128((const __m128i*)&(IN)); \ + const __m128i res = _mm_sub_epi8(src, pred); \ + _mm_storeu_si128((__m128i*)&out[i], res); \ + } \ + if (i != num_pixels) { \ + VP8LPredictorsSub_C[(X)](in + i, WEBP_OFFSET_PTR(upper, i), \ + num_pixels - i, out + i); \ + } \ + } + +GENERATE_PREDICTOR_1(1, in[i - 1]) // Predictor1: L +GENERATE_PREDICTOR_1(2, upper[i]) // Predictor2: T +GENERATE_PREDICTOR_1(3, upper[i + 1]) // Predictor3: TR +GENERATE_PREDICTOR_1(4, upper[i - 1]) // Predictor4: TL +#undef GENERATE_PREDICTOR_1 + +// Predictor5: avg2(avg2(L, TR), T) +static void PredictorSub5_SSE2(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + for (i = 0; i + 4 <= num_pixels; i += 4) { + const __m128i L = _mm_loadu_si128((const __m128i*)&in[i - 1]); + const __m128i T = _mm_loadu_si128((const __m128i*)&upper[i]); + const __m128i TR = _mm_loadu_si128((const __m128i*)&upper[i + 1]); + const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); + __m128i avg, pred, res; + Average2_m128i(&L, &TR, &avg); + Average2_m128i(&avg, &T, &pred); + res = _mm_sub_epi8(src, pred); + _mm_storeu_si128((__m128i*)&out[i], res); + } + if (i != num_pixels) { + VP8LPredictorsSub_C[5](in + i, upper + i, num_pixels - i, out + i); + } +} + +#define GENERATE_PREDICTOR_2(X, A, B) \ +static void PredictorSub##X##_SSE2(const uint32_t* in, const uint32_t* upper, \ + int num_pixels, uint32_t* out) { \ + int i; \ + for (i = 0; i + 4 <= num_pixels; i += 4) { \ + const __m128i tA = _mm_loadu_si128((const __m128i*)&(A)); \ + const __m128i tB = _mm_loadu_si128((const __m128i*)&(B)); \ + const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); \ + __m128i pred, res; \ + Average2_m128i(&tA, &tB, &pred); \ + res = _mm_sub_epi8(src, pred); \ + _mm_storeu_si128((__m128i*)&out[i], res); \ + } \ + if (i != num_pixels) { \ + VP8LPredictorsSub_C[(X)](in + i, upper + i, num_pixels - i, out + i); \ + } \ +} + +GENERATE_PREDICTOR_2(6, in[i - 1], upper[i - 1]) // Predictor6: avg(L, TL) +GENERATE_PREDICTOR_2(7, in[i - 1], upper[i]) // Predictor7: avg(L, T) +GENERATE_PREDICTOR_2(8, upper[i - 1], upper[i]) // Predictor8: avg(TL, T) +GENERATE_PREDICTOR_2(9, upper[i], upper[i + 1]) // Predictor9: average(T, TR) +#undef GENERATE_PREDICTOR_2 + +// Predictor10: avg(avg(L,TL), avg(T, TR)). +static void PredictorSub10_SSE2(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + for (i = 0; i + 4 <= num_pixels; i += 4) { + const __m128i L = _mm_loadu_si128((const __m128i*)&in[i - 1]); + const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); + const __m128i TL = _mm_loadu_si128((const __m128i*)&upper[i - 1]); + const __m128i T = _mm_loadu_si128((const __m128i*)&upper[i]); + const __m128i TR = _mm_loadu_si128((const __m128i*)&upper[i + 1]); + __m128i avgTTR, avgLTL, avg, res; + Average2_m128i(&T, &TR, &avgTTR); + Average2_m128i(&L, &TL, &avgLTL); + Average2_m128i(&avgTTR, &avgLTL, &avg); + res = _mm_sub_epi8(src, avg); + _mm_storeu_si128((__m128i*)&out[i], res); + } + if (i != num_pixels) { + VP8LPredictorsSub_C[10](in + i, upper + i, num_pixels - i, out + i); + } +} + +// Predictor11: select. +static void GetSumAbsDiff32_SSE2(const __m128i* const A, const __m128i* const B, + __m128i* const out) { + // We can unpack with any value on the upper 32 bits, provided it's the same + // on both operands (to that their sum of abs diff is zero). Here we use *A. + const __m128i A_lo = _mm_unpacklo_epi32(*A, *A); + const __m128i B_lo = _mm_unpacklo_epi32(*B, *A); + const __m128i A_hi = _mm_unpackhi_epi32(*A, *A); + const __m128i B_hi = _mm_unpackhi_epi32(*B, *A); + const __m128i s_lo = _mm_sad_epu8(A_lo, B_lo); + const __m128i s_hi = _mm_sad_epu8(A_hi, B_hi); + *out = _mm_packs_epi32(s_lo, s_hi); +} + +static void PredictorSub11_SSE2(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + for (i = 0; i + 4 <= num_pixels; i += 4) { + const __m128i L = _mm_loadu_si128((const __m128i*)&in[i - 1]); + const __m128i T = _mm_loadu_si128((const __m128i*)&upper[i]); + const __m128i TL = _mm_loadu_si128((const __m128i*)&upper[i - 1]); + const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); + __m128i pa, pb; + GetSumAbsDiff32_SSE2(&T, &TL, &pa); // pa = sum |T-TL| + GetSumAbsDiff32_SSE2(&L, &TL, &pb); // pb = sum |L-TL| + { + const __m128i mask = _mm_cmpgt_epi32(pb, pa); + const __m128i A = _mm_and_si128(mask, L); + const __m128i B = _mm_andnot_si128(mask, T); + const __m128i pred = _mm_or_si128(A, B); // pred = (L > T)? L : T + const __m128i res = _mm_sub_epi8(src, pred); + _mm_storeu_si128((__m128i*)&out[i], res); + } + } + if (i != num_pixels) { + VP8LPredictorsSub_C[11](in + i, upper + i, num_pixels - i, out + i); + } +} + +// Predictor12: ClampedSubSubtractFull. +static void PredictorSub12_SSE2(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + const __m128i zero = _mm_setzero_si128(); + for (i = 0; i + 4 <= num_pixels; i += 4) { + const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); + const __m128i L = _mm_loadu_si128((const __m128i*)&in[i - 1]); + const __m128i L_lo = _mm_unpacklo_epi8(L, zero); + const __m128i L_hi = _mm_unpackhi_epi8(L, zero); + const __m128i T = _mm_loadu_si128((const __m128i*)&upper[i]); + const __m128i T_lo = _mm_unpacklo_epi8(T, zero); + const __m128i T_hi = _mm_unpackhi_epi8(T, zero); + const __m128i TL = _mm_loadu_si128((const __m128i*)&upper[i - 1]); + const __m128i TL_lo = _mm_unpacklo_epi8(TL, zero); + const __m128i TL_hi = _mm_unpackhi_epi8(TL, zero); + const __m128i diff_lo = _mm_sub_epi16(T_lo, TL_lo); + const __m128i diff_hi = _mm_sub_epi16(T_hi, TL_hi); + const __m128i pred_lo = _mm_add_epi16(L_lo, diff_lo); + const __m128i pred_hi = _mm_add_epi16(L_hi, diff_hi); + const __m128i pred = _mm_packus_epi16(pred_lo, pred_hi); + const __m128i res = _mm_sub_epi8(src, pred); + _mm_storeu_si128((__m128i*)&out[i], res); + } + if (i != num_pixels) { + VP8LPredictorsSub_C[12](in + i, upper + i, num_pixels - i, out + i); + } +} + +// Predictors13: ClampedAddSubtractHalf +static void PredictorSub13_SSE2(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + const __m128i zero = _mm_setzero_si128(); + for (i = 0; i + 2 <= num_pixels; i += 2) { + // we can only process two pixels at a time + const __m128i L = _mm_loadl_epi64((const __m128i*)&in[i - 1]); + const __m128i src = _mm_loadl_epi64((const __m128i*)&in[i]); + const __m128i T = _mm_loadl_epi64((const __m128i*)&upper[i]); + const __m128i TL = _mm_loadl_epi64((const __m128i*)&upper[i - 1]); + const __m128i L_lo = _mm_unpacklo_epi8(L, zero); + const __m128i T_lo = _mm_unpacklo_epi8(T, zero); + const __m128i TL_lo = _mm_unpacklo_epi8(TL, zero); + const __m128i sum = _mm_add_epi16(T_lo, L_lo); + const __m128i avg = _mm_srli_epi16(sum, 1); + const __m128i A1 = _mm_sub_epi16(avg, TL_lo); + const __m128i bit_fix = _mm_cmpgt_epi16(TL_lo, avg); + const __m128i A2 = _mm_sub_epi16(A1, bit_fix); + const __m128i A3 = _mm_srai_epi16(A2, 1); + const __m128i A4 = _mm_add_epi16(avg, A3); + const __m128i pred = _mm_packus_epi16(A4, A4); + const __m128i res = _mm_sub_epi8(src, pred); + _mm_storel_epi64((__m128i*)&out[i], res); + } + if (i != num_pixels) { + VP8LPredictorsSub_C[13](in + i, upper + i, num_pixels - i, out + i); + } +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8LEncDspInitSSE2(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitSSE2(void) { + VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed_SSE2; + VP8LTransformColor = TransformColor_SSE2; + VP8LCollectColorBlueTransforms = CollectColorBlueTransforms_SSE2; + VP8LCollectColorRedTransforms = CollectColorRedTransforms_SSE2; + VP8LAddVector = AddVector_SSE2; + VP8LAddVectorEq = AddVectorEq_SSE2; +#if !defined(DONT_USE_COMBINED_SHANNON_ENTROPY_SSE2_FUNC) + VP8LCombinedShannonEntropy = CombinedShannonEntropy_SSE2; +#endif + VP8LVectorMismatch = VectorMismatch_SSE2; + VP8LBundleColorMap = BundleColorMap_SSE2; + + VP8LPredictorsSub[0] = PredictorSub0_SSE2; + VP8LPredictorsSub[1] = PredictorSub1_SSE2; + VP8LPredictorsSub[2] = PredictorSub2_SSE2; + VP8LPredictorsSub[3] = PredictorSub3_SSE2; + VP8LPredictorsSub[4] = PredictorSub4_SSE2; + VP8LPredictorsSub[5] = PredictorSub5_SSE2; + VP8LPredictorsSub[6] = PredictorSub6_SSE2; + VP8LPredictorsSub[7] = PredictorSub7_SSE2; + VP8LPredictorsSub[8] = PredictorSub8_SSE2; + VP8LPredictorsSub[9] = PredictorSub9_SSE2; + VP8LPredictorsSub[10] = PredictorSub10_SSE2; + VP8LPredictorsSub[11] = PredictorSub11_SSE2; + VP8LPredictorsSub[12] = PredictorSub12_SSE2; + VP8LPredictorsSub[13] = PredictorSub13_SSE2; + VP8LPredictorsSub[14] = PredictorSub0_SSE2; // <- padding security sentinels + VP8LPredictorsSub[15] = PredictorSub0_SSE2; +} + +#else // !WEBP_USE_SSE2 + +WEBP_DSP_INIT_STUB(VP8LEncDspInitSSE2) + +#endif // WEBP_USE_SSE2 diff --git a/third-party/webp/libwebp/src/dsp/lossless_enc_sse41.c b/third-party/webp/libwebp/src/dsp/lossless_enc_sse41.c new file mode 100644 index 0000000000..7ab83c2604 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/lossless_enc_sse41.c @@ -0,0 +1,205 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE4.1 variant of methods for lossless encoder +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE41) +#include +#include +#include "src/dsp/lossless.h" + +//------------------------------------------------------------------------------ +// Cost operations. + +static WEBP_INLINE uint32_t HorizontalSum_SSE41(__m128i cost) { + cost = _mm_add_epi32(cost, _mm_srli_si128(cost, 8)); + cost = _mm_add_epi32(cost, _mm_srli_si128(cost, 4)); + return _mm_cvtsi128_si32(cost); +} + +static uint32_t ExtraCost_SSE41(const uint32_t* const a, int length) { + int i; + __m128i cost = _mm_set_epi32(2 * a[7], 2 * a[6], a[5], a[4]); + assert(length % 8 == 0); + + for (i = 8; i + 8 <= length; i += 8) { + const int j = (i - 2) >> 1; + const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[i]); + const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[i + 4]); + const __m128i w = _mm_set_epi32(j + 3, j + 2, j + 1, j); + const __m128i a2 = _mm_hadd_epi32(a0, a1); + const __m128i mul = _mm_mullo_epi32(a2, w); + cost = _mm_add_epi32(mul, cost); + } + return HorizontalSum_SSE41(cost); +} + +static uint32_t ExtraCostCombined_SSE41(const uint32_t* const a, + const uint32_t* const b, int length) { + int i; + __m128i cost = _mm_add_epi32(_mm_set_epi32(2 * a[7], 2 * a[6], a[5], a[4]), + _mm_set_epi32(2 * b[7], 2 * b[6], b[5], b[4])); + assert(length % 8 == 0); + + for (i = 8; i + 8 <= length; i += 8) { + const int j = (i - 2) >> 1; + const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[i]); + const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[i + 4]); + const __m128i b0 = _mm_loadu_si128((const __m128i*)&b[i]); + const __m128i b1 = _mm_loadu_si128((const __m128i*)&b[i + 4]); + const __m128i w = _mm_set_epi32(j + 3, j + 2, j + 1, j); + const __m128i a2 = _mm_hadd_epi32(a0, a1); + const __m128i b2 = _mm_hadd_epi32(b0, b1); + const __m128i mul = _mm_mullo_epi32(_mm_add_epi32(a2, b2), w); + cost = _mm_add_epi32(mul, cost); + } + return HorizontalSum_SSE41(cost); +} + +//------------------------------------------------------------------------------ +// Subtract-Green Transform + +static void SubtractGreenFromBlueAndRed_SSE41(uint32_t* argb_data, + int num_pixels) { + int i; + const __m128i kCstShuffle = _mm_set_epi8(-1, 13, -1, 13, -1, 9, -1, 9, + -1, 5, -1, 5, -1, 1, -1, 1); + for (i = 0; i + 4 <= num_pixels; i += 4) { + const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); + const __m128i in_0g0g = _mm_shuffle_epi8(in, kCstShuffle); + const __m128i out = _mm_sub_epi8(in, in_0g0g); + _mm_storeu_si128((__m128i*)&argb_data[i], out); + } + // fallthrough and finish off with plain-C + if (i != num_pixels) { + VP8LSubtractGreenFromBlueAndRed_C(argb_data + i, num_pixels - i); + } +} + +//------------------------------------------------------------------------------ +// Color Transform + +// For sign-extended multiplying constants, pre-shifted by 5: +#define CST_5b(X) (((int16_t)((uint16_t)(X) << 8)) >> 5) + +#define MK_CST_16(HI, LO) \ + _mm_set1_epi32((int)(((uint32_t)(HI) << 16) | ((LO) & 0xffff))) + +static void CollectColorBlueTransforms_SSE41(const uint32_t* argb, int stride, + int tile_width, int tile_height, + int green_to_blue, int red_to_blue, + int histo[]) { + const __m128i mult = + MK_CST_16(CST_5b(red_to_blue) + 256,CST_5b(green_to_blue)); + const __m128i perm = + _mm_setr_epi8(-1, 1, -1, 2, -1, 5, -1, 6, -1, 9, -1, 10, -1, 13, -1, 14); + if (tile_width >= 4) { + int y; + for (y = 0; y < tile_height; ++y) { + const uint32_t* const src = argb + y * stride; + const __m128i A1 = _mm_loadu_si128((const __m128i*)src); + const __m128i B1 = _mm_shuffle_epi8(A1, perm); + const __m128i C1 = _mm_mulhi_epi16(B1, mult); + const __m128i D1 = _mm_sub_epi16(A1, C1); + __m128i E = _mm_add_epi16(_mm_srli_epi32(D1, 16), D1); + int x; + for (x = 4; x + 4 <= tile_width; x += 4) { + const __m128i A2 = _mm_loadu_si128((const __m128i*)(src + x)); + __m128i B2, C2, D2; + ++histo[_mm_extract_epi8(E, 0)]; + B2 = _mm_shuffle_epi8(A2, perm); + ++histo[_mm_extract_epi8(E, 4)]; + C2 = _mm_mulhi_epi16(B2, mult); + ++histo[_mm_extract_epi8(E, 8)]; + D2 = _mm_sub_epi16(A2, C2); + ++histo[_mm_extract_epi8(E, 12)]; + E = _mm_add_epi16(_mm_srli_epi32(D2, 16), D2); + } + ++histo[_mm_extract_epi8(E, 0)]; + ++histo[_mm_extract_epi8(E, 4)]; + ++histo[_mm_extract_epi8(E, 8)]; + ++histo[_mm_extract_epi8(E, 12)]; + } + } + { + const int left_over = tile_width & 3; + if (left_over > 0) { + VP8LCollectColorBlueTransforms_C(argb + tile_width - left_over, stride, + left_over, tile_height, + green_to_blue, red_to_blue, histo); + } + } +} + +static void CollectColorRedTransforms_SSE41(const uint32_t* argb, int stride, + int tile_width, int tile_height, + int green_to_red, int histo[]) { + + const __m128i mult = MK_CST_16(0, CST_5b(green_to_red)); + const __m128i mask_g = _mm_set1_epi32(0x0000ff00); + if (tile_width >= 4) { + int y; + for (y = 0; y < tile_height; ++y) { + const uint32_t* const src = argb + y * stride; + const __m128i A1 = _mm_loadu_si128((const __m128i*)src); + const __m128i B1 = _mm_and_si128(A1, mask_g); + const __m128i C1 = _mm_madd_epi16(B1, mult); + __m128i D = _mm_sub_epi16(A1, C1); + int x; + for (x = 4; x + 4 <= tile_width; x += 4) { + const __m128i A2 = _mm_loadu_si128((const __m128i*)(src + x)); + __m128i B2, C2; + ++histo[_mm_extract_epi8(D, 2)]; + B2 = _mm_and_si128(A2, mask_g); + ++histo[_mm_extract_epi8(D, 6)]; + C2 = _mm_madd_epi16(B2, mult); + ++histo[_mm_extract_epi8(D, 10)]; + ++histo[_mm_extract_epi8(D, 14)]; + D = _mm_sub_epi16(A2, C2); + } + ++histo[_mm_extract_epi8(D, 2)]; + ++histo[_mm_extract_epi8(D, 6)]; + ++histo[_mm_extract_epi8(D, 10)]; + ++histo[_mm_extract_epi8(D, 14)]; + } + } + { + const int left_over = tile_width & 3; + if (left_over > 0) { + VP8LCollectColorRedTransforms_C(argb + tile_width - left_over, stride, + left_over, tile_height, green_to_red, + histo); + } + } +} + +#undef MK_CST_16 + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8LEncDspInitSSE41(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitSSE41(void) { + VP8LExtraCost = ExtraCost_SSE41; + VP8LExtraCostCombined = ExtraCostCombined_SSE41; + VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed_SSE41; + VP8LCollectColorBlueTransforms = CollectColorBlueTransforms_SSE41; + VP8LCollectColorRedTransforms = CollectColorRedTransforms_SSE41; +} + +#else // !WEBP_USE_SSE41 + +WEBP_DSP_INIT_STUB(VP8LEncDspInitSSE41) + +#endif // WEBP_USE_SSE41 diff --git a/third-party/webp/libwebp/src/dsp/lossless_mips_dsp_r2.c b/third-party/webp/libwebp/src/dsp/lossless_mips_dsp_r2.c new file mode 100644 index 0000000000..bfe5ea6b38 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/lossless_mips_dsp_r2.c @@ -0,0 +1,701 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Image transforms and color space conversion methods for lossless decoder. +// +// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) +// Jovan Zelincevic (jovan.zelincevic@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MIPS_DSP_R2) + +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" + +#define MAP_COLOR_FUNCS(FUNC_NAME, TYPE, GET_INDEX, GET_VALUE) \ +static void FUNC_NAME(const TYPE* src, \ + const uint32_t* const color_map, \ + TYPE* dst, int y_start, int y_end, \ + int width) { \ + int y; \ + for (y = y_start; y < y_end; ++y) { \ + int x; \ + for (x = 0; x < (width >> 2); ++x) { \ + int tmp1, tmp2, tmp3, tmp4; \ + __asm__ volatile ( \ + ".ifc " #TYPE ", uint8_t \n\t" \ + "lbu %[tmp1], 0(%[src]) \n\t" \ + "lbu %[tmp2], 1(%[src]) \n\t" \ + "lbu %[tmp3], 2(%[src]) \n\t" \ + "lbu %[tmp4], 3(%[src]) \n\t" \ + "addiu %[src], %[src], 4 \n\t" \ + ".endif \n\t" \ + ".ifc " #TYPE ", uint32_t \n\t" \ + "lw %[tmp1], 0(%[src]) \n\t" \ + "lw %[tmp2], 4(%[src]) \n\t" \ + "lw %[tmp3], 8(%[src]) \n\t" \ + "lw %[tmp4], 12(%[src]) \n\t" \ + "ext %[tmp1], %[tmp1], 8, 8 \n\t" \ + "ext %[tmp2], %[tmp2], 8, 8 \n\t" \ + "ext %[tmp3], %[tmp3], 8, 8 \n\t" \ + "ext %[tmp4], %[tmp4], 8, 8 \n\t" \ + "addiu %[src], %[src], 16 \n\t" \ + ".endif \n\t" \ + "sll %[tmp1], %[tmp1], 2 \n\t" \ + "sll %[tmp2], %[tmp2], 2 \n\t" \ + "sll %[tmp3], %[tmp3], 2 \n\t" \ + "sll %[tmp4], %[tmp4], 2 \n\t" \ + "lwx %[tmp1], %[tmp1](%[color_map]) \n\t" \ + "lwx %[tmp2], %[tmp2](%[color_map]) \n\t" \ + "lwx %[tmp3], %[tmp3](%[color_map]) \n\t" \ + "lwx %[tmp4], %[tmp4](%[color_map]) \n\t" \ + ".ifc " #TYPE ", uint8_t \n\t" \ + "ext %[tmp1], %[tmp1], 8, 8 \n\t" \ + "ext %[tmp2], %[tmp2], 8, 8 \n\t" \ + "ext %[tmp3], %[tmp3], 8, 8 \n\t" \ + "ext %[tmp4], %[tmp4], 8, 8 \n\t" \ + "sb %[tmp1], 0(%[dst]) \n\t" \ + "sb %[tmp2], 1(%[dst]) \n\t" \ + "sb %[tmp3], 2(%[dst]) \n\t" \ + "sb %[tmp4], 3(%[dst]) \n\t" \ + "addiu %[dst], %[dst], 4 \n\t" \ + ".endif \n\t" \ + ".ifc " #TYPE ", uint32_t \n\t" \ + "sw %[tmp1], 0(%[dst]) \n\t" \ + "sw %[tmp2], 4(%[dst]) \n\t" \ + "sw %[tmp3], 8(%[dst]) \n\t" \ + "sw %[tmp4], 12(%[dst]) \n\t" \ + "addiu %[dst], %[dst], 16 \n\t" \ + ".endif \n\t" \ + : [tmp1]"=&r"(tmp1), [tmp2]"=&r"(tmp2), [tmp3]"=&r"(tmp3), \ + [tmp4]"=&r"(tmp4), [src]"+&r"(src), [dst]"+r"(dst) \ + : [color_map]"r"(color_map) \ + : "memory" \ + ); \ + } \ + for (x = 0; x < (width & 3); ++x) { \ + *dst++ = GET_VALUE(color_map[GET_INDEX(*src++)]); \ + } \ + } \ +} + +MAP_COLOR_FUNCS(MapARGB_MIPSdspR2, uint32_t, VP8GetARGBIndex, VP8GetARGBValue) +MAP_COLOR_FUNCS(MapAlpha_MIPSdspR2, uint8_t, VP8GetAlphaIndex, VP8GetAlphaValue) + +#undef MAP_COLOR_FUNCS + +static WEBP_INLINE uint32_t ClampedAddSubtractFull(uint32_t c0, uint32_t c1, + uint32_t c2) { + int temp0, temp1, temp2, temp3, temp4, temp5; + __asm__ volatile ( + "preceu.ph.qbr %[temp1], %[c0] \n\t" + "preceu.ph.qbl %[temp2], %[c0] \n\t" + "preceu.ph.qbr %[temp3], %[c1] \n\t" + "preceu.ph.qbl %[temp4], %[c1] \n\t" + "preceu.ph.qbr %[temp5], %[c2] \n\t" + "preceu.ph.qbl %[temp0], %[c2] \n\t" + "subq.ph %[temp3], %[temp3], %[temp5] \n\t" + "subq.ph %[temp4], %[temp4], %[temp0] \n\t" + "addq.ph %[temp1], %[temp1], %[temp3] \n\t" + "addq.ph %[temp2], %[temp2], %[temp4] \n\t" + "shll_s.ph %[temp1], %[temp1], 7 \n\t" + "shll_s.ph %[temp2], %[temp2], 7 \n\t" + "precrqu_s.qb.ph %[temp2], %[temp2], %[temp1] \n\t" + : [temp0]"=r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5) + : [c0]"r"(c0), [c1]"r"(c1), [c2]"r"(c2) + : "memory" + ); + return temp2; +} + +static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1, + uint32_t c2) { + int temp0, temp1, temp2, temp3, temp4, temp5; + __asm__ volatile ( + "adduh.qb %[temp5], %[c0], %[c1] \n\t" + "preceu.ph.qbr %[temp3], %[c2] \n\t" + "preceu.ph.qbr %[temp1], %[temp5] \n\t" + "preceu.ph.qbl %[temp2], %[temp5] \n\t" + "preceu.ph.qbl %[temp4], %[c2] \n\t" + "subq.ph %[temp3], %[temp1], %[temp3] \n\t" + "subq.ph %[temp4], %[temp2], %[temp4] \n\t" + "shrl.ph %[temp5], %[temp3], 15 \n\t" + "shrl.ph %[temp0], %[temp4], 15 \n\t" + "addq.ph %[temp3], %[temp3], %[temp5] \n\t" + "addq.ph %[temp4], %[temp0], %[temp4] \n\t" + "shra.ph %[temp3], %[temp3], 1 \n\t" + "shra.ph %[temp4], %[temp4], 1 \n\t" + "addq.ph %[temp1], %[temp1], %[temp3] \n\t" + "addq.ph %[temp2], %[temp2], %[temp4] \n\t" + "shll_s.ph %[temp1], %[temp1], 7 \n\t" + "shll_s.ph %[temp2], %[temp2], 7 \n\t" + "precrqu_s.qb.ph %[temp1], %[temp2], %[temp1] \n\t" + : [temp0]"=r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=r"(temp4), [temp5]"=&r"(temp5) + : [c0]"r"(c0), [c1]"r"(c1), [c2]"r"(c2) + : "memory" + ); + return temp1; +} + +static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) { + int temp0, temp1, temp2, temp3, temp4, temp5; + __asm__ volatile ( + "cmpgdu.lt.qb %[temp1], %[c], %[b] \n\t" + "pick.qb %[temp1], %[b], %[c] \n\t" + "pick.qb %[temp2], %[c], %[b] \n\t" + "cmpgdu.lt.qb %[temp4], %[c], %[a] \n\t" + "pick.qb %[temp4], %[a], %[c] \n\t" + "pick.qb %[temp5], %[c], %[a] \n\t" + "subu.qb %[temp3], %[temp1], %[temp2] \n\t" + "subu.qb %[temp0], %[temp4], %[temp5] \n\t" + "raddu.w.qb %[temp3], %[temp3] \n\t" + "raddu.w.qb %[temp0], %[temp0] \n\t" + "subu %[temp3], %[temp3], %[temp0] \n\t" + "slti %[temp0], %[temp3], 0x1 \n\t" + "movz %[a], %[b], %[temp0] \n\t" + : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [temp0]"=&r"(temp0), + [a]"+&r"(a) + : [b]"r"(b), [c]"r"(c) + ); + return a; +} + +static WEBP_INLINE uint32_t Average2(uint32_t a0, uint32_t a1) { + __asm__ volatile ( + "adduh.qb %[a0], %[a0], %[a1] \n\t" + : [a0]"+r"(a0) + : [a1]"r"(a1) + ); + return a0; +} + +static WEBP_INLINE uint32_t Average3(uint32_t a0, uint32_t a1, uint32_t a2) { + return Average2(Average2(a0, a2), a1); +} + +static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1, + uint32_t a2, uint32_t a3) { + return Average2(Average2(a0, a1), Average2(a2, a3)); +} + +static uint32_t Predictor5_MIPSdspR2(const uint32_t* const left, + const uint32_t* const top) { + return Average3(*left, top[0], top[1]); +} + +static uint32_t Predictor6_MIPSdspR2(const uint32_t* const left, + const uint32_t* const top) { + return Average2(*left, top[-1]); +} + +static uint32_t Predictor7_MIPSdspR2(const uint32_t* const left, + const uint32_t* const top) { + return Average2(*left, top[0]); +} + +static uint32_t Predictor8_MIPSdspR2(const uint32_t* const left, + const uint32_t* const top) { + (void)left; + return Average2(top[-1], top[0]); +} + +static uint32_t Predictor9_MIPSdspR2(const uint32_t* const left, + const uint32_t* const top) { + (void)left; + return Average2(top[0], top[1]); +} + +static uint32_t Predictor10_MIPSdspR2(const uint32_t* const left, + const uint32_t* const top) { + return Average4(*left, top[-1], top[0], top[1]); +} + +static uint32_t Predictor11_MIPSdspR2(const uint32_t* const left, + const uint32_t* const top) { + return Select(top[0], *left, top[-1]); +} + +static uint32_t Predictor12_MIPSdspR2(const uint32_t* const left, + const uint32_t* const top) { + return ClampedAddSubtractFull(*left, top[0], top[-1]); +} + +static uint32_t Predictor13_MIPSdspR2(const uint32_t* const left, + const uint32_t* const top) { + return ClampedAddSubtractHalf(*left, top[0], top[-1]); +} + +// Add green to blue and red channels (i.e. perform the inverse transform of +// 'subtract green'). +static void AddGreenToBlueAndRed_MIPSdspR2(const uint32_t* src, int num_pixels, + uint32_t* dst) { + uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + const uint32_t* const p_loop1_end = src + (num_pixels & ~3); + const uint32_t* const p_loop2_end = src + num_pixels; + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "beq %[src], %[p_loop1_end], 3f \n\t" + " nop \n\t" + "0: \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "lw %[temp1], 4(%[src]) \n\t" + "lw %[temp2], 8(%[src]) \n\t" + "lw %[temp3], 12(%[src]) \n\t" + "ext %[temp4], %[temp0], 8, 8 \n\t" + "ext %[temp5], %[temp1], 8, 8 \n\t" + "ext %[temp6], %[temp2], 8, 8 \n\t" + "ext %[temp7], %[temp3], 8, 8 \n\t" + "addiu %[src], %[src], 16 \n\t" + "addiu %[dst], %[dst], 16 \n\t" + "replv.ph %[temp4], %[temp4] \n\t" + "replv.ph %[temp5], %[temp5] \n\t" + "replv.ph %[temp6], %[temp6] \n\t" + "replv.ph %[temp7], %[temp7] \n\t" + "addu.qb %[temp0], %[temp0], %[temp4] \n\t" + "addu.qb %[temp1], %[temp1], %[temp5] \n\t" + "addu.qb %[temp2], %[temp2], %[temp6] \n\t" + "addu.qb %[temp3], %[temp3], %[temp7] \n\t" + "sw %[temp0], -16(%[dst]) \n\t" + "sw %[temp1], -12(%[dst]) \n\t" + "sw %[temp2], -8(%[dst]) \n\t" + "bne %[src], %[p_loop1_end], 0b \n\t" + " sw %[temp3], -4(%[dst]) \n\t" + "3: \n\t" + "beq %[src], %[p_loop2_end], 2f \n\t" + " nop \n\t" + "1: \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "addiu %[src], %[src], 4 \n\t" + "addiu %[dst], %[dst], 4 \n\t" + "ext %[temp4], %[temp0], 8, 8 \n\t" + "replv.ph %[temp4], %[temp4] \n\t" + "addu.qb %[temp0], %[temp0], %[temp4] \n\t" + "bne %[src], %[p_loop2_end], 1b \n\t" + " sw %[temp0], -4(%[dst]) \n\t" + "2: \n\t" + ".set pop \n\t" + : [dst]"+&r"(dst), [src]"+&r"(src), [temp0]"=&r"(temp0), + [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [temp6]"=&r"(temp6), + [temp7]"=&r"(temp7) + : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end) + : "memory" + ); +} + +static void TransformColorInverse_MIPSdspR2(const VP8LMultipliers* const m, + const uint32_t* src, int num_pixels, + uint32_t* dst) { + int temp0, temp1, temp2, temp3, temp4, temp5; + uint32_t argb, argb1, new_red; + const uint32_t G_to_R = m->green_to_red_; + const uint32_t G_to_B = m->green_to_blue_; + const uint32_t R_to_B = m->red_to_blue_; + const uint32_t* const p_loop_end = src + (num_pixels & ~1); + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "beq %[src], %[p_loop_end], 1f \n\t" + " nop \n\t" + "replv.ph %[temp0], %[G_to_R] \n\t" + "replv.ph %[temp1], %[G_to_B] \n\t" + "replv.ph %[temp2], %[R_to_B] \n\t" + "shll.ph %[temp0], %[temp0], 8 \n\t" + "shll.ph %[temp1], %[temp1], 8 \n\t" + "shll.ph %[temp2], %[temp2], 8 \n\t" + "shra.ph %[temp0], %[temp0], 8 \n\t" + "shra.ph %[temp1], %[temp1], 8 \n\t" + "shra.ph %[temp2], %[temp2], 8 \n\t" + "0: \n\t" + "lw %[argb], 0(%[src]) \n\t" + "lw %[argb1], 4(%[src]) \n\t" + "sw %[argb], 0(%[dst]) \n\t" + "sw %[argb1], 4(%[dst]) \n\t" + "addiu %[src], %[src], 8 \n\t" + "addiu %[dst], %[dst], 8 \n\t" + "precrq.qb.ph %[temp3], %[argb], %[argb1] \n\t" + "preceu.ph.qbra %[temp3], %[temp3] \n\t" + "shll.ph %[temp3], %[temp3], 8 \n\t" + "shra.ph %[temp3], %[temp3], 8 \n\t" + "mul.ph %[temp5], %[temp3], %[temp0] \n\t" + "mul.ph %[temp3], %[temp3], %[temp1] \n\t" + "precrq.ph.w %[new_red], %[argb], %[argb1] \n\t" + "ins %[argb1], %[argb], 16, 16 \n\t" + "shra.ph %[temp5], %[temp5], 5 \n\t" + "shra.ph %[temp3], %[temp3], 5 \n\t" + "addu.ph %[new_red], %[new_red], %[temp5] \n\t" + "addu.ph %[argb1], %[argb1], %[temp3] \n\t" + "preceu.ph.qbra %[temp5], %[new_red] \n\t" + "shll.ph %[temp4], %[temp5], 8 \n\t" + "shra.ph %[temp4], %[temp4], 8 \n\t" + "mul.ph %[temp4], %[temp4], %[temp2] \n\t" + "sb %[temp5], -2(%[dst]) \n\t" + "sra %[temp5], %[temp5], 16 \n\t" + "shra.ph %[temp4], %[temp4], 5 \n\t" + "addu.ph %[argb1], %[argb1], %[temp4] \n\t" + "preceu.ph.qbra %[temp3], %[argb1] \n\t" + "sb %[temp5], -6(%[dst]) \n\t" + "sb %[temp3], -4(%[dst]) \n\t" + "sra %[temp3], %[temp3], 16 \n\t" + "bne %[src], %[p_loop_end], 0b \n\t" + " sb %[temp3], -8(%[dst]) \n\t" + "1: \n\t" + ".set pop \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [new_red]"=&r"(new_red), [argb]"=&r"(argb), + [argb1]"=&r"(argb1), [dst]"+&r"(dst), [src]"+&r"(src) + : [G_to_R]"r"(G_to_R), [R_to_B]"r"(R_to_B), + [G_to_B]"r"(G_to_B), [p_loop_end]"r"(p_loop_end) + : "memory", "hi", "lo" + ); + + // Fall-back to C-version for left-overs. + if (num_pixels & 1) VP8LTransformColorInverse_C(m, src, 1, dst); +} + +static void ConvertBGRAToRGB_MIPSdspR2(const uint32_t* src, + int num_pixels, uint8_t* dst) { + int temp0, temp1, temp2, temp3; + const uint32_t* const p_loop1_end = src + (num_pixels & ~3); + const uint32_t* const p_loop2_end = src + num_pixels; + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "beq %[src], %[p_loop1_end], 3f \n\t" + " nop \n\t" + "0: \n\t" + "lw %[temp3], 12(%[src]) \n\t" + "lw %[temp2], 8(%[src]) \n\t" + "lw %[temp1], 4(%[src]) \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "ins %[temp3], %[temp2], 24, 8 \n\t" + "sll %[temp2], %[temp2], 8 \n\t" + "rotr %[temp3], %[temp3], 16 \n\t" + "ins %[temp2], %[temp1], 0, 16 \n\t" + "sll %[temp1], %[temp1], 8 \n\t" + "wsbh %[temp3], %[temp3] \n\t" + "balign %[temp0], %[temp1], 1 \n\t" + "wsbh %[temp2], %[temp2] \n\t" + "wsbh %[temp0], %[temp0] \n\t" + "usw %[temp3], 8(%[dst]) \n\t" + "rotr %[temp0], %[temp0], 16 \n\t" + "usw %[temp2], 4(%[dst]) \n\t" + "addiu %[src], %[src], 16 \n\t" + "usw %[temp0], 0(%[dst]) \n\t" + "bne %[src], %[p_loop1_end], 0b \n\t" + " addiu %[dst], %[dst], 12 \n\t" + "3: \n\t" + "beq %[src], %[p_loop2_end], 2f \n\t" + " nop \n\t" + "1: \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "addiu %[src], %[src], 4 \n\t" + "wsbh %[temp1], %[temp0] \n\t" + "addiu %[dst], %[dst], 3 \n\t" + "ush %[temp1], -2(%[dst]) \n\t" + "sra %[temp0], %[temp0], 16 \n\t" + "bne %[src], %[p_loop2_end], 1b \n\t" + " sb %[temp0], -3(%[dst]) \n\t" + "2: \n\t" + ".set pop \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [dst]"+&r"(dst), [src]"+&r"(src) + : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end) + : "memory" + ); +} + +static void ConvertBGRAToRGBA_MIPSdspR2(const uint32_t* src, + int num_pixels, uint8_t* dst) { + int temp0, temp1, temp2, temp3; + const uint32_t* const p_loop1_end = src + (num_pixels & ~3); + const uint32_t* const p_loop2_end = src + num_pixels; + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "beq %[src], %[p_loop1_end], 3f \n\t" + " nop \n\t" + "0: \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "lw %[temp1], 4(%[src]) \n\t" + "lw %[temp2], 8(%[src]) \n\t" + "lw %[temp3], 12(%[src]) \n\t" + "wsbh %[temp0], %[temp0] \n\t" + "wsbh %[temp1], %[temp1] \n\t" + "wsbh %[temp2], %[temp2] \n\t" + "wsbh %[temp3], %[temp3] \n\t" + "addiu %[src], %[src], 16 \n\t" + "balign %[temp0], %[temp0], 1 \n\t" + "balign %[temp1], %[temp1], 1 \n\t" + "balign %[temp2], %[temp2], 1 \n\t" + "balign %[temp3], %[temp3], 1 \n\t" + "usw %[temp0], 0(%[dst]) \n\t" + "usw %[temp1], 4(%[dst]) \n\t" + "usw %[temp2], 8(%[dst]) \n\t" + "usw %[temp3], 12(%[dst]) \n\t" + "bne %[src], %[p_loop1_end], 0b \n\t" + " addiu %[dst], %[dst], 16 \n\t" + "3: \n\t" + "beq %[src], %[p_loop2_end], 2f \n\t" + " nop \n\t" + "1: \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "wsbh %[temp0], %[temp0] \n\t" + "addiu %[src], %[src], 4 \n\t" + "balign %[temp0], %[temp0], 1 \n\t" + "usw %[temp0], 0(%[dst]) \n\t" + "bne %[src], %[p_loop2_end], 1b \n\t" + " addiu %[dst], %[dst], 4 \n\t" + "2: \n\t" + ".set pop \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [dst]"+&r"(dst), [src]"+&r"(src) + : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end) + : "memory" + ); +} + +static void ConvertBGRAToRGBA4444_MIPSdspR2(const uint32_t* src, + int num_pixels, uint8_t* dst) { + int temp0, temp1, temp2, temp3, temp4, temp5; + const uint32_t* const p_loop1_end = src + (num_pixels & ~3); + const uint32_t* const p_loop2_end = src + num_pixels; + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "beq %[src], %[p_loop1_end], 3f \n\t" + " nop \n\t" + "0: \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "lw %[temp1], 4(%[src]) \n\t" + "lw %[temp2], 8(%[src]) \n\t" + "lw %[temp3], 12(%[src]) \n\t" + "ext %[temp4], %[temp0], 28, 4 \n\t" + "ext %[temp5], %[temp0], 12, 4 \n\t" + "ins %[temp0], %[temp4], 0, 4 \n\t" + "ext %[temp4], %[temp1], 28, 4 \n\t" + "ins %[temp0], %[temp5], 16, 4 \n\t" + "ext %[temp5], %[temp1], 12, 4 \n\t" + "ins %[temp1], %[temp4], 0, 4 \n\t" + "ext %[temp4], %[temp2], 28, 4 \n\t" + "ins %[temp1], %[temp5], 16, 4 \n\t" + "ext %[temp5], %[temp2], 12, 4 \n\t" + "ins %[temp2], %[temp4], 0, 4 \n\t" + "ext %[temp4], %[temp3], 28, 4 \n\t" + "ins %[temp2], %[temp5], 16, 4 \n\t" + "ext %[temp5], %[temp3], 12, 4 \n\t" + "ins %[temp3], %[temp4], 0, 4 \n\t" + "precr.qb.ph %[temp1], %[temp1], %[temp0] \n\t" + "ins %[temp3], %[temp5], 16, 4 \n\t" + "addiu %[src], %[src], 16 \n\t" + "precr.qb.ph %[temp3], %[temp3], %[temp2] \n\t" +#if (WEBP_SWAP_16BIT_CSP == 1) + "usw %[temp1], 0(%[dst]) \n\t" + "usw %[temp3], 4(%[dst]) \n\t" +#else + "wsbh %[temp1], %[temp1] \n\t" + "wsbh %[temp3], %[temp3] \n\t" + "usw %[temp1], 0(%[dst]) \n\t" + "usw %[temp3], 4(%[dst]) \n\t" +#endif + "bne %[src], %[p_loop1_end], 0b \n\t" + " addiu %[dst], %[dst], 8 \n\t" + "3: \n\t" + "beq %[src], %[p_loop2_end], 2f \n\t" + " nop \n\t" + "1: \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "ext %[temp4], %[temp0], 28, 4 \n\t" + "ext %[temp5], %[temp0], 12, 4 \n\t" + "ins %[temp0], %[temp4], 0, 4 \n\t" + "ins %[temp0], %[temp5], 16, 4 \n\t" + "addiu %[src], %[src], 4 \n\t" + "precr.qb.ph %[temp0], %[temp0], %[temp0] \n\t" +#if (WEBP_SWAP_16BIT_CSP == 1) + "ush %[temp0], 0(%[dst]) \n\t" +#else + "wsbh %[temp0], %[temp0] \n\t" + "ush %[temp0], 0(%[dst]) \n\t" +#endif + "bne %[src], %[p_loop2_end], 1b \n\t" + " addiu %[dst], %[dst], 2 \n\t" + "2: \n\t" + ".set pop \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [dst]"+&r"(dst), [src]"+&r"(src) + : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end) + : "memory" + ); +} + +static void ConvertBGRAToRGB565_MIPSdspR2(const uint32_t* src, + int num_pixels, uint8_t* dst) { + int temp0, temp1, temp2, temp3, temp4, temp5; + const uint32_t* const p_loop1_end = src + (num_pixels & ~3); + const uint32_t* const p_loop2_end = src + num_pixels; + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "beq %[src], %[p_loop1_end], 3f \n\t" + " nop \n\t" + "0: \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "lw %[temp1], 4(%[src]) \n\t" + "lw %[temp2], 8(%[src]) \n\t" + "lw %[temp3], 12(%[src]) \n\t" + "ext %[temp4], %[temp0], 8, 16 \n\t" + "ext %[temp5], %[temp0], 5, 11 \n\t" + "ext %[temp0], %[temp0], 3, 5 \n\t" + "ins %[temp4], %[temp5], 0, 11 \n\t" + "ext %[temp5], %[temp1], 5, 11 \n\t" + "ins %[temp4], %[temp0], 0, 5 \n\t" + "ext %[temp0], %[temp1], 8, 16 \n\t" + "ext %[temp1], %[temp1], 3, 5 \n\t" + "ins %[temp0], %[temp5], 0, 11 \n\t" + "ext %[temp5], %[temp2], 5, 11 \n\t" + "ins %[temp0], %[temp1], 0, 5 \n\t" + "ext %[temp1], %[temp2], 8, 16 \n\t" + "ext %[temp2], %[temp2], 3, 5 \n\t" + "ins %[temp1], %[temp5], 0, 11 \n\t" + "ext %[temp5], %[temp3], 5, 11 \n\t" + "ins %[temp1], %[temp2], 0, 5 \n\t" + "ext %[temp2], %[temp3], 8, 16 \n\t" + "ext %[temp3], %[temp3], 3, 5 \n\t" + "ins %[temp2], %[temp5], 0, 11 \n\t" + "append %[temp0], %[temp4], 16 \n\t" + "ins %[temp2], %[temp3], 0, 5 \n\t" + "addiu %[src], %[src], 16 \n\t" + "append %[temp2], %[temp1], 16 \n\t" +#if (WEBP_SWAP_16BIT_CSP == 1) + "usw %[temp0], 0(%[dst]) \n\t" + "usw %[temp2], 4(%[dst]) \n\t" +#else + "wsbh %[temp0], %[temp0] \n\t" + "wsbh %[temp2], %[temp2] \n\t" + "usw %[temp0], 0(%[dst]) \n\t" + "usw %[temp2], 4(%[dst]) \n\t" +#endif + "bne %[src], %[p_loop1_end], 0b \n\t" + " addiu %[dst], %[dst], 8 \n\t" + "3: \n\t" + "beq %[src], %[p_loop2_end], 2f \n\t" + " nop \n\t" + "1: \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "ext %[temp4], %[temp0], 8, 16 \n\t" + "ext %[temp5], %[temp0], 5, 11 \n\t" + "ext %[temp0], %[temp0], 3, 5 \n\t" + "ins %[temp4], %[temp5], 0, 11 \n\t" + "addiu %[src], %[src], 4 \n\t" + "ins %[temp4], %[temp0], 0, 5 \n\t" +#if (WEBP_SWAP_16BIT_CSP == 1) + "ush %[temp4], 0(%[dst]) \n\t" +#else + "wsbh %[temp4], %[temp4] \n\t" + "ush %[temp4], 0(%[dst]) \n\t" +#endif + "bne %[src], %[p_loop2_end], 1b \n\t" + " addiu %[dst], %[dst], 2 \n\t" + "2: \n\t" + ".set pop \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [dst]"+&r"(dst), [src]"+&r"(src) + : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end) + : "memory" + ); +} + +static void ConvertBGRAToBGR_MIPSdspR2(const uint32_t* src, + int num_pixels, uint8_t* dst) { + int temp0, temp1, temp2, temp3; + const uint32_t* const p_loop1_end = src + (num_pixels & ~3); + const uint32_t* const p_loop2_end = src + num_pixels; + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "beq %[src], %[p_loop1_end], 3f \n\t" + " nop \n\t" + "0: \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "lw %[temp1], 4(%[src]) \n\t" + "lw %[temp2], 8(%[src]) \n\t" + "lw %[temp3], 12(%[src]) \n\t" + "ins %[temp0], %[temp1], 24, 8 \n\t" + "sra %[temp1], %[temp1], 8 \n\t" + "ins %[temp1], %[temp2], 16, 16 \n\t" + "sll %[temp2], %[temp2], 8 \n\t" + "balign %[temp3], %[temp2], 1 \n\t" + "addiu %[src], %[src], 16 \n\t" + "usw %[temp0], 0(%[dst]) \n\t" + "usw %[temp1], 4(%[dst]) \n\t" + "usw %[temp3], 8(%[dst]) \n\t" + "bne %[src], %[p_loop1_end], 0b \n\t" + " addiu %[dst], %[dst], 12 \n\t" + "3: \n\t" + "beq %[src], %[p_loop2_end], 2f \n\t" + " nop \n\t" + "1: \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "addiu %[src], %[src], 4 \n\t" + "addiu %[dst], %[dst], 3 \n\t" + "ush %[temp0], -3(%[dst]) \n\t" + "sra %[temp0], %[temp0], 16 \n\t" + "bne %[src], %[p_loop2_end], 1b \n\t" + " sb %[temp0], -1(%[dst]) \n\t" + "2: \n\t" + ".set pop \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [dst]"+&r"(dst), [src]"+&r"(src) + : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end) + : "memory" + ); +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8LDspInitMIPSdspR2(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInitMIPSdspR2(void) { + VP8LMapColor32b = MapARGB_MIPSdspR2; + VP8LMapColor8b = MapAlpha_MIPSdspR2; + + VP8LPredictors[5] = Predictor5_MIPSdspR2; + VP8LPredictors[6] = Predictor6_MIPSdspR2; + VP8LPredictors[7] = Predictor7_MIPSdspR2; + VP8LPredictors[8] = Predictor8_MIPSdspR2; + VP8LPredictors[9] = Predictor9_MIPSdspR2; + VP8LPredictors[10] = Predictor10_MIPSdspR2; + VP8LPredictors[11] = Predictor11_MIPSdspR2; + VP8LPredictors[12] = Predictor12_MIPSdspR2; + VP8LPredictors[13] = Predictor13_MIPSdspR2; + + VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed_MIPSdspR2; + VP8LTransformColorInverse = TransformColorInverse_MIPSdspR2; + + VP8LConvertBGRAToRGB = ConvertBGRAToRGB_MIPSdspR2; + VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA_MIPSdspR2; + VP8LConvertBGRAToRGBA4444 = ConvertBGRAToRGBA4444_MIPSdspR2; + VP8LConvertBGRAToRGB565 = ConvertBGRAToRGB565_MIPSdspR2; + VP8LConvertBGRAToBGR = ConvertBGRAToBGR_MIPSdspR2; +} + +#else // !WEBP_USE_MIPS_DSP_R2 + +WEBP_DSP_INIT_STUB(VP8LDspInitMIPSdspR2) + +#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/third-party/webp/libwebp/src/dsp/lossless_msa.c b/third-party/webp/libwebp/src/dsp/lossless_msa.c new file mode 100644 index 0000000000..9f5472078d --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/lossless_msa.c @@ -0,0 +1,356 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MSA variant of methods for lossless decoder +// +// Author: Prashant Patil (prashant.patil@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MSA) + +#include "src/dsp/lossless.h" +#include "src/dsp/msa_macro.h" + +//------------------------------------------------------------------------------ +// Colorspace conversion functions + +#define CONVERT16_BGRA_XXX(psrc, pdst, m0, m1, m2) do { \ + v16u8 src0, src1, src2, src3, dst0, dst1, dst2; \ + LD_UB4(psrc, 16, src0, src1, src2, src3); \ + VSHF_B2_UB(src0, src1, src1, src2, m0, m1, dst0, dst1); \ + dst2 = VSHF_UB(src2, src3, m2); \ + ST_UB2(dst0, dst1, pdst, 16); \ + ST_UB(dst2, pdst + 32); \ +} while (0) + +#define CONVERT12_BGRA_XXX(psrc, pdst, m0, m1, m2) do { \ + uint32_t pix_w; \ + v16u8 src0, src1, src2, dst0, dst1, dst2; \ + LD_UB3(psrc, 16, src0, src1, src2); \ + VSHF_B2_UB(src0, src1, src1, src2, m0, m1, dst0, dst1); \ + dst2 = VSHF_UB(src2, src2, m2); \ + ST_UB2(dst0, dst1, pdst, 16); \ + pix_w = __msa_copy_s_w((v4i32)dst2, 0); \ + SW(pix_w, pdst + 32); \ +} while (0) + +#define CONVERT8_BGRA_XXX(psrc, pdst, m0, m1) do { \ + uint64_t pix_d; \ + v16u8 src0, src1, src2 = { 0 }, dst0, dst1; \ + LD_UB2(psrc, 16, src0, src1); \ + VSHF_B2_UB(src0, src1, src1, src2, m0, m1, dst0, dst1); \ + ST_UB(dst0, pdst); \ + pix_d = __msa_copy_s_d((v2i64)dst1, 0); \ + SD(pix_d, pdst + 16); \ +} while (0) + +#define CONVERT4_BGRA_XXX(psrc, pdst, m) do { \ + const v16u8 src0 = LD_UB(psrc); \ + const v16u8 dst0 = VSHF_UB(src0, src0, m); \ + uint64_t pix_d = __msa_copy_s_d((v2i64)dst0, 0); \ + uint32_t pix_w = __msa_copy_s_w((v4i32)dst0, 2); \ + SD(pix_d, pdst + 0); \ + SW(pix_w, pdst + 8); \ +} while (0) + +#define CONVERT1_BGRA_BGR(psrc, pdst) do { \ + const int32_t b = (psrc)[0]; \ + const int32_t g = (psrc)[1]; \ + const int32_t r = (psrc)[2]; \ + (pdst)[0] = b; \ + (pdst)[1] = g; \ + (pdst)[2] = r; \ +} while (0) + +#define CONVERT1_BGRA_RGB(psrc, pdst) do { \ + const int32_t b = (psrc)[0]; \ + const int32_t g = (psrc)[1]; \ + const int32_t r = (psrc)[2]; \ + (pdst)[0] = r; \ + (pdst)[1] = g; \ + (pdst)[2] = b; \ +} while (0) + +#define TRANSFORM_COLOR_INVERSE_8(src0, src1, dst0, dst1, \ + c0, c1, mask0, mask1) do { \ + v8i16 g0, g1, t0, t1, t2, t3; \ + v4i32 t4, t5; \ + VSHF_B2_SH(src0, src0, src1, src1, mask0, mask0, g0, g1); \ + DOTP_SB2_SH(g0, g1, c0, c0, t0, t1); \ + SRAI_H2_SH(t0, t1, 5); \ + t0 = __msa_addv_h(t0, (v8i16)src0); \ + t1 = __msa_addv_h(t1, (v8i16)src1); \ + t4 = __msa_srli_w((v4i32)t0, 16); \ + t5 = __msa_srli_w((v4i32)t1, 16); \ + DOTP_SB2_SH(t4, t5, c1, c1, t2, t3); \ + SRAI_H2_SH(t2, t3, 5); \ + ADD2(t0, t2, t1, t3, t0, t1); \ + VSHF_B2_UB(src0, t0, src1, t1, mask1, mask1, dst0, dst1); \ +} while (0) + +#define TRANSFORM_COLOR_INVERSE_4(src, dst, c0, c1, mask0, mask1) do { \ + const v16i8 g0 = VSHF_SB(src, src, mask0); \ + v8i16 t0 = __msa_dotp_s_h(c0, g0); \ + v8i16 t1; \ + v4i32 t2; \ + t0 = SRAI_H(t0, 5); \ + t0 = __msa_addv_h(t0, (v8i16)src); \ + t2 = __msa_srli_w((v4i32)t0, 16); \ + t1 = __msa_dotp_s_h(c1, (v16i8)t2); \ + t1 = SRAI_H(t1, 5); \ + t0 = t0 + t1; \ + dst = VSHF_UB(src, t0, mask1); \ +} while (0) + +static void ConvertBGRAToRGBA_MSA(const uint32_t* src, + int num_pixels, uint8_t* dst) { + int i; + const uint8_t* ptemp_src = (const uint8_t*)src; + uint8_t* ptemp_dst = (uint8_t*)dst; + v16u8 src0, dst0; + const v16u8 mask = { 2, 1, 0, 3, 6, 5, 4, 7, 10, 9, 8, 11, 14, 13, 12, 15 }; + + while (num_pixels >= 8) { + v16u8 src1, dst1; + LD_UB2(ptemp_src, 16, src0, src1); + VSHF_B2_UB(src0, src0, src1, src1, mask, mask, dst0, dst1); + ST_UB2(dst0, dst1, ptemp_dst, 16); + ptemp_src += 32; + ptemp_dst += 32; + num_pixels -= 8; + } + if (num_pixels > 0) { + if (num_pixels >= 4) { + src0 = LD_UB(ptemp_src); + dst0 = VSHF_UB(src0, src0, mask); + ST_UB(dst0, ptemp_dst); + ptemp_src += 16; + ptemp_dst += 16; + num_pixels -= 4; + } + for (i = 0; i < num_pixels; i++) { + const uint8_t b = ptemp_src[2]; + const uint8_t g = ptemp_src[1]; + const uint8_t r = ptemp_src[0]; + const uint8_t a = ptemp_src[3]; + ptemp_dst[0] = b; + ptemp_dst[1] = g; + ptemp_dst[2] = r; + ptemp_dst[3] = a; + ptemp_src += 4; + ptemp_dst += 4; + } + } +} + +static void ConvertBGRAToBGR_MSA(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const uint8_t* ptemp_src = (const uint8_t*)src; + uint8_t* ptemp_dst = (uint8_t*)dst; + const v16u8 mask0 = { 0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, + 16, 17, 18, 20 }; + const v16u8 mask1 = { 5, 6, 8, 9, 10, 12, 13, 14, 16, 17, 18, 20, + 21, 22, 24, 25 }; + const v16u8 mask2 = { 10, 12, 13, 14, 16, 17, 18, 20, 21, 22, 24, 25, + 26, 28, 29, 30 }; + + while (num_pixels >= 16) { + CONVERT16_BGRA_XXX(ptemp_src, ptemp_dst, mask0, mask1, mask2); + ptemp_src += 64; + ptemp_dst += 48; + num_pixels -= 16; + } + if (num_pixels > 0) { + if (num_pixels >= 12) { + CONVERT12_BGRA_XXX(ptemp_src, ptemp_dst, mask0, mask1, mask2); + ptemp_src += 48; + ptemp_dst += 36; + num_pixels -= 12; + } else if (num_pixels >= 8) { + CONVERT8_BGRA_XXX(ptemp_src, ptemp_dst, mask0, mask1); + ptemp_src += 32; + ptemp_dst += 24; + num_pixels -= 8; + } else if (num_pixels >= 4) { + CONVERT4_BGRA_XXX(ptemp_src, ptemp_dst, mask0); + ptemp_src += 16; + ptemp_dst += 12; + num_pixels -= 4; + } + if (num_pixels == 3) { + CONVERT1_BGRA_BGR(ptemp_src + 0, ptemp_dst + 0); + CONVERT1_BGRA_BGR(ptemp_src + 4, ptemp_dst + 3); + CONVERT1_BGRA_BGR(ptemp_src + 8, ptemp_dst + 6); + } else if (num_pixels == 2) { + CONVERT1_BGRA_BGR(ptemp_src + 0, ptemp_dst + 0); + CONVERT1_BGRA_BGR(ptemp_src + 4, ptemp_dst + 3); + } else if (num_pixels == 1) { + CONVERT1_BGRA_BGR(ptemp_src, ptemp_dst); + } + } +} + +static void ConvertBGRAToRGB_MSA(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const uint8_t* ptemp_src = (const uint8_t*)src; + uint8_t* ptemp_dst = (uint8_t*)dst; + const v16u8 mask0 = { 2, 1, 0, 6, 5, 4, 10, 9, 8, 14, 13, 12, + 18, 17, 16, 22 }; + const v16u8 mask1 = { 5, 4, 10, 9, 8, 14, 13, 12, 18, 17, 16, 22, + 21, 20, 26, 25 }; + const v16u8 mask2 = { 8, 14, 13, 12, 18, 17, 16, 22, 21, 20, 26, 25, + 24, 30, 29, 28 }; + + while (num_pixels >= 16) { + CONVERT16_BGRA_XXX(ptemp_src, ptemp_dst, mask0, mask1, mask2); + ptemp_src += 64; + ptemp_dst += 48; + num_pixels -= 16; + } + if (num_pixels) { + if (num_pixels >= 12) { + CONVERT12_BGRA_XXX(ptemp_src, ptemp_dst, mask0, mask1, mask2); + ptemp_src += 48; + ptemp_dst += 36; + num_pixels -= 12; + } else if (num_pixels >= 8) { + CONVERT8_BGRA_XXX(ptemp_src, ptemp_dst, mask0, mask1); + ptemp_src += 32; + ptemp_dst += 24; + num_pixels -= 8; + } else if (num_pixels >= 4) { + CONVERT4_BGRA_XXX(ptemp_src, ptemp_dst, mask0); + ptemp_src += 16; + ptemp_dst += 12; + num_pixels -= 4; + } + if (num_pixels == 3) { + CONVERT1_BGRA_RGB(ptemp_src + 0, ptemp_dst + 0); + CONVERT1_BGRA_RGB(ptemp_src + 4, ptemp_dst + 3); + CONVERT1_BGRA_RGB(ptemp_src + 8, ptemp_dst + 6); + } else if (num_pixels == 2) { + CONVERT1_BGRA_RGB(ptemp_src + 0, ptemp_dst + 0); + CONVERT1_BGRA_RGB(ptemp_src + 4, ptemp_dst + 3); + } else if (num_pixels == 1) { + CONVERT1_BGRA_RGB(ptemp_src, ptemp_dst); + } + } +} + +static void AddGreenToBlueAndRed_MSA(const uint32_t* const src, int num_pixels, + uint32_t* dst) { + int i; + const uint8_t* in = (const uint8_t*)src; + uint8_t* out = (uint8_t*)dst; + v16u8 src0, dst0, tmp0; + const v16u8 mask = { 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, + 13, 255, 13, 255 }; + + while (num_pixels >= 8) { + v16u8 src1, dst1, tmp1; + LD_UB2(in, 16, src0, src1); + VSHF_B2_UB(src0, src1, src1, src0, mask, mask, tmp0, tmp1); + ADD2(src0, tmp0, src1, tmp1, dst0, dst1); + ST_UB2(dst0, dst1, out, 16); + in += 32; + out += 32; + num_pixels -= 8; + } + if (num_pixels > 0) { + if (num_pixels >= 4) { + src0 = LD_UB(in); + tmp0 = VSHF_UB(src0, src0, mask); + dst0 = src0 + tmp0; + ST_UB(dst0, out); + in += 16; + out += 16; + num_pixels -= 4; + } + for (i = 0; i < num_pixels; i++) { + const uint8_t b = in[0]; + const uint8_t g = in[1]; + const uint8_t r = in[2]; + out[0] = (b + g) & 0xff; + out[1] = g; + out[2] = (r + g) & 0xff; + out[4] = in[4]; + out += 4; + } + } +} + +static void TransformColorInverse_MSA(const VP8LMultipliers* const m, + const uint32_t* src, int num_pixels, + uint32_t* dst) { + v16u8 src0, dst0; + const v16i8 g2br = (v16i8)__msa_fill_w(m->green_to_blue_ | + (m->green_to_red_ << 16)); + const v16i8 r2b = (v16i8)__msa_fill_w(m->red_to_blue_); + const v16u8 mask0 = { 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, + 13, 255, 13, 255 }; + const v16u8 mask1 = { 16, 1, 18, 3, 20, 5, 22, 7, 24, 9, 26, 11, + 28, 13, 30, 15 }; + + while (num_pixels >= 8) { + v16u8 src1, dst1; + LD_UB2(src, 4, src0, src1); + TRANSFORM_COLOR_INVERSE_8(src0, src1, dst0, dst1, g2br, r2b, mask0, mask1); + ST_UB2(dst0, dst1, dst, 4); + src += 8; + dst += 8; + num_pixels -= 8; + } + if (num_pixels > 0) { + if (num_pixels >= 4) { + src0 = LD_UB(src); + TRANSFORM_COLOR_INVERSE_4(src0, dst0, g2br, r2b, mask0, mask1); + ST_UB(dst0, dst); + src += 4; + dst += 4; + num_pixels -= 4; + } + if (num_pixels > 0) { + src0 = LD_UB(src); + TRANSFORM_COLOR_INVERSE_4(src0, dst0, g2br, r2b, mask0, mask1); + if (num_pixels == 3) { + const uint64_t pix_d = __msa_copy_s_d((v2i64)dst0, 0); + const uint32_t pix_w = __msa_copy_s_w((v4i32)dst0, 2); + SD(pix_d, dst + 0); + SW(pix_w, dst + 2); + } else if (num_pixels == 2) { + const uint64_t pix_d = __msa_copy_s_d((v2i64)dst0, 0); + SD(pix_d, dst); + } else { + const uint32_t pix_w = __msa_copy_s_w((v4i32)dst0, 0); + SW(pix_w, dst); + } + } + } +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8LDspInitMSA(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInitMSA(void) { + VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA_MSA; + VP8LConvertBGRAToBGR = ConvertBGRAToBGR_MSA; + VP8LConvertBGRAToRGB = ConvertBGRAToRGB_MSA; + + VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed_MSA; + VP8LTransformColorInverse = TransformColorInverse_MSA; +} + +#else // !WEBP_USE_MSA + +WEBP_DSP_INIT_STUB(VP8LDspInitMSA) + +#endif // WEBP_USE_MSA diff --git a/third-party/webp/libwebp/src/dsp/lossless_neon.c b/third-party/webp/libwebp/src/dsp/lossless_neon.c new file mode 100644 index 0000000000..ddc9b61711 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/lossless_neon.c @@ -0,0 +1,645 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// NEON variant of methods for lossless decoder +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_NEON) + +#include + +#include "src/dsp/lossless.h" +#include "src/dsp/neon.h" + +//------------------------------------------------------------------------------ +// Colorspace conversion functions + +#if !defined(WORK_AROUND_GCC) +// gcc 4.6.0 had some trouble (NDK-r9) with this code. We only use it for +// gcc-4.8.x at least. +static void ConvertBGRAToRGBA_NEON(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const uint32_t* const end = src + (num_pixels & ~15); + for (; src < end; src += 16) { + uint8x16x4_t pixel = vld4q_u8((uint8_t*)src); + // swap B and R. (VSWP d0,d2 has no intrinsics equivalent!) + const uint8x16_t tmp = pixel.val[0]; + pixel.val[0] = pixel.val[2]; + pixel.val[2] = tmp; + vst4q_u8(dst, pixel); + dst += 64; + } + VP8LConvertBGRAToRGBA_C(src, num_pixels & 15, dst); // left-overs +} + +static void ConvertBGRAToBGR_NEON(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const uint32_t* const end = src + (num_pixels & ~15); + for (; src < end; src += 16) { + const uint8x16x4_t pixel = vld4q_u8((uint8_t*)src); + const uint8x16x3_t tmp = { { pixel.val[0], pixel.val[1], pixel.val[2] } }; + vst3q_u8(dst, tmp); + dst += 48; + } + VP8LConvertBGRAToBGR_C(src, num_pixels & 15, dst); // left-overs +} + +static void ConvertBGRAToRGB_NEON(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const uint32_t* const end = src + (num_pixels & ~15); + for (; src < end; src += 16) { + const uint8x16x4_t pixel = vld4q_u8((uint8_t*)src); + const uint8x16x3_t tmp = { { pixel.val[2], pixel.val[1], pixel.val[0] } }; + vst3q_u8(dst, tmp); + dst += 48; + } + VP8LConvertBGRAToRGB_C(src, num_pixels & 15, dst); // left-overs +} + +#else // WORK_AROUND_GCC + +// gcc-4.6.0 fallback + +static const uint8_t kRGBAShuffle[8] = { 2, 1, 0, 3, 6, 5, 4, 7 }; + +static void ConvertBGRAToRGBA_NEON(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const uint32_t* const end = src + (num_pixels & ~1); + const uint8x8_t shuffle = vld1_u8(kRGBAShuffle); + for (; src < end; src += 2) { + const uint8x8_t pixels = vld1_u8((uint8_t*)src); + vst1_u8(dst, vtbl1_u8(pixels, shuffle)); + dst += 8; + } + VP8LConvertBGRAToRGBA_C(src, num_pixels & 1, dst); // left-overs +} + +static const uint8_t kBGRShuffle[3][8] = { + { 0, 1, 2, 4, 5, 6, 8, 9 }, + { 10, 12, 13, 14, 16, 17, 18, 20 }, + { 21, 22, 24, 25, 26, 28, 29, 30 } +}; + +static void ConvertBGRAToBGR_NEON(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const uint32_t* const end = src + (num_pixels & ~7); + const uint8x8_t shuffle0 = vld1_u8(kBGRShuffle[0]); + const uint8x8_t shuffle1 = vld1_u8(kBGRShuffle[1]); + const uint8x8_t shuffle2 = vld1_u8(kBGRShuffle[2]); + for (; src < end; src += 8) { + uint8x8x4_t pixels; + INIT_VECTOR4(pixels, + vld1_u8((const uint8_t*)(src + 0)), + vld1_u8((const uint8_t*)(src + 2)), + vld1_u8((const uint8_t*)(src + 4)), + vld1_u8((const uint8_t*)(src + 6))); + vst1_u8(dst + 0, vtbl4_u8(pixels, shuffle0)); + vst1_u8(dst + 8, vtbl4_u8(pixels, shuffle1)); + vst1_u8(dst + 16, vtbl4_u8(pixels, shuffle2)); + dst += 8 * 3; + } + VP8LConvertBGRAToBGR_C(src, num_pixels & 7, dst); // left-overs +} + +static const uint8_t kRGBShuffle[3][8] = { + { 2, 1, 0, 6, 5, 4, 10, 9 }, + { 8, 14, 13, 12, 18, 17, 16, 22 }, + { 21, 20, 26, 25, 24, 30, 29, 28 } +}; + +static void ConvertBGRAToRGB_NEON(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const uint32_t* const end = src + (num_pixels & ~7); + const uint8x8_t shuffle0 = vld1_u8(kRGBShuffle[0]); + const uint8x8_t shuffle1 = vld1_u8(kRGBShuffle[1]); + const uint8x8_t shuffle2 = vld1_u8(kRGBShuffle[2]); + for (; src < end; src += 8) { + uint8x8x4_t pixels; + INIT_VECTOR4(pixels, + vld1_u8((const uint8_t*)(src + 0)), + vld1_u8((const uint8_t*)(src + 2)), + vld1_u8((const uint8_t*)(src + 4)), + vld1_u8((const uint8_t*)(src + 6))); + vst1_u8(dst + 0, vtbl4_u8(pixels, shuffle0)); + vst1_u8(dst + 8, vtbl4_u8(pixels, shuffle1)); + vst1_u8(dst + 16, vtbl4_u8(pixels, shuffle2)); + dst += 8 * 3; + } + VP8LConvertBGRAToRGB_C(src, num_pixels & 7, dst); // left-overs +} + +#endif // !WORK_AROUND_GCC + +//------------------------------------------------------------------------------ +// Predictor Transform + +#define LOAD_U32_AS_U8(IN) vreinterpret_u8_u32(vdup_n_u32((IN))) +#define LOAD_U32P_AS_U8(IN) vreinterpret_u8_u32(vld1_u32((IN))) +#define LOADQ_U32_AS_U8(IN) vreinterpretq_u8_u32(vdupq_n_u32((IN))) +#define LOADQ_U32P_AS_U8(IN) vreinterpretq_u8_u32(vld1q_u32((IN))) +#define GET_U8_AS_U32(IN) vget_lane_u32(vreinterpret_u32_u8((IN)), 0); +#define GETQ_U8_AS_U32(IN) vgetq_lane_u32(vreinterpretq_u32_u8((IN)), 0); +#define STOREQ_U8_AS_U32P(OUT, IN) vst1q_u32((OUT), vreinterpretq_u32_u8((IN))); +#define ROTATE32_LEFT(L) vextq_u8((L), (L), 12) // D|C|B|A -> C|B|A|D + +static WEBP_INLINE uint8x8_t Average2_u8_NEON(uint32_t a0, uint32_t a1) { + const uint8x8_t A0 = LOAD_U32_AS_U8(a0); + const uint8x8_t A1 = LOAD_U32_AS_U8(a1); + return vhadd_u8(A0, A1); +} + +static WEBP_INLINE uint32_t ClampedAddSubtractHalf_NEON(uint32_t c0, + uint32_t c1, + uint32_t c2) { + const uint8x8_t avg = Average2_u8_NEON(c0, c1); + // Remove one to c2 when bigger than avg. + const uint8x8_t C2 = LOAD_U32_AS_U8(c2); + const uint8x8_t cmp = vcgt_u8(C2, avg); + const uint8x8_t C2_1 = vadd_u8(C2, cmp); + // Compute half of the difference between avg and c2. + const int8x8_t diff_avg = vreinterpret_s8_u8(vhsub_u8(avg, C2_1)); + // Compute the sum with avg and saturate. + const int16x8_t avg_16 = vreinterpretq_s16_u16(vmovl_u8(avg)); + const uint8x8_t res = vqmovun_s16(vaddw_s8(avg_16, diff_avg)); + const uint32_t output = GET_U8_AS_U32(res); + return output; +} + +static WEBP_INLINE uint32_t Average2_NEON(uint32_t a0, uint32_t a1) { + const uint8x8_t avg_u8x8 = Average2_u8_NEON(a0, a1); + const uint32_t avg = GET_U8_AS_U32(avg_u8x8); + return avg; +} + +static WEBP_INLINE uint32_t Average3_NEON(uint32_t a0, uint32_t a1, + uint32_t a2) { + const uint8x8_t avg0 = Average2_u8_NEON(a0, a2); + const uint8x8_t A1 = LOAD_U32_AS_U8(a1); + const uint32_t avg = GET_U8_AS_U32(vhadd_u8(avg0, A1)); + return avg; +} + +static uint32_t Predictor5_NEON(const uint32_t* const left, + const uint32_t* const top) { + return Average3_NEON(*left, top[0], top[1]); +} +static uint32_t Predictor6_NEON(const uint32_t* const left, + const uint32_t* const top) { + return Average2_NEON(*left, top[-1]); +} +static uint32_t Predictor7_NEON(const uint32_t* const left, + const uint32_t* const top) { + return Average2_NEON(*left, top[0]); +} +static uint32_t Predictor13_NEON(const uint32_t* const left, + const uint32_t* const top) { + return ClampedAddSubtractHalf_NEON(*left, top[0], top[-1]); +} + +// Batch versions of those functions. + +// Predictor0: ARGB_BLACK. +static void PredictorAdd0_NEON(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + const uint8x16_t black = vreinterpretq_u8_u32(vdupq_n_u32(ARGB_BLACK)); + for (i = 0; i + 4 <= num_pixels; i += 4) { + const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]); + const uint8x16_t res = vaddq_u8(src, black); + STOREQ_U8_AS_U32P(&out[i], res); + } + VP8LPredictorsAdd_C[0](in + i, upper + i, num_pixels - i, out + i); +} + +// Predictor1: left. +static void PredictorAdd1_NEON(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + const uint8x16_t zero = LOADQ_U32_AS_U8(0); + for (i = 0; i + 4 <= num_pixels; i += 4) { + // a | b | c | d + const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]); + // 0 | a | b | c + const uint8x16_t shift0 = vextq_u8(zero, src, 12); + // a | a + b | b + c | c + d + const uint8x16_t sum0 = vaddq_u8(src, shift0); + // 0 | 0 | a | a + b + const uint8x16_t shift1 = vextq_u8(zero, sum0, 8); + // a | a + b | a + b + c | a + b + c + d + const uint8x16_t sum1 = vaddq_u8(sum0, shift1); + const uint8x16_t prev = LOADQ_U32_AS_U8(out[i - 1]); + const uint8x16_t res = vaddq_u8(sum1, prev); + STOREQ_U8_AS_U32P(&out[i], res); + } + VP8LPredictorsAdd_C[1](in + i, upper + i, num_pixels - i, out + i); +} + +// Macro that adds 32-bit integers from IN using mod 256 arithmetic +// per 8 bit channel. +#define GENERATE_PREDICTOR_1(X, IN) \ +static void PredictorAdd##X##_NEON(const uint32_t* in, \ + const uint32_t* upper, int num_pixels, \ + uint32_t* out) { \ + int i; \ + for (i = 0; i + 4 <= num_pixels; i += 4) { \ + const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]); \ + const uint8x16_t other = LOADQ_U32P_AS_U8(&(IN)); \ + const uint8x16_t res = vaddq_u8(src, other); \ + STOREQ_U8_AS_U32P(&out[i], res); \ + } \ + VP8LPredictorsAdd_C[(X)](in + i, upper + i, num_pixels - i, out + i); \ +} +// Predictor2: Top. +GENERATE_PREDICTOR_1(2, upper[i]) +// Predictor3: Top-right. +GENERATE_PREDICTOR_1(3, upper[i + 1]) +// Predictor4: Top-left. +GENERATE_PREDICTOR_1(4, upper[i - 1]) +#undef GENERATE_PREDICTOR_1 + +// Predictor5: average(average(left, TR), T) +#define DO_PRED5(LANE) do { \ + const uint8x16_t avgLTR = vhaddq_u8(L, TR); \ + const uint8x16_t avg = vhaddq_u8(avgLTR, T); \ + const uint8x16_t res = vaddq_u8(avg, src); \ + vst1q_lane_u32(&out[i + (LANE)], vreinterpretq_u32_u8(res), (LANE)); \ + L = ROTATE32_LEFT(res); \ +} while (0) + +static void PredictorAdd5_NEON(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + uint8x16_t L = LOADQ_U32_AS_U8(out[-1]); + for (i = 0; i + 4 <= num_pixels; i += 4) { + const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]); + const uint8x16_t T = LOADQ_U32P_AS_U8(&upper[i + 0]); + const uint8x16_t TR = LOADQ_U32P_AS_U8(&upper[i + 1]); + DO_PRED5(0); + DO_PRED5(1); + DO_PRED5(2); + DO_PRED5(3); + } + VP8LPredictorsAdd_C[5](in + i, upper + i, num_pixels - i, out + i); +} +#undef DO_PRED5 + +#define DO_PRED67(LANE) do { \ + const uint8x16_t avg = vhaddq_u8(L, top); \ + const uint8x16_t res = vaddq_u8(avg, src); \ + vst1q_lane_u32(&out[i + (LANE)], vreinterpretq_u32_u8(res), (LANE)); \ + L = ROTATE32_LEFT(res); \ +} while (0) + +// Predictor6: average(left, TL) +static void PredictorAdd6_NEON(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + uint8x16_t L = LOADQ_U32_AS_U8(out[-1]); + for (i = 0; i + 4 <= num_pixels; i += 4) { + const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]); + const uint8x16_t top = LOADQ_U32P_AS_U8(&upper[i - 1]); + DO_PRED67(0); + DO_PRED67(1); + DO_PRED67(2); + DO_PRED67(3); + } + VP8LPredictorsAdd_C[6](in + i, upper + i, num_pixels - i, out + i); +} + +// Predictor7: average(left, T) +static void PredictorAdd7_NEON(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + uint8x16_t L = LOADQ_U32_AS_U8(out[-1]); + for (i = 0; i + 4 <= num_pixels; i += 4) { + const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]); + const uint8x16_t top = LOADQ_U32P_AS_U8(&upper[i]); + DO_PRED67(0); + DO_PRED67(1); + DO_PRED67(2); + DO_PRED67(3); + } + VP8LPredictorsAdd_C[7](in + i, upper + i, num_pixels - i, out + i); +} +#undef DO_PRED67 + +#define GENERATE_PREDICTOR_2(X, IN) \ +static void PredictorAdd##X##_NEON(const uint32_t* in, \ + const uint32_t* upper, int num_pixels, \ + uint32_t* out) { \ + int i; \ + for (i = 0; i + 4 <= num_pixels; i += 4) { \ + const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]); \ + const uint8x16_t Tother = LOADQ_U32P_AS_U8(&(IN)); \ + const uint8x16_t T = LOADQ_U32P_AS_U8(&upper[i]); \ + const uint8x16_t avg = vhaddq_u8(T, Tother); \ + const uint8x16_t res = vaddq_u8(avg, src); \ + STOREQ_U8_AS_U32P(&out[i], res); \ + } \ + VP8LPredictorsAdd_C[(X)](in + i, upper + i, num_pixels - i, out + i); \ +} +// Predictor8: average TL T. +GENERATE_PREDICTOR_2(8, upper[i - 1]) +// Predictor9: average T TR. +GENERATE_PREDICTOR_2(9, upper[i + 1]) +#undef GENERATE_PREDICTOR_2 + +// Predictor10: average of (average of (L,TL), average of (T, TR)). +#define DO_PRED10(LANE) do { \ + const uint8x16_t avgLTL = vhaddq_u8(L, TL); \ + const uint8x16_t avg = vhaddq_u8(avgTTR, avgLTL); \ + const uint8x16_t res = vaddq_u8(avg, src); \ + vst1q_lane_u32(&out[i + (LANE)], vreinterpretq_u32_u8(res), (LANE)); \ + L = ROTATE32_LEFT(res); \ +} while (0) + +static void PredictorAdd10_NEON(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + uint8x16_t L = LOADQ_U32_AS_U8(out[-1]); + for (i = 0; i + 4 <= num_pixels; i += 4) { + const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]); + const uint8x16_t TL = LOADQ_U32P_AS_U8(&upper[i - 1]); + const uint8x16_t T = LOADQ_U32P_AS_U8(&upper[i]); + const uint8x16_t TR = LOADQ_U32P_AS_U8(&upper[i + 1]); + const uint8x16_t avgTTR = vhaddq_u8(T, TR); + DO_PRED10(0); + DO_PRED10(1); + DO_PRED10(2); + DO_PRED10(3); + } + VP8LPredictorsAdd_C[10](in + i, upper + i, num_pixels - i, out + i); +} +#undef DO_PRED10 + +// Predictor11: select. +#define DO_PRED11(LANE) do { \ + const uint8x16_t sumLin = vaddq_u8(L, src); /* in + L */ \ + const uint8x16_t pLTL = vabdq_u8(L, TL); /* |L - TL| */ \ + const uint16x8_t sum_LTL = vpaddlq_u8(pLTL); \ + const uint32x4_t pa = vpaddlq_u16(sum_LTL); \ + const uint32x4_t mask = vcleq_u32(pa, pb); \ + const uint8x16_t res = vbslq_u8(vreinterpretq_u8_u32(mask), sumTin, sumLin); \ + vst1q_lane_u32(&out[i + (LANE)], vreinterpretq_u32_u8(res), (LANE)); \ + L = ROTATE32_LEFT(res); \ +} while (0) + +static void PredictorAdd11_NEON(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + uint8x16_t L = LOADQ_U32_AS_U8(out[-1]); + for (i = 0; i + 4 <= num_pixels; i += 4) { + const uint8x16_t T = LOADQ_U32P_AS_U8(&upper[i]); + const uint8x16_t TL = LOADQ_U32P_AS_U8(&upper[i - 1]); + const uint8x16_t pTTL = vabdq_u8(T, TL); // |T - TL| + const uint16x8_t sum_TTL = vpaddlq_u8(pTTL); + const uint32x4_t pb = vpaddlq_u16(sum_TTL); + const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]); + const uint8x16_t sumTin = vaddq_u8(T, src); // in + T + DO_PRED11(0); + DO_PRED11(1); + DO_PRED11(2); + DO_PRED11(3); + } + VP8LPredictorsAdd_C[11](in + i, upper + i, num_pixels - i, out + i); +} +#undef DO_PRED11 + +// Predictor12: ClampedAddSubtractFull. +#define DO_PRED12(DIFF, LANE) do { \ + const uint8x8_t pred = \ + vqmovun_s16(vaddq_s16(vreinterpretq_s16_u16(L), (DIFF))); \ + const uint8x8_t res = \ + vadd_u8(pred, (LANE <= 1) ? vget_low_u8(src) : vget_high_u8(src)); \ + const uint16x8_t res16 = vmovl_u8(res); \ + vst1_lane_u32(&out[i + (LANE)], vreinterpret_u32_u8(res), (LANE) & 1); \ + /* rotate in the left predictor for next iteration */ \ + L = vextq_u16(res16, res16, 4); \ +} while (0) + +static void PredictorAdd12_NEON(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + uint16x8_t L = vmovl_u8(LOAD_U32_AS_U8(out[-1])); + for (i = 0; i + 4 <= num_pixels; i += 4) { + // load four pixels of source + const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]); + // precompute the difference T - TL once for all, stored as s16 + const uint8x16_t TL = LOADQ_U32P_AS_U8(&upper[i - 1]); + const uint8x16_t T = LOADQ_U32P_AS_U8(&upper[i]); + const int16x8_t diff_lo = + vreinterpretq_s16_u16(vsubl_u8(vget_low_u8(T), vget_low_u8(TL))); + const int16x8_t diff_hi = + vreinterpretq_s16_u16(vsubl_u8(vget_high_u8(T), vget_high_u8(TL))); + // loop over the four reconstructed pixels + DO_PRED12(diff_lo, 0); + DO_PRED12(diff_lo, 1); + DO_PRED12(diff_hi, 2); + DO_PRED12(diff_hi, 3); + } + VP8LPredictorsAdd_C[12](in + i, upper + i, num_pixels - i, out + i); +} +#undef DO_PRED12 + +// Predictor13: ClampedAddSubtractHalf +#define DO_PRED13(LANE, LOW_OR_HI) do { \ + const uint8x16_t avg = vhaddq_u8(L, T); \ + const uint8x16_t cmp = vcgtq_u8(TL, avg); \ + const uint8x16_t TL_1 = vaddq_u8(TL, cmp); \ + /* Compute half of the difference between avg and TL'. */ \ + const int8x8_t diff_avg = \ + vreinterpret_s8_u8(LOW_OR_HI(vhsubq_u8(avg, TL_1))); \ + /* Compute the sum with avg and saturate. */ \ + const int16x8_t avg_16 = vreinterpretq_s16_u16(vmovl_u8(LOW_OR_HI(avg))); \ + const uint8x8_t delta = vqmovun_s16(vaddw_s8(avg_16, diff_avg)); \ + const uint8x8_t res = vadd_u8(LOW_OR_HI(src), delta); \ + const uint8x16_t res2 = vcombine_u8(res, res); \ + vst1_lane_u32(&out[i + (LANE)], vreinterpret_u32_u8(res), (LANE) & 1); \ + L = ROTATE32_LEFT(res2); \ +} while (0) + +static void PredictorAdd13_NEON(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + uint8x16_t L = LOADQ_U32_AS_U8(out[-1]); + for (i = 0; i + 4 <= num_pixels; i += 4) { + const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]); + const uint8x16_t T = LOADQ_U32P_AS_U8(&upper[i]); + const uint8x16_t TL = LOADQ_U32P_AS_U8(&upper[i - 1]); + DO_PRED13(0, vget_low_u8); + DO_PRED13(1, vget_low_u8); + DO_PRED13(2, vget_high_u8); + DO_PRED13(3, vget_high_u8); + } + VP8LPredictorsAdd_C[13](in + i, upper + i, num_pixels - i, out + i); +} +#undef DO_PRED13 + +#undef LOAD_U32_AS_U8 +#undef LOAD_U32P_AS_U8 +#undef LOADQ_U32_AS_U8 +#undef LOADQ_U32P_AS_U8 +#undef GET_U8_AS_U32 +#undef GETQ_U8_AS_U32 +#undef STOREQ_U8_AS_U32P +#undef ROTATE32_LEFT + +//------------------------------------------------------------------------------ +// Subtract-Green Transform + +// vtbl?_u8 are marked unavailable for iOS arm64 with Xcode < 6.3, use +// non-standard versions there. +#if defined(__APPLE__) && WEBP_AARCH64 && \ + defined(__apple_build_version__) && (__apple_build_version__< 6020037) +#define USE_VTBLQ +#endif + +#ifdef USE_VTBLQ +// 255 = byte will be zeroed +static const uint8_t kGreenShuffle[16] = { + 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13, 255 +}; + +static WEBP_INLINE uint8x16_t DoGreenShuffle_NEON(const uint8x16_t argb, + const uint8x16_t shuffle) { + return vcombine_u8(vtbl1q_u8(argb, vget_low_u8(shuffle)), + vtbl1q_u8(argb, vget_high_u8(shuffle))); +} +#else // !USE_VTBLQ +// 255 = byte will be zeroed +static const uint8_t kGreenShuffle[8] = { 1, 255, 1, 255, 5, 255, 5, 255 }; + +static WEBP_INLINE uint8x16_t DoGreenShuffle_NEON(const uint8x16_t argb, + const uint8x8_t shuffle) { + return vcombine_u8(vtbl1_u8(vget_low_u8(argb), shuffle), + vtbl1_u8(vget_high_u8(argb), shuffle)); +} +#endif // USE_VTBLQ + +static void AddGreenToBlueAndRed_NEON(const uint32_t* src, int num_pixels, + uint32_t* dst) { + const uint32_t* const end = src + (num_pixels & ~3); +#ifdef USE_VTBLQ + const uint8x16_t shuffle = vld1q_u8(kGreenShuffle); +#else + const uint8x8_t shuffle = vld1_u8(kGreenShuffle); +#endif + for (; src < end; src += 4, dst += 4) { + const uint8x16_t argb = vld1q_u8((const uint8_t*)src); + const uint8x16_t greens = DoGreenShuffle_NEON(argb, shuffle); + vst1q_u8((uint8_t*)dst, vaddq_u8(argb, greens)); + } + // fallthrough and finish off with plain-C + VP8LAddGreenToBlueAndRed_C(src, num_pixels & 3, dst); +} + +//------------------------------------------------------------------------------ +// Color Transform + +static void TransformColorInverse_NEON(const VP8LMultipliers* const m, + const uint32_t* const src, + int num_pixels, uint32_t* dst) { +// sign-extended multiplying constants, pre-shifted by 6. +#define CST(X) (((int16_t)(m->X << 8)) >> 6) + const int16_t rb[8] = { + CST(green_to_blue_), CST(green_to_red_), + CST(green_to_blue_), CST(green_to_red_), + CST(green_to_blue_), CST(green_to_red_), + CST(green_to_blue_), CST(green_to_red_) + }; + const int16x8_t mults_rb = vld1q_s16(rb); + const int16_t b2[8] = { + 0, CST(red_to_blue_), 0, CST(red_to_blue_), + 0, CST(red_to_blue_), 0, CST(red_to_blue_), + }; + const int16x8_t mults_b2 = vld1q_s16(b2); +#undef CST +#ifdef USE_VTBLQ + static const uint8_t kg0g0[16] = { + 255, 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13 + }; + const uint8x16_t shuffle = vld1q_u8(kg0g0); +#else + static const uint8_t k0g0g[8] = { 255, 1, 255, 1, 255, 5, 255, 5 }; + const uint8x8_t shuffle = vld1_u8(k0g0g); +#endif + const uint32x4_t mask_ag = vdupq_n_u32(0xff00ff00u); + int i; + for (i = 0; i + 4 <= num_pixels; i += 4) { + const uint8x16_t in = vld1q_u8((const uint8_t*)(src + i)); + const uint32x4_t a0g0 = vandq_u32(vreinterpretq_u32_u8(in), mask_ag); + // 0 g 0 g + const uint8x16_t greens = DoGreenShuffle_NEON(in, shuffle); + // x dr x db1 + const int16x8_t A = vqdmulhq_s16(vreinterpretq_s16_u8(greens), mults_rb); + // x r' x b' + const int8x16_t B = vaddq_s8(vreinterpretq_s8_u8(in), + vreinterpretq_s8_s16(A)); + // r' 0 b' 0 + const int16x8_t C = vshlq_n_s16(vreinterpretq_s16_s8(B), 8); + // x db2 0 0 + const int16x8_t D = vqdmulhq_s16(C, mults_b2); + // 0 x db2 0 + const uint32x4_t E = vshrq_n_u32(vreinterpretq_u32_s16(D), 8); + // r' x b'' 0 + const int8x16_t F = vaddq_s8(vreinterpretq_s8_u32(E), + vreinterpretq_s8_s16(C)); + // 0 r' 0 b'' + const uint16x8_t G = vshrq_n_u16(vreinterpretq_u16_s8(F), 8); + const uint32x4_t out = vorrq_u32(vreinterpretq_u32_u16(G), a0g0); + vst1q_u32(dst + i, out); + } + // Fall-back to C-version for left-overs. + VP8LTransformColorInverse_C(m, src + i, num_pixels - i, dst + i); +} + +#undef USE_VTBLQ + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8LDspInitNEON(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInitNEON(void) { + VP8LPredictors[5] = Predictor5_NEON; + VP8LPredictors[6] = Predictor6_NEON; + VP8LPredictors[7] = Predictor7_NEON; + VP8LPredictors[13] = Predictor13_NEON; + + VP8LPredictorsAdd[0] = PredictorAdd0_NEON; + VP8LPredictorsAdd[1] = PredictorAdd1_NEON; + VP8LPredictorsAdd[2] = PredictorAdd2_NEON; + VP8LPredictorsAdd[3] = PredictorAdd3_NEON; + VP8LPredictorsAdd[4] = PredictorAdd4_NEON; + VP8LPredictorsAdd[5] = PredictorAdd5_NEON; + VP8LPredictorsAdd[6] = PredictorAdd6_NEON; + VP8LPredictorsAdd[7] = PredictorAdd7_NEON; + VP8LPredictorsAdd[8] = PredictorAdd8_NEON; + VP8LPredictorsAdd[9] = PredictorAdd9_NEON; + VP8LPredictorsAdd[10] = PredictorAdd10_NEON; + VP8LPredictorsAdd[11] = PredictorAdd11_NEON; + VP8LPredictorsAdd[12] = PredictorAdd12_NEON; + VP8LPredictorsAdd[13] = PredictorAdd13_NEON; + + VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA_NEON; + VP8LConvertBGRAToBGR = ConvertBGRAToBGR_NEON; + VP8LConvertBGRAToRGB = ConvertBGRAToRGB_NEON; + + VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed_NEON; + VP8LTransformColorInverse = TransformColorInverse_NEON; +} + +#else // !WEBP_USE_NEON + +WEBP_DSP_INIT_STUB(VP8LDspInitNEON) + +#endif // WEBP_USE_NEON diff --git a/third-party/webp/libwebp/src/dsp/lossless_sse2.c b/third-party/webp/libwebp/src/dsp/lossless_sse2.c new file mode 100644 index 0000000000..4b6a532c23 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/lossless_sse2.c @@ -0,0 +1,712 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE2 variant of methods for lossless decoder +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE2) + +#include "src/dsp/common_sse2.h" +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" +#include + +//------------------------------------------------------------------------------ +// Predictor Transform + +static WEBP_INLINE uint32_t ClampedAddSubtractFull_SSE2(uint32_t c0, + uint32_t c1, + uint32_t c2) { + const __m128i zero = _mm_setzero_si128(); + const __m128i C0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128((int)c0), zero); + const __m128i C1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128((int)c1), zero); + const __m128i C2 = _mm_unpacklo_epi8(_mm_cvtsi32_si128((int)c2), zero); + const __m128i V1 = _mm_add_epi16(C0, C1); + const __m128i V2 = _mm_sub_epi16(V1, C2); + const __m128i b = _mm_packus_epi16(V2, V2); + return (uint32_t)_mm_cvtsi128_si32(b); +} + +static WEBP_INLINE uint32_t ClampedAddSubtractHalf_SSE2(uint32_t c0, + uint32_t c1, + uint32_t c2) { + const __m128i zero = _mm_setzero_si128(); + const __m128i C0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128((int)c0), zero); + const __m128i C1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128((int)c1), zero); + const __m128i B0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128((int)c2), zero); + const __m128i avg = _mm_add_epi16(C1, C0); + const __m128i A0 = _mm_srli_epi16(avg, 1); + const __m128i A1 = _mm_sub_epi16(A0, B0); + const __m128i BgtA = _mm_cmpgt_epi16(B0, A0); + const __m128i A2 = _mm_sub_epi16(A1, BgtA); + const __m128i A3 = _mm_srai_epi16(A2, 1); + const __m128i A4 = _mm_add_epi16(A0, A3); + const __m128i A5 = _mm_packus_epi16(A4, A4); + return (uint32_t)_mm_cvtsi128_si32(A5); +} + +static WEBP_INLINE uint32_t Select_SSE2(uint32_t a, uint32_t b, uint32_t c) { + int pa_minus_pb; + const __m128i zero = _mm_setzero_si128(); + const __m128i A0 = _mm_cvtsi32_si128((int)a); + const __m128i B0 = _mm_cvtsi32_si128((int)b); + const __m128i C0 = _mm_cvtsi32_si128((int)c); + const __m128i AC0 = _mm_subs_epu8(A0, C0); + const __m128i CA0 = _mm_subs_epu8(C0, A0); + const __m128i BC0 = _mm_subs_epu8(B0, C0); + const __m128i CB0 = _mm_subs_epu8(C0, B0); + const __m128i AC = _mm_or_si128(AC0, CA0); + const __m128i BC = _mm_or_si128(BC0, CB0); + const __m128i pa = _mm_unpacklo_epi8(AC, zero); // |a - c| + const __m128i pb = _mm_unpacklo_epi8(BC, zero); // |b - c| + const __m128i diff = _mm_sub_epi16(pb, pa); + { + int16_t out[8]; + _mm_storeu_si128((__m128i*)out, diff); + pa_minus_pb = out[0] + out[1] + out[2] + out[3]; + } + return (pa_minus_pb <= 0) ? a : b; +} + +static WEBP_INLINE void Average2_m128i(const __m128i* const a0, + const __m128i* const a1, + __m128i* const avg) { + // (a + b) >> 1 = ((a + b + 1) >> 1) - ((a ^ b) & 1) + const __m128i ones = _mm_set1_epi8(1); + const __m128i avg1 = _mm_avg_epu8(*a0, *a1); + const __m128i one = _mm_and_si128(_mm_xor_si128(*a0, *a1), ones); + *avg = _mm_sub_epi8(avg1, one); +} + +static WEBP_INLINE void Average2_uint32_SSE2(const uint32_t a0, + const uint32_t a1, + __m128i* const avg) { + // (a + b) >> 1 = ((a + b + 1) >> 1) - ((a ^ b) & 1) + const __m128i ones = _mm_set1_epi8(1); + const __m128i A0 = _mm_cvtsi32_si128((int)a0); + const __m128i A1 = _mm_cvtsi32_si128((int)a1); + const __m128i avg1 = _mm_avg_epu8(A0, A1); + const __m128i one = _mm_and_si128(_mm_xor_si128(A0, A1), ones); + *avg = _mm_sub_epi8(avg1, one); +} + +static WEBP_INLINE __m128i Average2_uint32_16_SSE2(uint32_t a0, uint32_t a1) { + const __m128i zero = _mm_setzero_si128(); + const __m128i A0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128((int)a0), zero); + const __m128i A1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128((int)a1), zero); + const __m128i sum = _mm_add_epi16(A1, A0); + return _mm_srli_epi16(sum, 1); +} + +static WEBP_INLINE uint32_t Average2_SSE2(uint32_t a0, uint32_t a1) { + __m128i output; + Average2_uint32_SSE2(a0, a1, &output); + return (uint32_t)_mm_cvtsi128_si32(output); +} + +static WEBP_INLINE uint32_t Average3_SSE2(uint32_t a0, uint32_t a1, + uint32_t a2) { + const __m128i zero = _mm_setzero_si128(); + const __m128i avg1 = Average2_uint32_16_SSE2(a0, a2); + const __m128i A1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128((int)a1), zero); + const __m128i sum = _mm_add_epi16(avg1, A1); + const __m128i avg2 = _mm_srli_epi16(sum, 1); + const __m128i A2 = _mm_packus_epi16(avg2, avg2); + return (uint32_t)_mm_cvtsi128_si32(A2); +} + +static WEBP_INLINE uint32_t Average4_SSE2(uint32_t a0, uint32_t a1, + uint32_t a2, uint32_t a3) { + const __m128i avg1 = Average2_uint32_16_SSE2(a0, a1); + const __m128i avg2 = Average2_uint32_16_SSE2(a2, a3); + const __m128i sum = _mm_add_epi16(avg2, avg1); + const __m128i avg3 = _mm_srli_epi16(sum, 1); + const __m128i A0 = _mm_packus_epi16(avg3, avg3); + return (uint32_t)_mm_cvtsi128_si32(A0); +} + +static uint32_t Predictor5_SSE2(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average3_SSE2(*left, top[0], top[1]); + return pred; +} +static uint32_t Predictor6_SSE2(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average2_SSE2(*left, top[-1]); + return pred; +} +static uint32_t Predictor7_SSE2(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average2_SSE2(*left, top[0]); + return pred; +} +static uint32_t Predictor8_SSE2(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average2_SSE2(top[-1], top[0]); + (void)left; + return pred; +} +static uint32_t Predictor9_SSE2(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average2_SSE2(top[0], top[1]); + (void)left; + return pred; +} +static uint32_t Predictor10_SSE2(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Average4_SSE2(*left, top[-1], top[0], top[1]); + return pred; +} +static uint32_t Predictor11_SSE2(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = Select_SSE2(top[0], *left, top[-1]); + return pred; +} +static uint32_t Predictor12_SSE2(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = ClampedAddSubtractFull_SSE2(*left, top[0], top[-1]); + return pred; +} +static uint32_t Predictor13_SSE2(const uint32_t* const left, + const uint32_t* const top) { + const uint32_t pred = ClampedAddSubtractHalf_SSE2(*left, top[0], top[-1]); + return pred; +} + +// Batch versions of those functions. + +// Predictor0: ARGB_BLACK. +static void PredictorAdd0_SSE2(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + const __m128i black = _mm_set1_epi32((int)ARGB_BLACK); + for (i = 0; i + 4 <= num_pixels; i += 4) { + const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); + const __m128i res = _mm_add_epi8(src, black); + _mm_storeu_si128((__m128i*)&out[i], res); + } + if (i != num_pixels) { + VP8LPredictorsAdd_C[0](in + i, NULL, num_pixels - i, out + i); + } + (void)upper; +} + +// Predictor1: left. +static void PredictorAdd1_SSE2(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + __m128i prev = _mm_set1_epi32((int)out[-1]); + for (i = 0; i + 4 <= num_pixels; i += 4) { + // a | b | c | d + const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); + // 0 | a | b | c + const __m128i shift0 = _mm_slli_si128(src, 4); + // a | a + b | b + c | c + d + const __m128i sum0 = _mm_add_epi8(src, shift0); + // 0 | 0 | a | a + b + const __m128i shift1 = _mm_slli_si128(sum0, 8); + // a | a + b | a + b + c | a + b + c + d + const __m128i sum1 = _mm_add_epi8(sum0, shift1); + const __m128i res = _mm_add_epi8(sum1, prev); + _mm_storeu_si128((__m128i*)&out[i], res); + // replicate prev output on the four lanes + prev = _mm_shuffle_epi32(res, (3 << 0) | (3 << 2) | (3 << 4) | (3 << 6)); + } + if (i != num_pixels) { + VP8LPredictorsAdd_C[1](in + i, upper + i, num_pixels - i, out + i); + } +} + +// Macro that adds 32-bit integers from IN using mod 256 arithmetic +// per 8 bit channel. +#define GENERATE_PREDICTOR_1(X, IN) \ +static void PredictorAdd##X##_SSE2(const uint32_t* in, const uint32_t* upper, \ + int num_pixels, uint32_t* out) { \ + int i; \ + for (i = 0; i + 4 <= num_pixels; i += 4) { \ + const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); \ + const __m128i other = _mm_loadu_si128((const __m128i*)&(IN)); \ + const __m128i res = _mm_add_epi8(src, other); \ + _mm_storeu_si128((__m128i*)&out[i], res); \ + } \ + if (i != num_pixels) { \ + VP8LPredictorsAdd_C[(X)](in + i, upper + i, num_pixels - i, out + i); \ + } \ +} + +// Predictor2: Top. +GENERATE_PREDICTOR_1(2, upper[i]) +// Predictor3: Top-right. +GENERATE_PREDICTOR_1(3, upper[i + 1]) +// Predictor4: Top-left. +GENERATE_PREDICTOR_1(4, upper[i - 1]) +#undef GENERATE_PREDICTOR_1 + +// Due to averages with integers, values cannot be accumulated in parallel for +// predictors 5 to 7. +GENERATE_PREDICTOR_ADD(Predictor5_SSE2, PredictorAdd5_SSE2) +GENERATE_PREDICTOR_ADD(Predictor6_SSE2, PredictorAdd6_SSE2) +GENERATE_PREDICTOR_ADD(Predictor7_SSE2, PredictorAdd7_SSE2) + +#define GENERATE_PREDICTOR_2(X, IN) \ +static void PredictorAdd##X##_SSE2(const uint32_t* in, const uint32_t* upper, \ + int num_pixels, uint32_t* out) { \ + int i; \ + for (i = 0; i + 4 <= num_pixels; i += 4) { \ + const __m128i Tother = _mm_loadu_si128((const __m128i*)&(IN)); \ + const __m128i T = _mm_loadu_si128((const __m128i*)&upper[i]); \ + const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); \ + __m128i avg, res; \ + Average2_m128i(&T, &Tother, &avg); \ + res = _mm_add_epi8(avg, src); \ + _mm_storeu_si128((__m128i*)&out[i], res); \ + } \ + if (i != num_pixels) { \ + VP8LPredictorsAdd_C[(X)](in + i, upper + i, num_pixels - i, out + i); \ + } \ +} +// Predictor8: average TL T. +GENERATE_PREDICTOR_2(8, upper[i - 1]) +// Predictor9: average T TR. +GENERATE_PREDICTOR_2(9, upper[i + 1]) +#undef GENERATE_PREDICTOR_2 + +// Predictor10: average of (average of (L,TL), average of (T, TR)). +#define DO_PRED10(OUT) do { \ + __m128i avgLTL, avg; \ + Average2_m128i(&L, &TL, &avgLTL); \ + Average2_m128i(&avgTTR, &avgLTL, &avg); \ + L = _mm_add_epi8(avg, src); \ + out[i + (OUT)] = (uint32_t)_mm_cvtsi128_si32(L); \ +} while (0) + +#define DO_PRED10_SHIFT do { \ + /* Rotate the pre-computed values for the next iteration.*/ \ + avgTTR = _mm_srli_si128(avgTTR, 4); \ + TL = _mm_srli_si128(TL, 4); \ + src = _mm_srli_si128(src, 4); \ +} while (0) + +static void PredictorAdd10_SSE2(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + __m128i L = _mm_cvtsi32_si128((int)out[-1]); + for (i = 0; i + 4 <= num_pixels; i += 4) { + __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); + __m128i TL = _mm_loadu_si128((const __m128i*)&upper[i - 1]); + const __m128i T = _mm_loadu_si128((const __m128i*)&upper[i]); + const __m128i TR = _mm_loadu_si128((const __m128i*)&upper[i + 1]); + __m128i avgTTR; + Average2_m128i(&T, &TR, &avgTTR); + DO_PRED10(0); + DO_PRED10_SHIFT; + DO_PRED10(1); + DO_PRED10_SHIFT; + DO_PRED10(2); + DO_PRED10_SHIFT; + DO_PRED10(3); + } + if (i != num_pixels) { + VP8LPredictorsAdd_C[10](in + i, upper + i, num_pixels - i, out + i); + } +} +#undef DO_PRED10 +#undef DO_PRED10_SHIFT + +// Predictor11: select. +#define DO_PRED11(OUT) do { \ + const __m128i L_lo = _mm_unpacklo_epi32(L, T); \ + const __m128i TL_lo = _mm_unpacklo_epi32(TL, T); \ + const __m128i pb = _mm_sad_epu8(L_lo, TL_lo); /* pb = sum |L-TL|*/ \ + const __m128i mask = _mm_cmpgt_epi32(pb, pa); \ + const __m128i A = _mm_and_si128(mask, L); \ + const __m128i B = _mm_andnot_si128(mask, T); \ + const __m128i pred = _mm_or_si128(A, B); /* pred = (pa > b)? L : T*/ \ + L = _mm_add_epi8(src, pred); \ + out[i + (OUT)] = (uint32_t)_mm_cvtsi128_si32(L); \ +} while (0) + +#define DO_PRED11_SHIFT do { \ + /* Shift the pre-computed value for the next iteration.*/ \ + T = _mm_srli_si128(T, 4); \ + TL = _mm_srli_si128(TL, 4); \ + src = _mm_srli_si128(src, 4); \ + pa = _mm_srli_si128(pa, 4); \ +} while (0) + +static void PredictorAdd11_SSE2(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + __m128i pa; + __m128i L = _mm_cvtsi32_si128((int)out[-1]); + for (i = 0; i + 4 <= num_pixels; i += 4) { + __m128i T = _mm_loadu_si128((const __m128i*)&upper[i]); + __m128i TL = _mm_loadu_si128((const __m128i*)&upper[i - 1]); + __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); + { + // We can unpack with any value on the upper 32 bits, provided it's the + // same on both operands (so that their sum of abs diff is zero). Here we + // use T. + const __m128i T_lo = _mm_unpacklo_epi32(T, T); + const __m128i TL_lo = _mm_unpacklo_epi32(TL, T); + const __m128i T_hi = _mm_unpackhi_epi32(T, T); + const __m128i TL_hi = _mm_unpackhi_epi32(TL, T); + const __m128i s_lo = _mm_sad_epu8(T_lo, TL_lo); + const __m128i s_hi = _mm_sad_epu8(T_hi, TL_hi); + pa = _mm_packs_epi32(s_lo, s_hi); // pa = sum |T-TL| + } + DO_PRED11(0); + DO_PRED11_SHIFT; + DO_PRED11(1); + DO_PRED11_SHIFT; + DO_PRED11(2); + DO_PRED11_SHIFT; + DO_PRED11(3); + } + if (i != num_pixels) { + VP8LPredictorsAdd_C[11](in + i, upper + i, num_pixels - i, out + i); + } +} +#undef DO_PRED11 +#undef DO_PRED11_SHIFT + +// Predictor12: ClampedAddSubtractFull. +#define DO_PRED12(DIFF, LANE, OUT) do { \ + const __m128i all = _mm_add_epi16(L, (DIFF)); \ + const __m128i alls = _mm_packus_epi16(all, all); \ + const __m128i res = _mm_add_epi8(src, alls); \ + out[i + (OUT)] = (uint32_t)_mm_cvtsi128_si32(res); \ + L = _mm_unpacklo_epi8(res, zero); \ +} while (0) + +#define DO_PRED12_SHIFT(DIFF, LANE) do { \ + /* Shift the pre-computed value for the next iteration.*/ \ + if ((LANE) == 0) (DIFF) = _mm_srli_si128((DIFF), 8); \ + src = _mm_srli_si128(src, 4); \ +} while (0) + +static void PredictorAdd12_SSE2(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { + int i; + const __m128i zero = _mm_setzero_si128(); + const __m128i L8 = _mm_cvtsi32_si128((int)out[-1]); + __m128i L = _mm_unpacklo_epi8(L8, zero); + for (i = 0; i + 4 <= num_pixels; i += 4) { + // Load 4 pixels at a time. + __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); + const __m128i T = _mm_loadu_si128((const __m128i*)&upper[i]); + const __m128i T_lo = _mm_unpacklo_epi8(T, zero); + const __m128i T_hi = _mm_unpackhi_epi8(T, zero); + const __m128i TL = _mm_loadu_si128((const __m128i*)&upper[i - 1]); + const __m128i TL_lo = _mm_unpacklo_epi8(TL, zero); + const __m128i TL_hi = _mm_unpackhi_epi8(TL, zero); + __m128i diff_lo = _mm_sub_epi16(T_lo, TL_lo); + __m128i diff_hi = _mm_sub_epi16(T_hi, TL_hi); + DO_PRED12(diff_lo, 0, 0); + DO_PRED12_SHIFT(diff_lo, 0); + DO_PRED12(diff_lo, 1, 1); + DO_PRED12_SHIFT(diff_lo, 1); + DO_PRED12(diff_hi, 0, 2); + DO_PRED12_SHIFT(diff_hi, 0); + DO_PRED12(diff_hi, 1, 3); + } + if (i != num_pixels) { + VP8LPredictorsAdd_C[12](in + i, upper + i, num_pixels - i, out + i); + } +} +#undef DO_PRED12 +#undef DO_PRED12_SHIFT + +// Due to averages with integers, values cannot be accumulated in parallel for +// predictors 13. +GENERATE_PREDICTOR_ADD(Predictor13_SSE2, PredictorAdd13_SSE2) + +//------------------------------------------------------------------------------ +// Subtract-Green Transform + +static void AddGreenToBlueAndRed_SSE2(const uint32_t* const src, int num_pixels, + uint32_t* dst) { + int i; + for (i = 0; i + 4 <= num_pixels; i += 4) { + const __m128i in = _mm_loadu_si128((const __m128i*)&src[i]); // argb + const __m128i A = _mm_srli_epi16(in, 8); // 0 a 0 g + const __m128i B = _mm_shufflelo_epi16(A, _MM_SHUFFLE(2, 2, 0, 0)); + const __m128i C = _mm_shufflehi_epi16(B, _MM_SHUFFLE(2, 2, 0, 0)); // 0g0g + const __m128i out = _mm_add_epi8(in, C); + _mm_storeu_si128((__m128i*)&dst[i], out); + } + // fallthrough and finish off with plain-C + if (i != num_pixels) { + VP8LAddGreenToBlueAndRed_C(src + i, num_pixels - i, dst + i); + } +} + +//------------------------------------------------------------------------------ +// Color Transform + +static void TransformColorInverse_SSE2(const VP8LMultipliers* const m, + const uint32_t* const src, + int num_pixels, uint32_t* dst) { +// sign-extended multiplying constants, pre-shifted by 5. +#define CST(X) (((int16_t)(m->X << 8)) >> 5) // sign-extend +#define MK_CST_16(HI, LO) \ + _mm_set1_epi32((int)(((uint32_t)(HI) << 16) | ((LO) & 0xffff))) + const __m128i mults_rb = MK_CST_16(CST(green_to_red_), CST(green_to_blue_)); + const __m128i mults_b2 = MK_CST_16(CST(red_to_blue_), 0); +#undef MK_CST_16 +#undef CST + const __m128i mask_ag = _mm_set1_epi32((int)0xff00ff00); // alpha-green masks + int i; + for (i = 0; i + 4 <= num_pixels; i += 4) { + const __m128i in = _mm_loadu_si128((const __m128i*)&src[i]); // argb + const __m128i A = _mm_and_si128(in, mask_ag); // a 0 g 0 + const __m128i B = _mm_shufflelo_epi16(A, _MM_SHUFFLE(2, 2, 0, 0)); + const __m128i C = _mm_shufflehi_epi16(B, _MM_SHUFFLE(2, 2, 0, 0)); // g0g0 + const __m128i D = _mm_mulhi_epi16(C, mults_rb); // x dr x db1 + const __m128i E = _mm_add_epi8(in, D); // x r' x b' + const __m128i F = _mm_slli_epi16(E, 8); // r' 0 b' 0 + const __m128i G = _mm_mulhi_epi16(F, mults_b2); // x db2 0 0 + const __m128i H = _mm_srli_epi32(G, 8); // 0 x db2 0 + const __m128i I = _mm_add_epi8(H, F); // r' x b'' 0 + const __m128i J = _mm_srli_epi16(I, 8); // 0 r' 0 b'' + const __m128i out = _mm_or_si128(J, A); + _mm_storeu_si128((__m128i*)&dst[i], out); + } + // Fall-back to C-version for left-overs. + if (i != num_pixels) { + VP8LTransformColorInverse_C(m, src + i, num_pixels - i, dst + i); + } +} + +//------------------------------------------------------------------------------ +// Color-space conversion functions + +static void ConvertBGRAToRGB_SSE2(const uint32_t* src, int num_pixels, + uint8_t* dst) { + const __m128i* in = (const __m128i*)src; + __m128i* out = (__m128i*)dst; + + while (num_pixels >= 32) { + // Load the BGRA buffers. + __m128i in0 = _mm_loadu_si128(in + 0); + __m128i in1 = _mm_loadu_si128(in + 1); + __m128i in2 = _mm_loadu_si128(in + 2); + __m128i in3 = _mm_loadu_si128(in + 3); + __m128i in4 = _mm_loadu_si128(in + 4); + __m128i in5 = _mm_loadu_si128(in + 5); + __m128i in6 = _mm_loadu_si128(in + 6); + __m128i in7 = _mm_loadu_si128(in + 7); + VP8L32bToPlanar_SSE2(&in0, &in1, &in2, &in3); + VP8L32bToPlanar_SSE2(&in4, &in5, &in6, &in7); + // At this points, in1/in5 contains red only, in2/in6 green only ... + // Pack the colors in 24b RGB. + VP8PlanarTo24b_SSE2(&in1, &in5, &in2, &in6, &in3, &in7); + _mm_storeu_si128(out + 0, in1); + _mm_storeu_si128(out + 1, in5); + _mm_storeu_si128(out + 2, in2); + _mm_storeu_si128(out + 3, in6); + _mm_storeu_si128(out + 4, in3); + _mm_storeu_si128(out + 5, in7); + in += 8; + out += 6; + num_pixels -= 32; + } + // left-overs + if (num_pixels > 0) { + VP8LConvertBGRAToRGB_C((const uint32_t*)in, num_pixels, (uint8_t*)out); + } +} + +static void ConvertBGRAToRGBA_SSE2(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const __m128i red_blue_mask = _mm_set1_epi32(0x00ff00ff); + const __m128i* in = (const __m128i*)src; + __m128i* out = (__m128i*)dst; + while (num_pixels >= 8) { + const __m128i A1 = _mm_loadu_si128(in++); + const __m128i A2 = _mm_loadu_si128(in++); + const __m128i B1 = _mm_and_si128(A1, red_blue_mask); // R 0 B 0 + const __m128i B2 = _mm_and_si128(A2, red_blue_mask); // R 0 B 0 + const __m128i C1 = _mm_andnot_si128(red_blue_mask, A1); // 0 G 0 A + const __m128i C2 = _mm_andnot_si128(red_blue_mask, A2); // 0 G 0 A + const __m128i D1 = _mm_shufflelo_epi16(B1, _MM_SHUFFLE(2, 3, 0, 1)); + const __m128i D2 = _mm_shufflelo_epi16(B2, _MM_SHUFFLE(2, 3, 0, 1)); + const __m128i E1 = _mm_shufflehi_epi16(D1, _MM_SHUFFLE(2, 3, 0, 1)); + const __m128i E2 = _mm_shufflehi_epi16(D2, _MM_SHUFFLE(2, 3, 0, 1)); + const __m128i F1 = _mm_or_si128(E1, C1); + const __m128i F2 = _mm_or_si128(E2, C2); + _mm_storeu_si128(out++, F1); + _mm_storeu_si128(out++, F2); + num_pixels -= 8; + } + // left-overs + if (num_pixels > 0) { + VP8LConvertBGRAToRGBA_C((const uint32_t*)in, num_pixels, (uint8_t*)out); + } +} + +static void ConvertBGRAToRGBA4444_SSE2(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const __m128i mask_0x0f = _mm_set1_epi8(0x0f); + const __m128i mask_0xf0 = _mm_set1_epi8((char)0xf0); + const __m128i* in = (const __m128i*)src; + __m128i* out = (__m128i*)dst; + while (num_pixels >= 8) { + const __m128i bgra0 = _mm_loadu_si128(in++); // bgra0|bgra1|bgra2|bgra3 + const __m128i bgra4 = _mm_loadu_si128(in++); // bgra4|bgra5|bgra6|bgra7 + const __m128i v0l = _mm_unpacklo_epi8(bgra0, bgra4); // b0b4g0g4r0r4a0a4... + const __m128i v0h = _mm_unpackhi_epi8(bgra0, bgra4); // b2b6g2g6r2r6a2a6... + const __m128i v1l = _mm_unpacklo_epi8(v0l, v0h); // b0b2b4b6g0g2g4g6... + const __m128i v1h = _mm_unpackhi_epi8(v0l, v0h); // b1b3b5b7g1g3g5g7... + const __m128i v2l = _mm_unpacklo_epi8(v1l, v1h); // b0...b7 | g0...g7 + const __m128i v2h = _mm_unpackhi_epi8(v1l, v1h); // r0...r7 | a0...a7 + const __m128i ga0 = _mm_unpackhi_epi64(v2l, v2h); // g0...g7 | a0...a7 + const __m128i rb0 = _mm_unpacklo_epi64(v2h, v2l); // r0...r7 | b0...b7 + const __m128i ga1 = _mm_srli_epi16(ga0, 4); // g0-|g1-|...|a6-|a7- + const __m128i rb1 = _mm_and_si128(rb0, mask_0xf0); // -r0|-r1|...|-b6|-a7 + const __m128i ga2 = _mm_and_si128(ga1, mask_0x0f); // g0-|g1-|...|a6-|a7- + const __m128i rgba0 = _mm_or_si128(ga2, rb1); // rg0..rg7 | ba0..ba7 + const __m128i rgba1 = _mm_srli_si128(rgba0, 8); // ba0..ba7 | 0 +#if (WEBP_SWAP_16BIT_CSP == 1) + const __m128i rgba = _mm_unpacklo_epi8(rgba1, rgba0); // barg0...barg7 +#else + const __m128i rgba = _mm_unpacklo_epi8(rgba0, rgba1); // rgba0...rgba7 +#endif + _mm_storeu_si128(out++, rgba); + num_pixels -= 8; + } + // left-overs + if (num_pixels > 0) { + VP8LConvertBGRAToRGBA4444_C((const uint32_t*)in, num_pixels, (uint8_t*)out); + } +} + +static void ConvertBGRAToRGB565_SSE2(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const __m128i mask_0xe0 = _mm_set1_epi8((char)0xe0); + const __m128i mask_0xf8 = _mm_set1_epi8((char)0xf8); + const __m128i mask_0x07 = _mm_set1_epi8(0x07); + const __m128i* in = (const __m128i*)src; + __m128i* out = (__m128i*)dst; + while (num_pixels >= 8) { + const __m128i bgra0 = _mm_loadu_si128(in++); // bgra0|bgra1|bgra2|bgra3 + const __m128i bgra4 = _mm_loadu_si128(in++); // bgra4|bgra5|bgra6|bgra7 + const __m128i v0l = _mm_unpacklo_epi8(bgra0, bgra4); // b0b4g0g4r0r4a0a4... + const __m128i v0h = _mm_unpackhi_epi8(bgra0, bgra4); // b2b6g2g6r2r6a2a6... + const __m128i v1l = _mm_unpacklo_epi8(v0l, v0h); // b0b2b4b6g0g2g4g6... + const __m128i v1h = _mm_unpackhi_epi8(v0l, v0h); // b1b3b5b7g1g3g5g7... + const __m128i v2l = _mm_unpacklo_epi8(v1l, v1h); // b0...b7 | g0...g7 + const __m128i v2h = _mm_unpackhi_epi8(v1l, v1h); // r0...r7 | a0...a7 + const __m128i ga0 = _mm_unpackhi_epi64(v2l, v2h); // g0...g7 | a0...a7 + const __m128i rb0 = _mm_unpacklo_epi64(v2h, v2l); // r0...r7 | b0...b7 + const __m128i rb1 = _mm_and_si128(rb0, mask_0xf8); // -r0..-r7|-b0..-b7 + const __m128i g_lo1 = _mm_srli_epi16(ga0, 5); + const __m128i g_lo2 = _mm_and_si128(g_lo1, mask_0x07); // g0-...g7-|xx (3b) + const __m128i g_hi1 = _mm_slli_epi16(ga0, 3); + const __m128i g_hi2 = _mm_and_si128(g_hi1, mask_0xe0); // -g0...-g7|xx (3b) + const __m128i b0 = _mm_srli_si128(rb1, 8); // -b0...-b7|0 + const __m128i rg1 = _mm_or_si128(rb1, g_lo2); // gr0...gr7|xx + const __m128i b1 = _mm_srli_epi16(b0, 3); + const __m128i gb1 = _mm_or_si128(b1, g_hi2); // bg0...bg7|xx +#if (WEBP_SWAP_16BIT_CSP == 1) + const __m128i rgba = _mm_unpacklo_epi8(gb1, rg1); // rggb0...rggb7 +#else + const __m128i rgba = _mm_unpacklo_epi8(rg1, gb1); // bgrb0...bgrb7 +#endif + _mm_storeu_si128(out++, rgba); + num_pixels -= 8; + } + // left-overs + if (num_pixels > 0) { + VP8LConvertBGRAToRGB565_C((const uint32_t*)in, num_pixels, (uint8_t*)out); + } +} + +static void ConvertBGRAToBGR_SSE2(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const __m128i mask_l = _mm_set_epi32(0, 0x00ffffff, 0, 0x00ffffff); + const __m128i mask_h = _mm_set_epi32(0x00ffffff, 0, 0x00ffffff, 0); + const __m128i* in = (const __m128i*)src; + const uint8_t* const end = dst + num_pixels * 3; + // the last storel_epi64 below writes 8 bytes starting at offset 18 + while (dst + 26 <= end) { + const __m128i bgra0 = _mm_loadu_si128(in++); // bgra0|bgra1|bgra2|bgra3 + const __m128i bgra4 = _mm_loadu_si128(in++); // bgra4|bgra5|bgra6|bgra7 + const __m128i a0l = _mm_and_si128(bgra0, mask_l); // bgr0|0|bgr0|0 + const __m128i a4l = _mm_and_si128(bgra4, mask_l); // bgr0|0|bgr0|0 + const __m128i a0h = _mm_and_si128(bgra0, mask_h); // 0|bgr0|0|bgr0 + const __m128i a4h = _mm_and_si128(bgra4, mask_h); // 0|bgr0|0|bgr0 + const __m128i b0h = _mm_srli_epi64(a0h, 8); // 000b|gr00|000b|gr00 + const __m128i b4h = _mm_srli_epi64(a4h, 8); // 000b|gr00|000b|gr00 + const __m128i c0 = _mm_or_si128(a0l, b0h); // rgbrgb00|rgbrgb00 + const __m128i c4 = _mm_or_si128(a4l, b4h); // rgbrgb00|rgbrgb00 + const __m128i c2 = _mm_srli_si128(c0, 8); + const __m128i c6 = _mm_srli_si128(c4, 8); + _mm_storel_epi64((__m128i*)(dst + 0), c0); + _mm_storel_epi64((__m128i*)(dst + 6), c2); + _mm_storel_epi64((__m128i*)(dst + 12), c4); + _mm_storel_epi64((__m128i*)(dst + 18), c6); + dst += 24; + num_pixels -= 8; + } + // left-overs + if (num_pixels > 0) { + VP8LConvertBGRAToBGR_C((const uint32_t*)in, num_pixels, dst); + } +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8LDspInitSSE2(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInitSSE2(void) { + VP8LPredictors[5] = Predictor5_SSE2; + VP8LPredictors[6] = Predictor6_SSE2; + VP8LPredictors[7] = Predictor7_SSE2; + VP8LPredictors[8] = Predictor8_SSE2; + VP8LPredictors[9] = Predictor9_SSE2; + VP8LPredictors[10] = Predictor10_SSE2; + VP8LPredictors[11] = Predictor11_SSE2; + VP8LPredictors[12] = Predictor12_SSE2; + VP8LPredictors[13] = Predictor13_SSE2; + + VP8LPredictorsAdd[0] = PredictorAdd0_SSE2; + VP8LPredictorsAdd[1] = PredictorAdd1_SSE2; + VP8LPredictorsAdd[2] = PredictorAdd2_SSE2; + VP8LPredictorsAdd[3] = PredictorAdd3_SSE2; + VP8LPredictorsAdd[4] = PredictorAdd4_SSE2; + VP8LPredictorsAdd[5] = PredictorAdd5_SSE2; + VP8LPredictorsAdd[6] = PredictorAdd6_SSE2; + VP8LPredictorsAdd[7] = PredictorAdd7_SSE2; + VP8LPredictorsAdd[8] = PredictorAdd8_SSE2; + VP8LPredictorsAdd[9] = PredictorAdd9_SSE2; + VP8LPredictorsAdd[10] = PredictorAdd10_SSE2; + VP8LPredictorsAdd[11] = PredictorAdd11_SSE2; + VP8LPredictorsAdd[12] = PredictorAdd12_SSE2; + VP8LPredictorsAdd[13] = PredictorAdd13_SSE2; + + VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed_SSE2; + VP8LTransformColorInverse = TransformColorInverse_SSE2; + + VP8LConvertBGRAToRGB = ConvertBGRAToRGB_SSE2; + VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA_SSE2; + VP8LConvertBGRAToRGBA4444 = ConvertBGRAToRGBA4444_SSE2; + VP8LConvertBGRAToRGB565 = ConvertBGRAToRGB565_SSE2; + VP8LConvertBGRAToBGR = ConvertBGRAToBGR_SSE2; +} + +#else // !WEBP_USE_SSE2 + +WEBP_DSP_INIT_STUB(VP8LDspInitSSE2) + +#endif // WEBP_USE_SSE2 diff --git a/third-party/webp/libwebp/src/dsp/lossless_sse41.c b/third-party/webp/libwebp/src/dsp/lossless_sse41.c new file mode 100644 index 0000000000..bb7ce7611f --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/lossless_sse41.c @@ -0,0 +1,133 @@ +// Copyright 2021 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE41 variant of methods for lossless decoder + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE41) + +#include "src/dsp/common_sse41.h" +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" + +//------------------------------------------------------------------------------ +// Color-space conversion functions + +static void TransformColorInverse_SSE41(const VP8LMultipliers* const m, + const uint32_t* const src, + int num_pixels, uint32_t* dst) { +// sign-extended multiplying constants, pre-shifted by 5. +#define CST(X) (((int16_t)(m->X << 8)) >> 5) // sign-extend + const __m128i mults_rb = + _mm_set1_epi32((int)((uint32_t)CST(green_to_red_) << 16 | + (CST(green_to_blue_) & 0xffff))); + const __m128i mults_b2 = _mm_set1_epi32(CST(red_to_blue_)); +#undef CST + const __m128i mask_ag = _mm_set1_epi32((int)0xff00ff00); + const __m128i perm1 = _mm_setr_epi8(-1, 1, -1, 1, -1, 5, -1, 5, + -1, 9, -1, 9, -1, 13, -1, 13); + const __m128i perm2 = _mm_setr_epi8(-1, 2, -1, -1, -1, 6, -1, -1, + -1, 10, -1, -1, -1, 14, -1, -1); + int i; + for (i = 0; i + 4 <= num_pixels; i += 4) { + const __m128i A = _mm_loadu_si128((const __m128i*)(src + i)); + const __m128i B = _mm_shuffle_epi8(A, perm1); // argb -> g0g0 + const __m128i C = _mm_mulhi_epi16(B, mults_rb); + const __m128i D = _mm_add_epi8(A, C); + const __m128i E = _mm_shuffle_epi8(D, perm2); + const __m128i F = _mm_mulhi_epi16(E, mults_b2); + const __m128i G = _mm_add_epi8(D, F); + const __m128i out = _mm_blendv_epi8(G, A, mask_ag); + _mm_storeu_si128((__m128i*)&dst[i], out); + } + // Fall-back to C-version for left-overs. + if (i != num_pixels) { + VP8LTransformColorInverse_C(m, src + i, num_pixels - i, dst + i); + } +} + +//------------------------------------------------------------------------------ + +#define ARGB_TO_RGB_SSE41 do { \ + while (num_pixels >= 16) { \ + const __m128i in0 = _mm_loadu_si128(in + 0); \ + const __m128i in1 = _mm_loadu_si128(in + 1); \ + const __m128i in2 = _mm_loadu_si128(in + 2); \ + const __m128i in3 = _mm_loadu_si128(in + 3); \ + const __m128i a0 = _mm_shuffle_epi8(in0, perm0); \ + const __m128i a1 = _mm_shuffle_epi8(in1, perm1); \ + const __m128i a2 = _mm_shuffle_epi8(in2, perm2); \ + const __m128i a3 = _mm_shuffle_epi8(in3, perm3); \ + const __m128i b0 = _mm_blend_epi16(a0, a1, 0xc0); \ + const __m128i b1 = _mm_blend_epi16(a1, a2, 0xf0); \ + const __m128i b2 = _mm_blend_epi16(a2, a3, 0xfc); \ + _mm_storeu_si128(out + 0, b0); \ + _mm_storeu_si128(out + 1, b1); \ + _mm_storeu_si128(out + 2, b2); \ + in += 4; \ + out += 3; \ + num_pixels -= 16; \ + } \ +} while (0) + +static void ConvertBGRAToRGB_SSE41(const uint32_t* src, int num_pixels, + uint8_t* dst) { + const __m128i* in = (const __m128i*)src; + __m128i* out = (__m128i*)dst; + const __m128i perm0 = _mm_setr_epi8(2, 1, 0, 6, 5, 4, 10, 9, + 8, 14, 13, 12, -1, -1, -1, -1); + const __m128i perm1 = _mm_shuffle_epi32(perm0, 0x39); + const __m128i perm2 = _mm_shuffle_epi32(perm0, 0x4e); + const __m128i perm3 = _mm_shuffle_epi32(perm0, 0x93); + + ARGB_TO_RGB_SSE41; + + // left-overs + if (num_pixels > 0) { + VP8LConvertBGRAToRGB_C((const uint32_t*)in, num_pixels, (uint8_t*)out); + } +} + +static void ConvertBGRAToBGR_SSE41(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const __m128i* in = (const __m128i*)src; + __m128i* out = (__m128i*)dst; + const __m128i perm0 = _mm_setr_epi8(0, 1, 2, 4, 5, 6, 8, 9, 10, + 12, 13, 14, -1, -1, -1, -1); + const __m128i perm1 = _mm_shuffle_epi32(perm0, 0x39); + const __m128i perm2 = _mm_shuffle_epi32(perm0, 0x4e); + const __m128i perm3 = _mm_shuffle_epi32(perm0, 0x93); + + ARGB_TO_RGB_SSE41; + + // left-overs + if (num_pixels > 0) { + VP8LConvertBGRAToBGR_C((const uint32_t*)in, num_pixels, (uint8_t*)out); + } +} + +#undef ARGB_TO_RGB_SSE41 + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8LDspInitSSE41(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInitSSE41(void) { + VP8LTransformColorInverse = TransformColorInverse_SSE41; + VP8LConvertBGRAToRGB = ConvertBGRAToRGB_SSE41; + VP8LConvertBGRAToBGR = ConvertBGRAToBGR_SSE41; +} + +#else // !WEBP_USE_SSE41 + +WEBP_DSP_INIT_STUB(VP8LDspInitSSE41) + +#endif // WEBP_USE_SSE41 diff --git a/third-party/webp/libwebp/src/dsp/mips_macro.h b/third-party/webp/libwebp/src/dsp/mips_macro.h new file mode 100644 index 0000000000..44aba9b71d --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/mips_macro.h @@ -0,0 +1,200 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MIPS common macros + +#ifndef WEBP_DSP_MIPS_MACRO_H_ +#define WEBP_DSP_MIPS_MACRO_H_ + +#if defined(__GNUC__) && defined(__ANDROID__) && LOCAL_GCC_VERSION == 0x409 +#define WORK_AROUND_GCC +#endif + +#define STR(s) #s +#define XSTR(s) STR(s) + +// O0[31..16 | 15..0] = I0[31..16 | 15..0] + I1[31..16 | 15..0] +// O1[31..16 | 15..0] = I0[31..16 | 15..0] - I1[31..16 | 15..0] +// O - output +// I - input (macro doesn't change it) +#define ADD_SUB_HALVES(O0, O1, \ + I0, I1) \ + "addq.ph %[" #O0 "], %[" #I0 "], %[" #I1 "] \n\t" \ + "subq.ph %[" #O1 "], %[" #I0 "], %[" #I1 "] \n\t" + +// O - output +// I - input (macro doesn't change it) +// I[0/1] - offset in bytes +#define LOAD_IN_X2(O0, O1, \ + I0, I1) \ + "lh %[" #O0 "], " #I0 "(%[in]) \n\t" \ + "lh %[" #O1 "], " #I1 "(%[in]) \n\t" + +// I0 - location +// I1..I9 - offsets in bytes +#define LOAD_WITH_OFFSET_X4(O0, O1, O2, O3, \ + I0, I1, I2, I3, I4, I5, I6, I7, I8, I9) \ + "ulw %[" #O0 "], " #I1 "+" XSTR(I9) "*" #I5 "(%[" #I0 "]) \n\t" \ + "ulw %[" #O1 "], " #I2 "+" XSTR(I9) "*" #I6 "(%[" #I0 "]) \n\t" \ + "ulw %[" #O2 "], " #I3 "+" XSTR(I9) "*" #I7 "(%[" #I0 "]) \n\t" \ + "ulw %[" #O3 "], " #I4 "+" XSTR(I9) "*" #I8 "(%[" #I0 "]) \n\t" + +// O - output +// IO - input/output +// I - input (macro doesn't change it) +#define MUL_SHIFT_SUM(O0, O1, O2, O3, O4, O5, O6, O7, \ + IO0, IO1, IO2, IO3, \ + I0, I1, I2, I3, I4, I5, I6, I7) \ + "mul %[" #O0 "], %[" #I0 "], %[kC2] \n\t" \ + "mul %[" #O1 "], %[" #I0 "], %[kC1] \n\t" \ + "mul %[" #O2 "], %[" #I1 "], %[kC2] \n\t" \ + "mul %[" #O3 "], %[" #I1 "], %[kC1] \n\t" \ + "mul %[" #O4 "], %[" #I2 "], %[kC2] \n\t" \ + "mul %[" #O5 "], %[" #I2 "], %[kC1] \n\t" \ + "mul %[" #O6 "], %[" #I3 "], %[kC2] \n\t" \ + "mul %[" #O7 "], %[" #I3 "], %[kC1] \n\t" \ + "sra %[" #O0 "], %[" #O0 "], 16 \n\t" \ + "sra %[" #O1 "], %[" #O1 "], 16 \n\t" \ + "sra %[" #O2 "], %[" #O2 "], 16 \n\t" \ + "sra %[" #O3 "], %[" #O3 "], 16 \n\t" \ + "sra %[" #O4 "], %[" #O4 "], 16 \n\t" \ + "sra %[" #O5 "], %[" #O5 "], 16 \n\t" \ + "sra %[" #O6 "], %[" #O6 "], 16 \n\t" \ + "sra %[" #O7 "], %[" #O7 "], 16 \n\t" \ + "addu %[" #IO0 "], %[" #IO0 "], %[" #I4 "] \n\t" \ + "addu %[" #IO1 "], %[" #IO1 "], %[" #I5 "] \n\t" \ + "subu %[" #IO2 "], %[" #IO2 "], %[" #I6 "] \n\t" \ + "subu %[" #IO3 "], %[" #IO3 "], %[" #I7 "] \n\t" + +// O - output +// I - input (macro doesn't change it) +#define INSERT_HALF_X2(O0, O1, \ + I0, I1) \ + "ins %[" #O0 "], %[" #I0 "], 16, 16 \n\t" \ + "ins %[" #O1 "], %[" #I1 "], 16, 16 \n\t" + +// O - output +// I - input (macro doesn't change it) +#define SRA_16(O0, O1, O2, O3, \ + I0, I1, I2, I3) \ + "sra %[" #O0 "], %[" #I0 "], 16 \n\t" \ + "sra %[" #O1 "], %[" #I1 "], 16 \n\t" \ + "sra %[" #O2 "], %[" #I2 "], 16 \n\t" \ + "sra %[" #O3 "], %[" #I3 "], 16 \n\t" + +// temp0[31..16 | 15..0] = temp8[31..16 | 15..0] + temp12[31..16 | 15..0] +// temp1[31..16 | 15..0] = temp8[31..16 | 15..0] - temp12[31..16 | 15..0] +// temp0[31..16 | 15..0] = temp0[31..16 >> 3 | 15..0 >> 3] +// temp1[31..16 | 15..0] = temp1[31..16 >> 3 | 15..0 >> 3] +// O - output +// I - input (macro doesn't change it) +#define SHIFT_R_SUM_X2(O0, O1, O2, O3, O4, O5, O6, O7, \ + I0, I1, I2, I3, I4, I5, I6, I7) \ + "addq.ph %[" #O0 "], %[" #I0 "], %[" #I4 "] \n\t" \ + "subq.ph %[" #O1 "], %[" #I0 "], %[" #I4 "] \n\t" \ + "addq.ph %[" #O2 "], %[" #I1 "], %[" #I5 "] \n\t" \ + "subq.ph %[" #O3 "], %[" #I1 "], %[" #I5 "] \n\t" \ + "addq.ph %[" #O4 "], %[" #I2 "], %[" #I6 "] \n\t" \ + "subq.ph %[" #O5 "], %[" #I2 "], %[" #I6 "] \n\t" \ + "addq.ph %[" #O6 "], %[" #I3 "], %[" #I7 "] \n\t" \ + "subq.ph %[" #O7 "], %[" #I3 "], %[" #I7 "] \n\t" \ + "shra.ph %[" #O0 "], %[" #O0 "], 3 \n\t" \ + "shra.ph %[" #O1 "], %[" #O1 "], 3 \n\t" \ + "shra.ph %[" #O2 "], %[" #O2 "], 3 \n\t" \ + "shra.ph %[" #O3 "], %[" #O3 "], 3 \n\t" \ + "shra.ph %[" #O4 "], %[" #O4 "], 3 \n\t" \ + "shra.ph %[" #O5 "], %[" #O5 "], 3 \n\t" \ + "shra.ph %[" #O6 "], %[" #O6 "], 3 \n\t" \ + "shra.ph %[" #O7 "], %[" #O7 "], 3 \n\t" + +// precrq.ph.w temp0, temp8, temp2 +// temp0 = temp8[31..16] | temp2[31..16] +// ins temp2, temp8, 16, 16 +// temp2 = temp8[31..16] | temp2[15..0] +// O - output +// IO - input/output +// I - input (macro doesn't change it) +#define PACK_2_HALVES_TO_WORD(O0, O1, O2, O3, \ + IO0, IO1, IO2, IO3, \ + I0, I1, I2, I3) \ + "precrq.ph.w %[" #O0 "], %[" #I0 "], %[" #IO0 "] \n\t" \ + "precrq.ph.w %[" #O1 "], %[" #I1 "], %[" #IO1 "] \n\t" \ + "ins %[" #IO0 "], %[" #I0 "], 16, 16 \n\t" \ + "ins %[" #IO1 "], %[" #I1 "], 16, 16 \n\t" \ + "precrq.ph.w %[" #O2 "], %[" #I2 "], %[" #IO2 "] \n\t" \ + "precrq.ph.w %[" #O3 "], %[" #I3 "], %[" #IO3 "] \n\t" \ + "ins %[" #IO2 "], %[" #I2 "], 16, 16 \n\t" \ + "ins %[" #IO3 "], %[" #I3 "], 16, 16 \n\t" + +// preceu.ph.qbr temp0, temp8 +// temp0 = 0 | 0 | temp8[23..16] | temp8[7..0] +// preceu.ph.qbl temp1, temp8 +// temp1 = temp8[23..16] | temp8[7..0] | 0 | 0 +// O - output +// I - input (macro doesn't change it) +#define CONVERT_2_BYTES_TO_HALF(O0, O1, O2, O3, O4, O5, O6, O7, \ + I0, I1, I2, I3) \ + "preceu.ph.qbr %[" #O0 "], %[" #I0 "] \n\t" \ + "preceu.ph.qbl %[" #O1 "], %[" #I0 "] \n\t" \ + "preceu.ph.qbr %[" #O2 "], %[" #I1 "] \n\t" \ + "preceu.ph.qbl %[" #O3 "], %[" #I1 "] \n\t" \ + "preceu.ph.qbr %[" #O4 "], %[" #I2 "] \n\t" \ + "preceu.ph.qbl %[" #O5 "], %[" #I2 "] \n\t" \ + "preceu.ph.qbr %[" #O6 "], %[" #I3 "] \n\t" \ + "preceu.ph.qbl %[" #O7 "], %[" #I3 "] \n\t" + +// temp0[31..16 | 15..0] = temp0[31..16 | 15..0] + temp8[31..16 | 15..0] +// temp0[31..16 | 15..0] = temp0[31..16 <<(s) 7 | 15..0 <<(s) 7] +// temp1..temp7 same as temp0 +// precrqu_s.qb.ph temp0, temp1, temp0: +// temp0 = temp1[31..24] | temp1[15..8] | temp0[31..24] | temp0[15..8] +// store temp0 to dst +// IO - input/output +// I - input (macro doesn't change it) +#define STORE_SAT_SUM_X2(IO0, IO1, IO2, IO3, IO4, IO5, IO6, IO7, \ + I0, I1, I2, I3, I4, I5, I6, I7, \ + I8, I9, I10, I11, I12, I13) \ + "addq.ph %[" #IO0 "], %[" #IO0 "], %[" #I0 "] \n\t" \ + "addq.ph %[" #IO1 "], %[" #IO1 "], %[" #I1 "] \n\t" \ + "addq.ph %[" #IO2 "], %[" #IO2 "], %[" #I2 "] \n\t" \ + "addq.ph %[" #IO3 "], %[" #IO3 "], %[" #I3 "] \n\t" \ + "addq.ph %[" #IO4 "], %[" #IO4 "], %[" #I4 "] \n\t" \ + "addq.ph %[" #IO5 "], %[" #IO5 "], %[" #I5 "] \n\t" \ + "addq.ph %[" #IO6 "], %[" #IO6 "], %[" #I6 "] \n\t" \ + "addq.ph %[" #IO7 "], %[" #IO7 "], %[" #I7 "] \n\t" \ + "shll_s.ph %[" #IO0 "], %[" #IO0 "], 7 \n\t" \ + "shll_s.ph %[" #IO1 "], %[" #IO1 "], 7 \n\t" \ + "shll_s.ph %[" #IO2 "], %[" #IO2 "], 7 \n\t" \ + "shll_s.ph %[" #IO3 "], %[" #IO3 "], 7 \n\t" \ + "shll_s.ph %[" #IO4 "], %[" #IO4 "], 7 \n\t" \ + "shll_s.ph %[" #IO5 "], %[" #IO5 "], 7 \n\t" \ + "shll_s.ph %[" #IO6 "], %[" #IO6 "], 7 \n\t" \ + "shll_s.ph %[" #IO7 "], %[" #IO7 "], 7 \n\t" \ + "precrqu_s.qb.ph %[" #IO0 "], %[" #IO1 "], %[" #IO0 "] \n\t" \ + "precrqu_s.qb.ph %[" #IO2 "], %[" #IO3 "], %[" #IO2 "] \n\t" \ + "precrqu_s.qb.ph %[" #IO4 "], %[" #IO5 "], %[" #IO4 "] \n\t" \ + "precrqu_s.qb.ph %[" #IO6 "], %[" #IO7 "], %[" #IO6 "] \n\t" \ + "usw %[" #IO0 "], " XSTR(I13) "*" #I9 "(%[" #I8 "]) \n\t" \ + "usw %[" #IO2 "], " XSTR(I13) "*" #I10 "(%[" #I8 "]) \n\t" \ + "usw %[" #IO4 "], " XSTR(I13) "*" #I11 "(%[" #I8 "]) \n\t" \ + "usw %[" #IO6 "], " XSTR(I13) "*" #I12 "(%[" #I8 "]) \n\t" + +#define OUTPUT_EARLY_CLOBBER_REGS_10() \ + : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), \ + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [temp6]"=&r"(temp6), \ + [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), [temp9]"=&r"(temp9), \ + [temp10]"=&r"(temp10) + +#define OUTPUT_EARLY_CLOBBER_REGS_18() \ + OUTPUT_EARLY_CLOBBER_REGS_10(), \ + [temp11]"=&r"(temp11), [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), \ + [temp14]"=&r"(temp14), [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), \ + [temp17]"=&r"(temp17), [temp18]"=&r"(temp18) + +#endif // WEBP_DSP_MIPS_MACRO_H_ diff --git a/third-party/webp/libwebp/src/dsp/msa_macro.h b/third-party/webp/libwebp/src/dsp/msa_macro.h new file mode 100644 index 0000000000..90adbbc319 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/msa_macro.h @@ -0,0 +1,1395 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MSA common macros +// +// Author(s): Prashant Patil (prashant.patil@imgtec.com) + +#ifndef WEBP_DSP_MSA_MACRO_H_ +#define WEBP_DSP_MSA_MACRO_H_ + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MSA) + +#include +#include + +#if defined(__clang__) + #define CLANG_BUILD +#endif + +#ifdef CLANG_BUILD + #define ALPHAVAL (-1) + #define ADDVI_H(a, b) __msa_addvi_h((v8i16)a, b) + #define ADDVI_W(a, b) __msa_addvi_w((v4i32)a, b) + #define SRAI_B(a, b) __msa_srai_b((v16i8)a, b) + #define SRAI_H(a, b) __msa_srai_h((v8i16)a, b) + #define SRAI_W(a, b) __msa_srai_w((v4i32)a, b) + #define SRLI_H(a, b) __msa_srli_h((v8i16)a, b) + #define SLLI_B(a, b) __msa_slli_b((v4i32)a, b) + #define ANDI_B(a, b) __msa_andi_b((v16u8)a, b) + #define ORI_B(a, b) __msa_ori_b((v16u8)a, b) +#else + #define ALPHAVAL (0xff) + #define ADDVI_H(a, b) (a + b) + #define ADDVI_W(a, b) (a + b) + #define SRAI_B(a, b) (a >> b) + #define SRAI_H(a, b) (a >> b) + #define SRAI_W(a, b) (a >> b) + #define SRLI_H(a, b) (a << b) + #define SLLI_B(a, b) (a << b) + #define ANDI_B(a, b) (a & b) + #define ORI_B(a, b) (a | b) +#endif + +#define LD_B(RTYPE, psrc) *((RTYPE*)(psrc)) +#define LD_UB(...) LD_B(v16u8, __VA_ARGS__) +#define LD_SB(...) LD_B(v16i8, __VA_ARGS__) + +#define LD_H(RTYPE, psrc) *((RTYPE*)(psrc)) +#define LD_UH(...) LD_H(v8u16, __VA_ARGS__) +#define LD_SH(...) LD_H(v8i16, __VA_ARGS__) + +#define LD_W(RTYPE, psrc) *((RTYPE*)(psrc)) +#define LD_UW(...) LD_W(v4u32, __VA_ARGS__) +#define LD_SW(...) LD_W(v4i32, __VA_ARGS__) + +#define ST_B(RTYPE, in, pdst) *((RTYPE*)(pdst)) = in +#define ST_UB(...) ST_B(v16u8, __VA_ARGS__) +#define ST_SB(...) ST_B(v16i8, __VA_ARGS__) + +#define ST_H(RTYPE, in, pdst) *((RTYPE*)(pdst)) = in +#define ST_UH(...) ST_H(v8u16, __VA_ARGS__) +#define ST_SH(...) ST_H(v8i16, __VA_ARGS__) + +#define ST_W(RTYPE, in, pdst) *((RTYPE*)(pdst)) = in +#define ST_UW(...) ST_W(v4u32, __VA_ARGS__) +#define ST_SW(...) ST_W(v4i32, __VA_ARGS__) + +#define MSA_LOAD_FUNC(TYPE, INSTR, FUNC_NAME) \ + static inline TYPE FUNC_NAME(const void* const psrc) { \ + const uint8_t* const psrc_m = (const uint8_t*)psrc; \ + TYPE val_m; \ + __asm__ volatile("" #INSTR " %[val_m], %[psrc_m] \n\t" \ + : [val_m] "=r"(val_m) \ + : [psrc_m] "m"(*psrc_m)); \ + return val_m; \ + } + +#define MSA_LOAD(psrc, FUNC_NAME) FUNC_NAME(psrc) + +#define MSA_STORE_FUNC(TYPE, INSTR, FUNC_NAME) \ + static inline void FUNC_NAME(TYPE val, void* const pdst) { \ + uint8_t* const pdst_m = (uint8_t*)pdst; \ + TYPE val_m = val; \ + __asm__ volatile(" " #INSTR " %[val_m], %[pdst_m] \n\t" \ + : [pdst_m] "=m"(*pdst_m) \ + : [val_m] "r"(val_m)); \ + } + +#define MSA_STORE(val, pdst, FUNC_NAME) FUNC_NAME(val, pdst) + +#if (__mips_isa_rev >= 6) + MSA_LOAD_FUNC(uint16_t, lh, msa_lh); + #define LH(psrc) MSA_LOAD(psrc, msa_lh) + MSA_LOAD_FUNC(uint32_t, lw, msa_lw); + #define LW(psrc) MSA_LOAD(psrc, msa_lw) + #if (__mips == 64) + MSA_LOAD_FUNC(uint64_t, ld, msa_ld); + #define LD(psrc) MSA_LOAD(psrc, msa_ld) + #else // !(__mips == 64) + #define LD(psrc) ((((uint64_t)MSA_LOAD(psrc + 4, msa_lw)) << 32) | \ + MSA_LOAD(psrc, msa_lw)) + #endif // (__mips == 64) + + MSA_STORE_FUNC(uint16_t, sh, msa_sh); + #define SH(val, pdst) MSA_STORE(val, pdst, msa_sh) + MSA_STORE_FUNC(uint32_t, sw, msa_sw); + #define SW(val, pdst) MSA_STORE(val, pdst, msa_sw) + MSA_STORE_FUNC(uint64_t, sd, msa_sd); + #define SD(val, pdst) MSA_STORE(val, pdst, msa_sd) +#else // !(__mips_isa_rev >= 6) + MSA_LOAD_FUNC(uint16_t, ulh, msa_ulh); + #define LH(psrc) MSA_LOAD(psrc, msa_ulh) + MSA_LOAD_FUNC(uint32_t, ulw, msa_ulw); + #define LW(psrc) MSA_LOAD(psrc, msa_ulw) + #if (__mips == 64) + MSA_LOAD_FUNC(uint64_t, uld, msa_uld); + #define LD(psrc) MSA_LOAD(psrc, msa_uld) + #else // !(__mips == 64) + #define LD(psrc) ((((uint64_t)MSA_LOAD(psrc + 4, msa_ulw)) << 32) | \ + MSA_LOAD(psrc, msa_ulw)) + #endif // (__mips == 64) + + MSA_STORE_FUNC(uint16_t, ush, msa_ush); + #define SH(val, pdst) MSA_STORE(val, pdst, msa_ush) + MSA_STORE_FUNC(uint32_t, usw, msa_usw); + #define SW(val, pdst) MSA_STORE(val, pdst, msa_usw) + #define SD(val, pdst) do { \ + uint8_t* const pdst_sd_m = (uint8_t*)(pdst); \ + const uint32_t val0_m = (uint32_t)(val & 0x00000000FFFFFFFF); \ + const uint32_t val1_m = (uint32_t)((val >> 32) & 0x00000000FFFFFFFF); \ + SW(val0_m, pdst_sd_m); \ + SW(val1_m, pdst_sd_m + 4); \ + } while (0) +#endif // (__mips_isa_rev >= 6) + +/* Description : Load 4 words with stride + * Arguments : Inputs - psrc, stride + * Outputs - out0, out1, out2, out3 + * Details : Load word in 'out0' from (psrc) + * Load word in 'out1' from (psrc + stride) + * Load word in 'out2' from (psrc + 2 * stride) + * Load word in 'out3' from (psrc + 3 * stride) + */ +#define LW4(psrc, stride, out0, out1, out2, out3) do { \ + const uint8_t* ptmp = (const uint8_t*)psrc; \ + out0 = LW(ptmp); \ + ptmp += stride; \ + out1 = LW(ptmp); \ + ptmp += stride; \ + out2 = LW(ptmp); \ + ptmp += stride; \ + out3 = LW(ptmp); \ +} while (0) + +/* Description : Store words with stride + * Arguments : Inputs - in0, in1, in2, in3, pdst, stride + * Details : Store word from 'in0' to (pdst) + * Store word from 'in1' to (pdst + stride) + * Store word from 'in2' to (pdst + 2 * stride) + * Store word from 'in3' to (pdst + 3 * stride) + */ +#define SW4(in0, in1, in2, in3, pdst, stride) do { \ + uint8_t* ptmp = (uint8_t*)pdst; \ + SW(in0, ptmp); \ + ptmp += stride; \ + SW(in1, ptmp); \ + ptmp += stride; \ + SW(in2, ptmp); \ + ptmp += stride; \ + SW(in3, ptmp); \ +} while (0) + +#define SW3(in0, in1, in2, pdst, stride) do { \ + uint8_t* ptmp = (uint8_t*)pdst; \ + SW(in0, ptmp); \ + ptmp += stride; \ + SW(in1, ptmp); \ + ptmp += stride; \ + SW(in2, ptmp); \ +} while (0) + +#define SW2(in0, in1, pdst, stride) do { \ + uint8_t* ptmp = (uint8_t*)pdst; \ + SW(in0, ptmp); \ + ptmp += stride; \ + SW(in1, ptmp); \ +} while (0) + +/* Description : Store 4 double words with stride + * Arguments : Inputs - in0, in1, in2, in3, pdst, stride + * Details : Store double word from 'in0' to (pdst) + * Store double word from 'in1' to (pdst + stride) + * Store double word from 'in2' to (pdst + 2 * stride) + * Store double word from 'in3' to (pdst + 3 * stride) + */ +#define SD4(in0, in1, in2, in3, pdst, stride) do { \ + uint8_t* ptmp = (uint8_t*)pdst; \ + SD(in0, ptmp); \ + ptmp += stride; \ + SD(in1, ptmp); \ + ptmp += stride; \ + SD(in2, ptmp); \ + ptmp += stride; \ + SD(in3, ptmp); \ +} while (0) + +/* Description : Load vectors with 16 byte elements with stride + * Arguments : Inputs - psrc, stride + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Load 16 byte elements in 'out0' from (psrc) + * Load 16 byte elements in 'out1' from (psrc + stride) + */ +#define LD_B2(RTYPE, psrc, stride, out0, out1) do { \ + out0 = LD_B(RTYPE, psrc); \ + out1 = LD_B(RTYPE, psrc + stride); \ +} while (0) +#define LD_UB2(...) LD_B2(v16u8, __VA_ARGS__) +#define LD_SB2(...) LD_B2(v16i8, __VA_ARGS__) + +#define LD_B3(RTYPE, psrc, stride, out0, out1, out2) do { \ + LD_B2(RTYPE, psrc, stride, out0, out1); \ + out2 = LD_B(RTYPE, psrc + 2 * stride); \ +} while (0) +#define LD_UB3(...) LD_B3(v16u8, __VA_ARGS__) +#define LD_SB3(...) LD_B3(v16i8, __VA_ARGS__) + +#define LD_B4(RTYPE, psrc, stride, out0, out1, out2, out3) do { \ + LD_B2(RTYPE, psrc, stride, out0, out1); \ + LD_B2(RTYPE, psrc + 2 * stride , stride, out2, out3); \ +} while (0) +#define LD_UB4(...) LD_B4(v16u8, __VA_ARGS__) +#define LD_SB4(...) LD_B4(v16i8, __VA_ARGS__) + +#define LD_B8(RTYPE, psrc, stride, \ + out0, out1, out2, out3, out4, out5, out6, out7) do { \ + LD_B4(RTYPE, psrc, stride, out0, out1, out2, out3); \ + LD_B4(RTYPE, psrc + 4 * stride, stride, out4, out5, out6, out7); \ +} while (0) +#define LD_UB8(...) LD_B8(v16u8, __VA_ARGS__) +#define LD_SB8(...) LD_B8(v16i8, __VA_ARGS__) + +/* Description : Load vectors with 8 halfword elements with stride + * Arguments : Inputs - psrc, stride + * Outputs - out0, out1 + * Details : Load 8 halfword elements in 'out0' from (psrc) + * Load 8 halfword elements in 'out1' from (psrc + stride) + */ +#define LD_H2(RTYPE, psrc, stride, out0, out1) do { \ + out0 = LD_H(RTYPE, psrc); \ + out1 = LD_H(RTYPE, psrc + stride); \ +} while (0) +#define LD_UH2(...) LD_H2(v8u16, __VA_ARGS__) +#define LD_SH2(...) LD_H2(v8i16, __VA_ARGS__) + +/* Description : Load vectors with 4 word elements with stride + * Arguments : Inputs - psrc, stride + * Outputs - out0, out1, out2, out3 + * Details : Load 4 word elements in 'out0' from (psrc + 0 * stride) + * Load 4 word elements in 'out1' from (psrc + 1 * stride) + * Load 4 word elements in 'out2' from (psrc + 2 * stride) + * Load 4 word elements in 'out3' from (psrc + 3 * stride) + */ +#define LD_W2(RTYPE, psrc, stride, out0, out1) do { \ + out0 = LD_W(RTYPE, psrc); \ + out1 = LD_W(RTYPE, psrc + stride); \ +} while (0) +#define LD_UW2(...) LD_W2(v4u32, __VA_ARGS__) +#define LD_SW2(...) LD_W2(v4i32, __VA_ARGS__) + +#define LD_W3(RTYPE, psrc, stride, out0, out1, out2) do { \ + LD_W2(RTYPE, psrc, stride, out0, out1); \ + out2 = LD_W(RTYPE, psrc + 2 * stride); \ +} while (0) +#define LD_UW3(...) LD_W3(v4u32, __VA_ARGS__) +#define LD_SW3(...) LD_W3(v4i32, __VA_ARGS__) + +#define LD_W4(RTYPE, psrc, stride, out0, out1, out2, out3) do { \ + LD_W2(RTYPE, psrc, stride, out0, out1); \ + LD_W2(RTYPE, psrc + 2 * stride, stride, out2, out3); \ +} while (0) +#define LD_UW4(...) LD_W4(v4u32, __VA_ARGS__) +#define LD_SW4(...) LD_W4(v4i32, __VA_ARGS__) + +/* Description : Store vectors of 16 byte elements with stride + * Arguments : Inputs - in0, in1, pdst, stride + * Details : Store 16 byte elements from 'in0' to (pdst) + * Store 16 byte elements from 'in1' to (pdst + stride) + */ +#define ST_B2(RTYPE, in0, in1, pdst, stride) do { \ + ST_B(RTYPE, in0, pdst); \ + ST_B(RTYPE, in1, pdst + stride); \ +} while (0) +#define ST_UB2(...) ST_B2(v16u8, __VA_ARGS__) +#define ST_SB2(...) ST_B2(v16i8, __VA_ARGS__) + +#define ST_B4(RTYPE, in0, in1, in2, in3, pdst, stride) do { \ + ST_B2(RTYPE, in0, in1, pdst, stride); \ + ST_B2(RTYPE, in2, in3, pdst + 2 * stride, stride); \ +} while (0) +#define ST_UB4(...) ST_B4(v16u8, __VA_ARGS__) +#define ST_SB4(...) ST_B4(v16i8, __VA_ARGS__) + +#define ST_B8(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7, \ + pdst, stride) do { \ + ST_B4(RTYPE, in0, in1, in2, in3, pdst, stride); \ + ST_B4(RTYPE, in4, in5, in6, in7, pdst + 4 * stride, stride); \ +} while (0) +#define ST_UB8(...) ST_B8(v16u8, __VA_ARGS__) + +/* Description : Store vectors of 4 word elements with stride + * Arguments : Inputs - in0, in1, in2, in3, pdst, stride + * Details : Store 4 word elements from 'in0' to (pdst + 0 * stride) + * Store 4 word elements from 'in1' to (pdst + 1 * stride) + * Store 4 word elements from 'in2' to (pdst + 2 * stride) + * Store 4 word elements from 'in3' to (pdst + 3 * stride) + */ +#define ST_W2(RTYPE, in0, in1, pdst, stride) do { \ + ST_W(RTYPE, in0, pdst); \ + ST_W(RTYPE, in1, pdst + stride); \ +} while (0) +#define ST_UW2(...) ST_W2(v4u32, __VA_ARGS__) +#define ST_SW2(...) ST_W2(v4i32, __VA_ARGS__) + +#define ST_W3(RTYPE, in0, in1, in2, pdst, stride) do { \ + ST_W2(RTYPE, in0, in1, pdst, stride); \ + ST_W(RTYPE, in2, pdst + 2 * stride); \ +} while (0) +#define ST_UW3(...) ST_W3(v4u32, __VA_ARGS__) +#define ST_SW3(...) ST_W3(v4i32, __VA_ARGS__) + +#define ST_W4(RTYPE, in0, in1, in2, in3, pdst, stride) do { \ + ST_W2(RTYPE, in0, in1, pdst, stride); \ + ST_W2(RTYPE, in2, in3, pdst + 2 * stride, stride); \ +} while (0) +#define ST_UW4(...) ST_W4(v4u32, __VA_ARGS__) +#define ST_SW4(...) ST_W4(v4i32, __VA_ARGS__) + +/* Description : Store vectors of 8 halfword elements with stride + * Arguments : Inputs - in0, in1, pdst, stride + * Details : Store 8 halfword elements from 'in0' to (pdst) + * Store 8 halfword elements from 'in1' to (pdst + stride) + */ +#define ST_H2(RTYPE, in0, in1, pdst, stride) do { \ + ST_H(RTYPE, in0, pdst); \ + ST_H(RTYPE, in1, pdst + stride); \ +} while (0) +#define ST_UH2(...) ST_H2(v8u16, __VA_ARGS__) +#define ST_SH2(...) ST_H2(v8i16, __VA_ARGS__) + +/* Description : Store 2x4 byte block to destination memory from input vector + * Arguments : Inputs - in, stidx, pdst, stride + * Details : Index 'stidx' halfword element from 'in' vector is copied to + * the GP register and stored to (pdst) + * Index 'stidx+1' halfword element from 'in' vector is copied to + * the GP register and stored to (pdst + stride) + * Index 'stidx+2' halfword element from 'in' vector is copied to + * the GP register and stored to (pdst + 2 * stride) + * Index 'stidx+3' halfword element from 'in' vector is copied to + * the GP register and stored to (pdst + 3 * stride) + */ +#define ST2x4_UB(in, stidx, pdst, stride) do { \ + uint8_t* pblk_2x4_m = (uint8_t*)pdst; \ + const uint16_t out0_m = __msa_copy_s_h((v8i16)in, stidx); \ + const uint16_t out1_m = __msa_copy_s_h((v8i16)in, stidx + 1); \ + const uint16_t out2_m = __msa_copy_s_h((v8i16)in, stidx + 2); \ + const uint16_t out3_m = __msa_copy_s_h((v8i16)in, stidx + 3); \ + SH(out0_m, pblk_2x4_m); \ + pblk_2x4_m += stride; \ + SH(out1_m, pblk_2x4_m); \ + pblk_2x4_m += stride; \ + SH(out2_m, pblk_2x4_m); \ + pblk_2x4_m += stride; \ + SH(out3_m, pblk_2x4_m); \ +} while (0) + +/* Description : Store 4x4 byte block to destination memory from input vector + * Arguments : Inputs - in0, in1, pdst, stride + * Details : 'Idx0' word element from input vector 'in0' is copied to the + * GP register and stored to (pdst) + * 'Idx1' word element from input vector 'in0' is copied to the + * GP register and stored to (pdst + stride) + * 'Idx2' word element from input vector 'in0' is copied to the + * GP register and stored to (pdst + 2 * stride) + * 'Idx3' word element from input vector 'in0' is copied to the + * GP register and stored to (pdst + 3 * stride) + */ +#define ST4x4_UB(in0, in1, idx0, idx1, idx2, idx3, pdst, stride) do { \ + uint8_t* const pblk_4x4_m = (uint8_t*)pdst; \ + const uint32_t out0_m = __msa_copy_s_w((v4i32)in0, idx0); \ + const uint32_t out1_m = __msa_copy_s_w((v4i32)in0, idx1); \ + const uint32_t out2_m = __msa_copy_s_w((v4i32)in1, idx2); \ + const uint32_t out3_m = __msa_copy_s_w((v4i32)in1, idx3); \ + SW4(out0_m, out1_m, out2_m, out3_m, pblk_4x4_m, stride); \ +} while (0) + +#define ST4x8_UB(in0, in1, pdst, stride) do { \ + uint8_t* const pblk_4x8 = (uint8_t*)pdst; \ + ST4x4_UB(in0, in0, 0, 1, 2, 3, pblk_4x8, stride); \ + ST4x4_UB(in1, in1, 0, 1, 2, 3, pblk_4x8 + 4 * stride, stride); \ +} while (0) + +/* Description : Immediate number of elements to slide + * Arguments : Inputs - in0, in1, slide_val + * Outputs - out + * Return Type - as per RTYPE + * Details : Byte elements from 'in1' vector are slid into 'in0' by + * value specified in the 'slide_val' + */ +#define SLDI_B(RTYPE, in0, in1, slide_val) \ + (RTYPE)__msa_sldi_b((v16i8)in0, (v16i8)in1, slide_val) \ + +#define SLDI_UB(...) SLDI_B(v16u8, __VA_ARGS__) +#define SLDI_SB(...) SLDI_B(v16i8, __VA_ARGS__) +#define SLDI_SH(...) SLDI_B(v8i16, __VA_ARGS__) + +/* Description : Shuffle byte vector elements as per mask vector + * Arguments : Inputs - in0, in1, in2, in3, mask0, mask1 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Byte elements from 'in0' & 'in1' are copied selectively to + * 'out0' as per control vector 'mask0' + */ +#define VSHF_B(RTYPE, in0, in1, mask) \ + (RTYPE)__msa_vshf_b((v16i8)mask, (v16i8)in1, (v16i8)in0) + +#define VSHF_UB(...) VSHF_B(v16u8, __VA_ARGS__) +#define VSHF_SB(...) VSHF_B(v16i8, __VA_ARGS__) +#define VSHF_UH(...) VSHF_B(v8u16, __VA_ARGS__) +#define VSHF_SH(...) VSHF_B(v8i16, __VA_ARGS__) + +#define VSHF_B2(RTYPE, in0, in1, in2, in3, mask0, mask1, out0, out1) do { \ + out0 = VSHF_B(RTYPE, in0, in1, mask0); \ + out1 = VSHF_B(RTYPE, in2, in3, mask1); \ +} while (0) +#define VSHF_B2_UB(...) VSHF_B2(v16u8, __VA_ARGS__) +#define VSHF_B2_SB(...) VSHF_B2(v16i8, __VA_ARGS__) +#define VSHF_B2_UH(...) VSHF_B2(v8u16, __VA_ARGS__) +#define VSHF_B2_SH(...) VSHF_B2(v8i16, __VA_ARGS__) + +/* Description : Shuffle halfword vector elements as per mask vector + * Arguments : Inputs - in0, in1, in2, in3, mask0, mask1 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : halfword elements from 'in0' & 'in1' are copied selectively to + * 'out0' as per control vector 'mask0' + */ +#define VSHF_H2(RTYPE, in0, in1, in2, in3, mask0, mask1, out0, out1) do { \ + out0 = (RTYPE)__msa_vshf_h((v8i16)mask0, (v8i16)in1, (v8i16)in0); \ + out1 = (RTYPE)__msa_vshf_h((v8i16)mask1, (v8i16)in3, (v8i16)in2); \ +} while (0) +#define VSHF_H2_UH(...) VSHF_H2(v8u16, __VA_ARGS__) +#define VSHF_H2_SH(...) VSHF_H2(v8i16, __VA_ARGS__) + +/* Description : Dot product of byte vector elements + * Arguments : Inputs - mult0, mult1, cnst0, cnst1 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Signed byte elements from 'mult0' are multiplied with + * signed byte elements from 'cnst0' producing a result + * twice the size of input i.e. signed halfword. + * The multiplication result of adjacent odd-even elements + * are added together and written to the 'out0' vector +*/ +#define DOTP_SB2(RTYPE, mult0, mult1, cnst0, cnst1, out0, out1) do { \ + out0 = (RTYPE)__msa_dotp_s_h((v16i8)mult0, (v16i8)cnst0); \ + out1 = (RTYPE)__msa_dotp_s_h((v16i8)mult1, (v16i8)cnst1); \ +} while (0) +#define DOTP_SB2_SH(...) DOTP_SB2(v8i16, __VA_ARGS__) + +/* Description : Dot product of halfword vector elements + * Arguments : Inputs - mult0, mult1, cnst0, cnst1 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Signed halfword elements from 'mult0' are multiplied with + * signed halfword elements from 'cnst0' producing a result + * twice the size of input i.e. signed word. + * The multiplication result of adjacent odd-even elements + * are added together and written to the 'out0' vector + */ +#define DOTP_SH2(RTYPE, mult0, mult1, cnst0, cnst1, out0, out1) do { \ + out0 = (RTYPE)__msa_dotp_s_w((v8i16)mult0, (v8i16)cnst0); \ + out1 = (RTYPE)__msa_dotp_s_w((v8i16)mult1, (v8i16)cnst1); \ +} while (0) +#define DOTP_SH2_SW(...) DOTP_SH2(v4i32, __VA_ARGS__) + +/* Description : Dot product of unsigned word vector elements + * Arguments : Inputs - mult0, mult1, cnst0, cnst1 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Unsigned word elements from 'mult0' are multiplied with + * unsigned word elements from 'cnst0' producing a result + * twice the size of input i.e. unsigned double word. + * The multiplication result of adjacent odd-even elements + * are added together and written to the 'out0' vector + */ +#define DOTP_UW2(RTYPE, mult0, mult1, cnst0, cnst1, out0, out1) do { \ + out0 = (RTYPE)__msa_dotp_u_d((v4u32)mult0, (v4u32)cnst0); \ + out1 = (RTYPE)__msa_dotp_u_d((v4u32)mult1, (v4u32)cnst1); \ +} while (0) +#define DOTP_UW2_UD(...) DOTP_UW2(v2u64, __VA_ARGS__) + +/* Description : Dot product & addition of halfword vector elements + * Arguments : Inputs - mult0, mult1, cnst0, cnst1 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Signed halfword elements from 'mult0' are multiplied with + * signed halfword elements from 'cnst0' producing a result + * twice the size of input i.e. signed word. + * The multiplication result of adjacent odd-even elements + * are added to the 'out0' vector + */ +#define DPADD_SH2(RTYPE, mult0, mult1, cnst0, cnst1, out0, out1) do { \ + out0 = (RTYPE)__msa_dpadd_s_w((v4i32)out0, (v8i16)mult0, (v8i16)cnst0); \ + out1 = (RTYPE)__msa_dpadd_s_w((v4i32)out1, (v8i16)mult1, (v8i16)cnst1); \ +} while (0) +#define DPADD_SH2_SW(...) DPADD_SH2(v4i32, __VA_ARGS__) + +/* Description : Clips all signed halfword elements of input vector + * between 0 & 255 + * Arguments : Input/output - val + * Return Type - signed halfword + */ +#define CLIP_SH_0_255(val) do { \ + const v8i16 max_m = __msa_ldi_h(255); \ + val = __msa_maxi_s_h((v8i16)val, 0); \ + val = __msa_min_s_h(max_m, (v8i16)val); \ +} while (0) + +#define CLIP_SH2_0_255(in0, in1) do { \ + CLIP_SH_0_255(in0); \ + CLIP_SH_0_255(in1); \ +} while (0) + +#define CLIP_SH4_0_255(in0, in1, in2, in3) do { \ + CLIP_SH2_0_255(in0, in1); \ + CLIP_SH2_0_255(in2, in3); \ +} while (0) + +/* Description : Clips all unsigned halfword elements of input vector + * between 0 & 255 + * Arguments : Input - in + * Output - out_m + * Return Type - unsigned halfword + */ +#define CLIP_UH_0_255(in) do { \ + const v8u16 max_m = (v8u16)__msa_ldi_h(255); \ + in = __msa_maxi_u_h((v8u16) in, 0); \ + in = __msa_min_u_h((v8u16) max_m, (v8u16) in); \ +} while (0) + +#define CLIP_UH2_0_255(in0, in1) do { \ + CLIP_UH_0_255(in0); \ + CLIP_UH_0_255(in1); \ +} while (0) + +/* Description : Clips all signed word elements of input vector + * between 0 & 255 + * Arguments : Input/output - val + * Return Type - signed word + */ +#define CLIP_SW_0_255(val) do { \ + const v4i32 max_m = __msa_ldi_w(255); \ + val = __msa_maxi_s_w((v4i32)val, 0); \ + val = __msa_min_s_w(max_m, (v4i32)val); \ +} while (0) + +#define CLIP_SW4_0_255(in0, in1, in2, in3) do { \ + CLIP_SW_0_255(in0); \ + CLIP_SW_0_255(in1); \ + CLIP_SW_0_255(in2); \ + CLIP_SW_0_255(in3); \ +} while (0) + +/* Description : Horizontal addition of 4 signed word elements of input vector + * Arguments : Input - in (signed word vector) + * Output - sum_m (i32 sum) + * Return Type - signed word (GP) + * Details : 4 signed word elements of 'in' vector are added together and + * the resulting integer sum is returned + */ +static WEBP_INLINE int32_t func_hadd_sw_s32(v4i32 in) { + const v2i64 res0_m = __msa_hadd_s_d((v4i32)in, (v4i32)in); + const v2i64 res1_m = __msa_splati_d(res0_m, 1); + const v2i64 out = res0_m + res1_m; + int32_t sum_m = __msa_copy_s_w((v4i32)out, 0); + return sum_m; +} +#define HADD_SW_S32(in) func_hadd_sw_s32(in) + +/* Description : Horizontal addition of 8 signed halfword elements + * Arguments : Input - in (signed halfword vector) + * Output - sum_m (s32 sum) + * Return Type - signed word + * Details : 8 signed halfword elements of input vector are added + * together and the resulting integer sum is returned + */ +static WEBP_INLINE int32_t func_hadd_sh_s32(v8i16 in) { + const v4i32 res = __msa_hadd_s_w(in, in); + const v2i64 res0 = __msa_hadd_s_d(res, res); + const v2i64 res1 = __msa_splati_d(res0, 1); + const v2i64 res2 = res0 + res1; + const int32_t sum_m = __msa_copy_s_w((v4i32)res2, 0); + return sum_m; +} +#define HADD_SH_S32(in) func_hadd_sh_s32(in) + +/* Description : Horizontal addition of 8 unsigned halfword elements + * Arguments : Input - in (unsigned halfword vector) + * Output - sum_m (u32 sum) + * Return Type - unsigned word + * Details : 8 unsigned halfword elements of input vector are added + * together and the resulting integer sum is returned + */ +static WEBP_INLINE uint32_t func_hadd_uh_u32(v8u16 in) { + uint32_t sum_m; + const v4u32 res_m = __msa_hadd_u_w(in, in); + v2u64 res0_m = __msa_hadd_u_d(res_m, res_m); + v2u64 res1_m = (v2u64)__msa_splati_d((v2i64)res0_m, 1); + res0_m = res0_m + res1_m; + sum_m = __msa_copy_s_w((v4i32)res0_m, 0); + return sum_m; +} +#define HADD_UH_U32(in) func_hadd_uh_u32(in) + +/* Description : Horizontal addition of signed half word vector elements + Arguments : Inputs - in0, in1 + Outputs - out0, out1 + Return Type - as per RTYPE + Details : Each signed odd half word element from 'in0' is added to + even signed half word element from 'in0' (pairwise) and the + halfword result is written in 'out0' +*/ +#define HADD_SH2(RTYPE, in0, in1, out0, out1) do { \ + out0 = (RTYPE)__msa_hadd_s_w((v8i16)in0, (v8i16)in0); \ + out1 = (RTYPE)__msa_hadd_s_w((v8i16)in1, (v8i16)in1); \ +} while (0) +#define HADD_SH2_SW(...) HADD_SH2(v4i32, __VA_ARGS__) + +#define HADD_SH4(RTYPE, in0, in1, in2, in3, out0, out1, out2, out3) do { \ + HADD_SH2(RTYPE, in0, in1, out0, out1); \ + HADD_SH2(RTYPE, in2, in3, out2, out3); \ +} while (0) +#define HADD_SH4_SW(...) HADD_SH4(v4i32, __VA_ARGS__) + +/* Description : Horizontal subtraction of unsigned byte vector elements + * Arguments : Inputs - in0, in1 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Each unsigned odd byte element from 'in0' is subtracted from + * even unsigned byte element from 'in0' (pairwise) and the + * halfword result is written to 'out0' + */ +#define HSUB_UB2(RTYPE, in0, in1, out0, out1) do { \ + out0 = (RTYPE)__msa_hsub_u_h((v16u8)in0, (v16u8)in0); \ + out1 = (RTYPE)__msa_hsub_u_h((v16u8)in1, (v16u8)in1); \ +} while (0) +#define HSUB_UB2_UH(...) HSUB_UB2(v8u16, __VA_ARGS__) +#define HSUB_UB2_SH(...) HSUB_UB2(v8i16, __VA_ARGS__) +#define HSUB_UB2_SW(...) HSUB_UB2(v4i32, __VA_ARGS__) + +/* Description : Set element n input vector to GPR value + * Arguments : Inputs - in0, in1, in2, in3 + * Output - out + * Return Type - as per RTYPE + * Details : Set element 0 in vector 'out' to value specified in 'in0' + */ +#define INSERT_W2(RTYPE, in0, in1, out) do { \ + out = (RTYPE)__msa_insert_w((v4i32)out, 0, in0); \ + out = (RTYPE)__msa_insert_w((v4i32)out, 1, in1); \ +} while (0) +#define INSERT_W2_UB(...) INSERT_W2(v16u8, __VA_ARGS__) +#define INSERT_W2_SB(...) INSERT_W2(v16i8, __VA_ARGS__) + +#define INSERT_W4(RTYPE, in0, in1, in2, in3, out) do { \ + out = (RTYPE)__msa_insert_w((v4i32)out, 0, in0); \ + out = (RTYPE)__msa_insert_w((v4i32)out, 1, in1); \ + out = (RTYPE)__msa_insert_w((v4i32)out, 2, in2); \ + out = (RTYPE)__msa_insert_w((v4i32)out, 3, in3); \ +} while (0) +#define INSERT_W4_UB(...) INSERT_W4(v16u8, __VA_ARGS__) +#define INSERT_W4_SB(...) INSERT_W4(v16i8, __VA_ARGS__) +#define INSERT_W4_SW(...) INSERT_W4(v4i32, __VA_ARGS__) + +/* Description : Set element n of double word input vector to GPR value + * Arguments : Inputs - in0, in1 + * Output - out + * Return Type - as per RTYPE + * Details : Set element 0 in vector 'out' to GPR value specified in 'in0' + * Set element 1 in vector 'out' to GPR value specified in 'in1' + */ +#define INSERT_D2(RTYPE, in0, in1, out) do { \ + out = (RTYPE)__msa_insert_d((v2i64)out, 0, in0); \ + out = (RTYPE)__msa_insert_d((v2i64)out, 1, in1); \ +} while (0) +#define INSERT_D2_UB(...) INSERT_D2(v16u8, __VA_ARGS__) +#define INSERT_D2_SB(...) INSERT_D2(v16i8, __VA_ARGS__) + +/* Description : Interleave even byte elements from vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Even byte elements of 'in0' and 'in1' are interleaved + * and written to 'out0' + */ +#define ILVEV_B2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_ilvev_b((v16i8)in1, (v16i8)in0); \ + out1 = (RTYPE)__msa_ilvev_b((v16i8)in3, (v16i8)in2); \ +} while (0) +#define ILVEV_B2_UB(...) ILVEV_B2(v16u8, __VA_ARGS__) +#define ILVEV_B2_SB(...) ILVEV_B2(v16i8, __VA_ARGS__) +#define ILVEV_B2_UH(...) ILVEV_B2(v8u16, __VA_ARGS__) +#define ILVEV_B2_SH(...) ILVEV_B2(v8i16, __VA_ARGS__) +#define ILVEV_B2_SD(...) ILVEV_B2(v2i64, __VA_ARGS__) + +/* Description : Interleave odd byte elements from vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Odd byte elements of 'in0' and 'in1' are interleaved + * and written to 'out0' + */ +#define ILVOD_B2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_ilvod_b((v16i8)in1, (v16i8)in0); \ + out1 = (RTYPE)__msa_ilvod_b((v16i8)in3, (v16i8)in2); \ +} while (0) +#define ILVOD_B2_UB(...) ILVOD_B2(v16u8, __VA_ARGS__) +#define ILVOD_B2_SB(...) ILVOD_B2(v16i8, __VA_ARGS__) +#define ILVOD_B2_UH(...) ILVOD_B2(v8u16, __VA_ARGS__) +#define ILVOD_B2_SH(...) ILVOD_B2(v8i16, __VA_ARGS__) +#define ILVOD_B2_SD(...) ILVOD_B2(v2i64, __VA_ARGS__) + +/* Description : Interleave even halfword elements from vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Even halfword elements of 'in0' and 'in1' are interleaved + * and written to 'out0' + */ +#define ILVEV_H2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_ilvev_h((v8i16)in1, (v8i16)in0); \ + out1 = (RTYPE)__msa_ilvev_h((v8i16)in3, (v8i16)in2); \ +} while (0) +#define ILVEV_H2_UB(...) ILVEV_H2(v16u8, __VA_ARGS__) +#define ILVEV_H2_UH(...) ILVEV_H2(v8u16, __VA_ARGS__) +#define ILVEV_H2_SH(...) ILVEV_H2(v8i16, __VA_ARGS__) +#define ILVEV_H2_SW(...) ILVEV_H2(v4i32, __VA_ARGS__) + +/* Description : Interleave odd halfword elements from vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Odd halfword elements of 'in0' and 'in1' are interleaved + * and written to 'out0' + */ +#define ILVOD_H2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_ilvod_h((v8i16)in1, (v8i16)in0); \ + out1 = (RTYPE)__msa_ilvod_h((v8i16)in3, (v8i16)in2); \ +} while (0) +#define ILVOD_H2_UB(...) ILVOD_H2(v16u8, __VA_ARGS__) +#define ILVOD_H2_UH(...) ILVOD_H2(v8u16, __VA_ARGS__) +#define ILVOD_H2_SH(...) ILVOD_H2(v8i16, __VA_ARGS__) +#define ILVOD_H2_SW(...) ILVOD_H2(v4i32, __VA_ARGS__) + +/* Description : Interleave even word elements from vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Even word elements of 'in0' and 'in1' are interleaved + * and written to 'out0' + */ +#define ILVEV_W2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_ilvev_w((v4i32)in1, (v4i32)in0); \ + out1 = (RTYPE)__msa_ilvev_w((v4i32)in3, (v4i32)in2); \ +} while (0) +#define ILVEV_W2_UB(...) ILVEV_W2(v16u8, __VA_ARGS__) +#define ILVEV_W2_SB(...) ILVEV_W2(v16i8, __VA_ARGS__) +#define ILVEV_W2_UH(...) ILVEV_W2(v8u16, __VA_ARGS__) +#define ILVEV_W2_SD(...) ILVEV_W2(v2i64, __VA_ARGS__) + +/* Description : Interleave even-odd word elements from vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Even word elements of 'in0' and 'in1' are interleaved + * and written to 'out0' + * Odd word elements of 'in2' and 'in3' are interleaved + * and written to 'out1' + */ +#define ILVEVOD_W2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_ilvev_w((v4i32)in1, (v4i32)in0); \ + out1 = (RTYPE)__msa_ilvod_w((v4i32)in3, (v4i32)in2); \ +} while (0) +#define ILVEVOD_W2_UB(...) ILVEVOD_W2(v16u8, __VA_ARGS__) +#define ILVEVOD_W2_UH(...) ILVEVOD_W2(v8u16, __VA_ARGS__) +#define ILVEVOD_W2_SH(...) ILVEVOD_W2(v8i16, __VA_ARGS__) +#define ILVEVOD_W2_SW(...) ILVEVOD_W2(v4i32, __VA_ARGS__) + +/* Description : Interleave even-odd half-word elements from vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Even half-word elements of 'in0' and 'in1' are interleaved + * and written to 'out0' + * Odd half-word elements of 'in2' and 'in3' are interleaved + * and written to 'out1' + */ +#define ILVEVOD_H2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_ilvev_h((v8i16)in1, (v8i16)in0); \ + out1 = (RTYPE)__msa_ilvod_h((v8i16)in3, (v8i16)in2); \ +} while (0) +#define ILVEVOD_H2_UB(...) ILVEVOD_H2(v16u8, __VA_ARGS__) +#define ILVEVOD_H2_UH(...) ILVEVOD_H2(v8u16, __VA_ARGS__) +#define ILVEVOD_H2_SH(...) ILVEVOD_H2(v8i16, __VA_ARGS__) +#define ILVEVOD_H2_SW(...) ILVEVOD_H2(v4i32, __VA_ARGS__) + +/* Description : Interleave even double word elements from vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Even double word elements of 'in0' and 'in1' are interleaved + * and written to 'out0' + */ +#define ILVEV_D2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_ilvev_d((v2i64)in1, (v2i64)in0); \ + out1 = (RTYPE)__msa_ilvev_d((v2i64)in3, (v2i64)in2); \ +} while (0) +#define ILVEV_D2_UB(...) ILVEV_D2(v16u8, __VA_ARGS__) +#define ILVEV_D2_SB(...) ILVEV_D2(v16i8, __VA_ARGS__) +#define ILVEV_D2_SW(...) ILVEV_D2(v4i32, __VA_ARGS__) +#define ILVEV_D2_SD(...) ILVEV_D2(v2i64, __VA_ARGS__) + +/* Description : Interleave left half of byte elements from vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Left half of byte elements of 'in0' and 'in1' are interleaved + * and written to 'out0'. + */ +#define ILVL_B2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_ilvl_b((v16i8)in0, (v16i8)in1); \ + out1 = (RTYPE)__msa_ilvl_b((v16i8)in2, (v16i8)in3); \ +} while (0) +#define ILVL_B2_UB(...) ILVL_B2(v16u8, __VA_ARGS__) +#define ILVL_B2_SB(...) ILVL_B2(v16i8, __VA_ARGS__) +#define ILVL_B2_UH(...) ILVL_B2(v8u16, __VA_ARGS__) +#define ILVL_B2_SH(...) ILVL_B2(v8i16, __VA_ARGS__) +#define ILVL_B2_SW(...) ILVL_B2(v4i32, __VA_ARGS__) + +/* Description : Interleave right half of byte elements from vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Right half of byte elements of 'in0' and 'in1' are interleaved + * and written to out0. + */ +#define ILVR_B2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_ilvr_b((v16i8)in0, (v16i8)in1); \ + out1 = (RTYPE)__msa_ilvr_b((v16i8)in2, (v16i8)in3); \ +} while (0) +#define ILVR_B2_UB(...) ILVR_B2(v16u8, __VA_ARGS__) +#define ILVR_B2_SB(...) ILVR_B2(v16i8, __VA_ARGS__) +#define ILVR_B2_UH(...) ILVR_B2(v8u16, __VA_ARGS__) +#define ILVR_B2_SH(...) ILVR_B2(v8i16, __VA_ARGS__) +#define ILVR_B2_SW(...) ILVR_B2(v4i32, __VA_ARGS__) + +#define ILVR_B4(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7, \ + out0, out1, out2, out3) do { \ + ILVR_B2(RTYPE, in0, in1, in2, in3, out0, out1); \ + ILVR_B2(RTYPE, in4, in5, in6, in7, out2, out3); \ +} while (0) +#define ILVR_B4_UB(...) ILVR_B4(v16u8, __VA_ARGS__) +#define ILVR_B4_SB(...) ILVR_B4(v16i8, __VA_ARGS__) +#define ILVR_B4_UH(...) ILVR_B4(v8u16, __VA_ARGS__) +#define ILVR_B4_SH(...) ILVR_B4(v8i16, __VA_ARGS__) +#define ILVR_B4_SW(...) ILVR_B4(v4i32, __VA_ARGS__) + +/* Description : Interleave right half of halfword elements from vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Right half of halfword elements of 'in0' and 'in1' are + * interleaved and written to 'out0'. + */ +#define ILVR_H2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_ilvr_h((v8i16)in0, (v8i16)in1); \ + out1 = (RTYPE)__msa_ilvr_h((v8i16)in2, (v8i16)in3); \ +} while (0) +#define ILVR_H2_UB(...) ILVR_H2(v16u8, __VA_ARGS__) +#define ILVR_H2_SH(...) ILVR_H2(v8i16, __VA_ARGS__) +#define ILVR_H2_SW(...) ILVR_H2(v4i32, __VA_ARGS__) + +#define ILVR_H4(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7, \ + out0, out1, out2, out3) do { \ + ILVR_H2(RTYPE, in0, in1, in2, in3, out0, out1); \ + ILVR_H2(RTYPE, in4, in5, in6, in7, out2, out3); \ +} while (0) +#define ILVR_H4_UB(...) ILVR_H4(v16u8, __VA_ARGS__) +#define ILVR_H4_SH(...) ILVR_H4(v8i16, __VA_ARGS__) +#define ILVR_H4_SW(...) ILVR_H4(v4i32, __VA_ARGS__) + +/* Description : Interleave right half of double word elements from vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Right half of double word elements of 'in0' and 'in1' are + * interleaved and written to 'out0'. + */ +#define ILVR_D2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_ilvr_d((v2i64)in0, (v2i64)in1); \ + out1 = (RTYPE)__msa_ilvr_d((v2i64)in2, (v2i64)in3); \ +} while (0) +#define ILVR_D2_UB(...) ILVR_D2(v16u8, __VA_ARGS__) +#define ILVR_D2_SB(...) ILVR_D2(v16i8, __VA_ARGS__) +#define ILVR_D2_SH(...) ILVR_D2(v8i16, __VA_ARGS__) + +#define ILVR_D4(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7, \ + out0, out1, out2, out3) do { \ + ILVR_D2(RTYPE, in0, in1, in2, in3, out0, out1); \ + ILVR_D2(RTYPE, in4, in5, in6, in7, out2, out3); \ +} while (0) +#define ILVR_D4_SB(...) ILVR_D4(v16i8, __VA_ARGS__) +#define ILVR_D4_UB(...) ILVR_D4(v16u8, __VA_ARGS__) + +/* Description : Interleave both left and right half of input vectors + * Arguments : Inputs - in0, in1 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Right half of byte elements from 'in0' and 'in1' are + * interleaved and written to 'out0' + */ +#define ILVRL_B2(RTYPE, in0, in1, out0, out1) do { \ + out0 = (RTYPE)__msa_ilvr_b((v16i8)in0, (v16i8)in1); \ + out1 = (RTYPE)__msa_ilvl_b((v16i8)in0, (v16i8)in1); \ +} while (0) +#define ILVRL_B2_UB(...) ILVRL_B2(v16u8, __VA_ARGS__) +#define ILVRL_B2_SB(...) ILVRL_B2(v16i8, __VA_ARGS__) +#define ILVRL_B2_UH(...) ILVRL_B2(v8u16, __VA_ARGS__) +#define ILVRL_B2_SH(...) ILVRL_B2(v8i16, __VA_ARGS__) +#define ILVRL_B2_SW(...) ILVRL_B2(v4i32, __VA_ARGS__) + +#define ILVRL_H2(RTYPE, in0, in1, out0, out1) do { \ + out0 = (RTYPE)__msa_ilvr_h((v8i16)in0, (v8i16)in1); \ + out1 = (RTYPE)__msa_ilvl_h((v8i16)in0, (v8i16)in1); \ +} while (0) +#define ILVRL_H2_UB(...) ILVRL_H2(v16u8, __VA_ARGS__) +#define ILVRL_H2_SB(...) ILVRL_H2(v16i8, __VA_ARGS__) +#define ILVRL_H2_SH(...) ILVRL_H2(v8i16, __VA_ARGS__) +#define ILVRL_H2_SW(...) ILVRL_H2(v4i32, __VA_ARGS__) +#define ILVRL_H2_UW(...) ILVRL_H2(v4u32, __VA_ARGS__) + +#define ILVRL_W2(RTYPE, in0, in1, out0, out1) do { \ + out0 = (RTYPE)__msa_ilvr_w((v4i32)in0, (v4i32)in1); \ + out1 = (RTYPE)__msa_ilvl_w((v4i32)in0, (v4i32)in1); \ +} while (0) +#define ILVRL_W2_UB(...) ILVRL_W2(v16u8, __VA_ARGS__) +#define ILVRL_W2_SH(...) ILVRL_W2(v8i16, __VA_ARGS__) +#define ILVRL_W2_SW(...) ILVRL_W2(v4i32, __VA_ARGS__) +#define ILVRL_W2_UW(...) ILVRL_W2(v4u32, __VA_ARGS__) + +/* Description : Pack even byte elements of vector pairs + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Even byte elements of 'in0' are copied to the left half of + * 'out0' & even byte elements of 'in1' are copied to the right + * half of 'out0'. + */ +#define PCKEV_B2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_pckev_b((v16i8)in0, (v16i8)in1); \ + out1 = (RTYPE)__msa_pckev_b((v16i8)in2, (v16i8)in3); \ +} while (0) +#define PCKEV_B2_SB(...) PCKEV_B2(v16i8, __VA_ARGS__) +#define PCKEV_B2_UB(...) PCKEV_B2(v16u8, __VA_ARGS__) +#define PCKEV_B2_SH(...) PCKEV_B2(v8i16, __VA_ARGS__) +#define PCKEV_B2_SW(...) PCKEV_B2(v4i32, __VA_ARGS__) + +#define PCKEV_B4(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7, \ + out0, out1, out2, out3) do { \ + PCKEV_B2(RTYPE, in0, in1, in2, in3, out0, out1); \ + PCKEV_B2(RTYPE, in4, in5, in6, in7, out2, out3); \ +} while (0) +#define PCKEV_B4_SB(...) PCKEV_B4(v16i8, __VA_ARGS__) +#define PCKEV_B4_UB(...) PCKEV_B4(v16u8, __VA_ARGS__) +#define PCKEV_B4_SH(...) PCKEV_B4(v8i16, __VA_ARGS__) +#define PCKEV_B4_SW(...) PCKEV_B4(v4i32, __VA_ARGS__) + +/* Description : Pack even halfword elements of vector pairs + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Even halfword elements of 'in0' are copied to the left half of + * 'out0' & even halfword elements of 'in1' are copied to the + * right half of 'out0'. + */ +#define PCKEV_H2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_pckev_h((v8i16)in0, (v8i16)in1); \ + out1 = (RTYPE)__msa_pckev_h((v8i16)in2, (v8i16)in3); \ +} while (0) +#define PCKEV_H2_UH(...) PCKEV_H2(v8u16, __VA_ARGS__) +#define PCKEV_H2_SH(...) PCKEV_H2(v8i16, __VA_ARGS__) +#define PCKEV_H2_SW(...) PCKEV_H2(v4i32, __VA_ARGS__) +#define PCKEV_H2_UW(...) PCKEV_H2(v4u32, __VA_ARGS__) + +/* Description : Pack even word elements of vector pairs + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Even word elements of 'in0' are copied to the left half of + * 'out0' & even word elements of 'in1' are copied to the + * right half of 'out0'. + */ +#define PCKEV_W2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_pckev_w((v4i32)in0, (v4i32)in1); \ + out1 = (RTYPE)__msa_pckev_w((v4i32)in2, (v4i32)in3); \ +} while (0) +#define PCKEV_W2_UH(...) PCKEV_W2(v8u16, __VA_ARGS__) +#define PCKEV_W2_SH(...) PCKEV_W2(v8i16, __VA_ARGS__) +#define PCKEV_W2_SW(...) PCKEV_W2(v4i32, __VA_ARGS__) +#define PCKEV_W2_UW(...) PCKEV_W2(v4u32, __VA_ARGS__) + +/* Description : Pack odd halfword elements of vector pairs + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Odd halfword elements of 'in0' are copied to the left half of + * 'out0' & odd halfword elements of 'in1' are copied to the + * right half of 'out0'. + */ +#define PCKOD_H2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_pckod_h((v8i16)in0, (v8i16)in1); \ + out1 = (RTYPE)__msa_pckod_h((v8i16)in2, (v8i16)in3); \ +} while (0) +#define PCKOD_H2_UH(...) PCKOD_H2(v8u16, __VA_ARGS__) +#define PCKOD_H2_SH(...) PCKOD_H2(v8i16, __VA_ARGS__) +#define PCKOD_H2_SW(...) PCKOD_H2(v4i32, __VA_ARGS__) +#define PCKOD_H2_UW(...) PCKOD_H2(v4u32, __VA_ARGS__) + +/* Description : Arithmetic immediate shift right all elements of word vector + * Arguments : Inputs - in0, in1, shift + * Outputs - in place operation + * Return Type - as per input vector RTYPE + * Details : Each element of vector 'in0' is right shifted by 'shift' and + * the result is written in-place. 'shift' is a GP variable. + */ +#define SRAI_W2(RTYPE, in0, in1, shift_val) do { \ + in0 = (RTYPE)SRAI_W(in0, shift_val); \ + in1 = (RTYPE)SRAI_W(in1, shift_val); \ +} while (0) +#define SRAI_W2_SW(...) SRAI_W2(v4i32, __VA_ARGS__) +#define SRAI_W2_UW(...) SRAI_W2(v4u32, __VA_ARGS__) + +#define SRAI_W4(RTYPE, in0, in1, in2, in3, shift_val) do { \ + SRAI_W2(RTYPE, in0, in1, shift_val); \ + SRAI_W2(RTYPE, in2, in3, shift_val); \ +} while (0) +#define SRAI_W4_SW(...) SRAI_W4(v4i32, __VA_ARGS__) +#define SRAI_W4_UW(...) SRAI_W4(v4u32, __VA_ARGS__) + +/* Description : Arithmetic shift right all elements of half-word vector + * Arguments : Inputs - in0, in1, shift + * Outputs - in place operation + * Return Type - as per input vector RTYPE + * Details : Each element of vector 'in0' is right shifted by 'shift' and + * the result is written in-place. 'shift' is a GP variable. + */ +#define SRAI_H2(RTYPE, in0, in1, shift_val) do { \ + in0 = (RTYPE)SRAI_H(in0, shift_val); \ + in1 = (RTYPE)SRAI_H(in1, shift_val); \ +} while (0) +#define SRAI_H2_SH(...) SRAI_H2(v8i16, __VA_ARGS__) +#define SRAI_H2_UH(...) SRAI_H2(v8u16, __VA_ARGS__) + +/* Description : Arithmetic rounded shift right all elements of word vector + * Arguments : Inputs - in0, in1, shift + * Outputs - in place operation + * Return Type - as per input vector RTYPE + * Details : Each element of vector 'in0' is right shifted by 'shift' and + * the result is written in-place. 'shift' is a GP variable. + */ +#define SRARI_W2(RTYPE, in0, in1, shift) do { \ + in0 = (RTYPE)__msa_srari_w((v4i32)in0, shift); \ + in1 = (RTYPE)__msa_srari_w((v4i32)in1, shift); \ +} while (0) +#define SRARI_W2_SW(...) SRARI_W2(v4i32, __VA_ARGS__) + +#define SRARI_W4(RTYPE, in0, in1, in2, in3, shift) do { \ + SRARI_W2(RTYPE, in0, in1, shift); \ + SRARI_W2(RTYPE, in2, in3, shift); \ +} while (0) +#define SRARI_W4_SH(...) SRARI_W4(v8i16, __VA_ARGS__) +#define SRARI_W4_UW(...) SRARI_W4(v4u32, __VA_ARGS__) +#define SRARI_W4_SW(...) SRARI_W4(v4i32, __VA_ARGS__) + +/* Description : Shift right arithmetic rounded double words + * Arguments : Inputs - in0, in1, shift + * Outputs - in place operation + * Return Type - as per RTYPE + * Details : Each element of vector 'in0' is shifted right arithmetically by + * the number of bits in the corresponding element in the vector + * 'shift'. The last discarded bit is added to shifted value for + * rounding and the result is written in-place. + * 'shift' is a vector. + */ +#define SRAR_D2(RTYPE, in0, in1, shift) do { \ + in0 = (RTYPE)__msa_srar_d((v2i64)in0, (v2i64)shift); \ + in1 = (RTYPE)__msa_srar_d((v2i64)in1, (v2i64)shift); \ +} while (0) +#define SRAR_D2_SW(...) SRAR_D2(v4i32, __VA_ARGS__) +#define SRAR_D2_SD(...) SRAR_D2(v2i64, __VA_ARGS__) +#define SRAR_D2_UD(...) SRAR_D2(v2u64, __VA_ARGS__) + +#define SRAR_D4(RTYPE, in0, in1, in2, in3, shift) do { \ + SRAR_D2(RTYPE, in0, in1, shift); \ + SRAR_D2(RTYPE, in2, in3, shift); \ +} while (0) +#define SRAR_D4_SD(...) SRAR_D4(v2i64, __VA_ARGS__) +#define SRAR_D4_UD(...) SRAR_D4(v2u64, __VA_ARGS__) + +/* Description : Addition of 2 pairs of half-word vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Details : Each element in 'in0' is added to 'in1' and result is written + * to 'out0'. + */ +#define ADDVI_H2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)ADDVI_H(in0, in1); \ + out1 = (RTYPE)ADDVI_H(in2, in3); \ +} while (0) +#define ADDVI_H2_SH(...) ADDVI_H2(v8i16, __VA_ARGS__) +#define ADDVI_H2_UH(...) ADDVI_H2(v8u16, __VA_ARGS__) + +/* Description : Addition of 2 pairs of word vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Details : Each element in 'in0' is added to 'in1' and result is written + * to 'out0'. + */ +#define ADDVI_W2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)ADDVI_W(in0, in1); \ + out1 = (RTYPE)ADDVI_W(in2, in3); \ +} while (0) +#define ADDVI_W2_SW(...) ADDVI_W2(v4i32, __VA_ARGS__) + +/* Description : Fill 2 pairs of word vectors with GP registers + * Arguments : Inputs - in0, in1 + * Outputs - out0, out1 + * Details : GP register in0 is replicated in each word element of out0 + * GP register in1 is replicated in each word element of out1 + */ +#define FILL_W2(RTYPE, in0, in1, out0, out1) do { \ + out0 = (RTYPE)__msa_fill_w(in0); \ + out1 = (RTYPE)__msa_fill_w(in1); \ +} while (0) +#define FILL_W2_SW(...) FILL_W2(v4i32, __VA_ARGS__) + +/* Description : Addition of 2 pairs of vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Details : Each element in 'in0' is added to 'in1' and result is written + * to 'out0'. + */ +#define ADD2(in0, in1, in2, in3, out0, out1) do { \ + out0 = in0 + in1; \ + out1 = in2 + in3; \ +} while (0) + +#define ADD4(in0, in1, in2, in3, in4, in5, in6, in7, \ + out0, out1, out2, out3) do { \ + ADD2(in0, in1, in2, in3, out0, out1); \ + ADD2(in4, in5, in6, in7, out2, out3); \ +} while (0) + +/* Description : Subtraction of 2 pairs of vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Details : Each element in 'in1' is subtracted from 'in0' and result is + * written to 'out0'. + */ +#define SUB2(in0, in1, in2, in3, out0, out1) do { \ + out0 = in0 - in1; \ + out1 = in2 - in3; \ +} while (0) + +#define SUB3(in0, in1, in2, in3, in4, in5, out0, out1, out2) do { \ + out0 = in0 - in1; \ + out1 = in2 - in3; \ + out2 = in4 - in5; \ +} while (0) + +#define SUB4(in0, in1, in2, in3, in4, in5, in6, in7, \ + out0, out1, out2, out3) do { \ + out0 = in0 - in1; \ + out1 = in2 - in3; \ + out2 = in4 - in5; \ + out3 = in6 - in7; \ +} while (0) + +/* Description : Addition - Subtraction of input vectors + * Arguments : Inputs - in0, in1 + * Outputs - out0, out1 + * Details : Each element in 'in1' is added to 'in0' and result is + * written to 'out0'. + * Each element in 'in1' is subtracted from 'in0' and result is + * written to 'out1'. + */ +#define ADDSUB2(in0, in1, out0, out1) do { \ + out0 = in0 + in1; \ + out1 = in0 - in1; \ +} while (0) + +/* Description : Multiplication of pairs of vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1 + * Details : Each element from 'in0' is multiplied with elements from 'in1' + * and the result is written to 'out0' + */ +#define MUL2(in0, in1, in2, in3, out0, out1) do { \ + out0 = in0 * in1; \ + out1 = in2 * in3; \ +} while (0) + +#define MUL4(in0, in1, in2, in3, in4, in5, in6, in7, \ + out0, out1, out2, out3) do { \ + MUL2(in0, in1, in2, in3, out0, out1); \ + MUL2(in4, in5, in6, in7, out2, out3); \ +} while (0) + +/* Description : Sign extend halfword elements from right half of the vector + * Arguments : Input - in (halfword vector) + * Output - out (sign extended word vector) + * Return Type - signed word + * Details : Sign bit of halfword elements from input vector 'in' is + * extracted and interleaved with same vector 'in0' to generate + * 4 word elements keeping sign intact + */ +#define UNPCK_R_SH_SW(in, out) do { \ + const v8i16 sign_m = __msa_clti_s_h((v8i16)in, 0); \ + out = (v4i32)__msa_ilvr_h(sign_m, (v8i16)in); \ +} while (0) + +/* Description : Sign extend halfword elements from input vector and return + * the result in pair of vectors + * Arguments : Input - in (halfword vector) + * Outputs - out0, out1 (sign extended word vectors) + * Return Type - signed word + * Details : Sign bit of halfword elements from input vector 'in' is + * extracted and interleaved right with same vector 'in0' to + * generate 4 signed word elements in 'out0' + * Then interleaved left with same vector 'in0' to + * generate 4 signed word elements in 'out1' + */ +#define UNPCK_SH_SW(in, out0, out1) do { \ + const v8i16 tmp_m = __msa_clti_s_h((v8i16)in, 0); \ + ILVRL_H2_SW(tmp_m, in, out0, out1); \ +} while (0) + +/* Description : Butterfly of 4 input vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1, out2, out3 + * Details : Butterfly operation + */ +#define BUTTERFLY_4(in0, in1, in2, in3, out0, out1, out2, out3) do { \ + out0 = in0 + in3; \ + out1 = in1 + in2; \ + out2 = in1 - in2; \ + out3 = in0 - in3; \ +} while (0) + +/* Description : Transpose 16x4 block into 4x16 with byte elements in vectors + * Arguments : Inputs - in0, in1, in2, in3, in4, in5, in6, in7, + * in8, in9, in10, in11, in12, in13, in14, in15 + * Outputs - out0, out1, out2, out3 + * Return Type - unsigned byte + */ +#define TRANSPOSE16x4_UB_UB(in0, in1, in2, in3, in4, in5, in6, in7, \ + in8, in9, in10, in11, in12, in13, in14, in15, \ + out0, out1, out2, out3) do { \ + v2i64 tmp0_m, tmp1_m, tmp2_m, tmp3_m, tmp4_m, tmp5_m; \ + ILVEV_W2_SD(in0, in4, in8, in12, tmp2_m, tmp3_m); \ + ILVEV_W2_SD(in1, in5, in9, in13, tmp0_m, tmp1_m); \ + ILVEV_D2_UB(tmp2_m, tmp3_m, tmp0_m, tmp1_m, out1, out3); \ + ILVEV_W2_SD(in2, in6, in10, in14, tmp4_m, tmp5_m); \ + ILVEV_W2_SD(in3, in7, in11, in15, tmp0_m, tmp1_m); \ + ILVEV_D2_SD(tmp4_m, tmp5_m, tmp0_m, tmp1_m, tmp2_m, tmp3_m); \ + ILVEV_B2_SD(out1, out3, tmp2_m, tmp3_m, tmp0_m, tmp1_m); \ + ILVEVOD_H2_UB(tmp0_m, tmp1_m, tmp0_m, tmp1_m, out0, out2); \ + ILVOD_B2_SD(out1, out3, tmp2_m, tmp3_m, tmp0_m, tmp1_m); \ + ILVEVOD_H2_UB(tmp0_m, tmp1_m, tmp0_m, tmp1_m, out1, out3); \ +} while (0) + +/* Description : Transpose 16x8 block into 8x16 with byte elements in vectors + * Arguments : Inputs - in0, in1, in2, in3, in4, in5, in6, in7, + * in8, in9, in10, in11, in12, in13, in14, in15 + * Outputs - out0, out1, out2, out3, out4, out5, out6, out7 + * Return Type - unsigned byte + */ +#define TRANSPOSE16x8_UB_UB(in0, in1, in2, in3, in4, in5, in6, in7, \ + in8, in9, in10, in11, in12, in13, in14, in15, \ + out0, out1, out2, out3, out4, out5, \ + out6, out7) do { \ + v8i16 tmp0_m, tmp1_m, tmp4_m, tmp5_m, tmp6_m, tmp7_m; \ + v4i32 tmp2_m, tmp3_m; \ + ILVEV_D2_UB(in0, in8, in1, in9, out7, out6); \ + ILVEV_D2_UB(in2, in10, in3, in11, out5, out4); \ + ILVEV_D2_UB(in4, in12, in5, in13, out3, out2); \ + ILVEV_D2_UB(in6, in14, in7, in15, out1, out0); \ + ILVEV_B2_SH(out7, out6, out5, out4, tmp0_m, tmp1_m); \ + ILVOD_B2_SH(out7, out6, out5, out4, tmp4_m, tmp5_m); \ + ILVEV_B2_UB(out3, out2, out1, out0, out5, out7); \ + ILVOD_B2_SH(out3, out2, out1, out0, tmp6_m, tmp7_m); \ + ILVEV_H2_SW(tmp0_m, tmp1_m, out5, out7, tmp2_m, tmp3_m); \ + ILVEVOD_W2_UB(tmp2_m, tmp3_m, tmp2_m, tmp3_m, out0, out4); \ + ILVOD_H2_SW(tmp0_m, tmp1_m, out5, out7, tmp2_m, tmp3_m); \ + ILVEVOD_W2_UB(tmp2_m, tmp3_m, tmp2_m, tmp3_m, out2, out6); \ + ILVEV_H2_SW(tmp4_m, tmp5_m, tmp6_m, tmp7_m, tmp2_m, tmp3_m); \ + ILVEVOD_W2_UB(tmp2_m, tmp3_m, tmp2_m, tmp3_m, out1, out5); \ + ILVOD_H2_SW(tmp4_m, tmp5_m, tmp6_m, tmp7_m, tmp2_m, tmp3_m); \ + ILVEVOD_W2_UB(tmp2_m, tmp3_m, tmp2_m, tmp3_m, out3, out7); \ +} while (0) + +/* Description : Transpose 4x4 block with word elements in vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1, out2, out3 + * Return Type - as per RTYPE + */ +#define TRANSPOSE4x4_W(RTYPE, in0, in1, in2, in3, \ + out0, out1, out2, out3) do { \ + v4i32 s0_m, s1_m, s2_m, s3_m; \ + ILVRL_W2_SW(in1, in0, s0_m, s1_m); \ + ILVRL_W2_SW(in3, in2, s2_m, s3_m); \ + out0 = (RTYPE)__msa_ilvr_d((v2i64)s2_m, (v2i64)s0_m); \ + out1 = (RTYPE)__msa_ilvl_d((v2i64)s2_m, (v2i64)s0_m); \ + out2 = (RTYPE)__msa_ilvr_d((v2i64)s3_m, (v2i64)s1_m); \ + out3 = (RTYPE)__msa_ilvl_d((v2i64)s3_m, (v2i64)s1_m); \ +} while (0) +#define TRANSPOSE4x4_SW_SW(...) TRANSPOSE4x4_W(v4i32, __VA_ARGS__) + +/* Description : Add block 4x4 + * Arguments : Inputs - in0, in1, in2, in3, pdst, stride + * Details : Least significant 4 bytes from each input vector are added to + * the destination bytes, clipped between 0-255 and stored. + */ +#define ADDBLK_ST4x4_UB(in0, in1, in2, in3, pdst, stride) do { \ + uint32_t src0_m, src1_m, src2_m, src3_m; \ + v8i16 inp0_m, inp1_m, res0_m, res1_m; \ + v16i8 dst0_m = { 0 }; \ + v16i8 dst1_m = { 0 }; \ + const v16i8 zero_m = { 0 }; \ + ILVR_D2_SH(in1, in0, in3, in2, inp0_m, inp1_m); \ + LW4(pdst, stride, src0_m, src1_m, src2_m, src3_m); \ + INSERT_W2_SB(src0_m, src1_m, dst0_m); \ + INSERT_W2_SB(src2_m, src3_m, dst1_m); \ + ILVR_B2_SH(zero_m, dst0_m, zero_m, dst1_m, res0_m, res1_m); \ + ADD2(res0_m, inp0_m, res1_m, inp1_m, res0_m, res1_m); \ + CLIP_SH2_0_255(res0_m, res1_m); \ + PCKEV_B2_SB(res0_m, res0_m, res1_m, res1_m, dst0_m, dst1_m); \ + ST4x4_UB(dst0_m, dst1_m, 0, 1, 0, 1, pdst, stride); \ +} while (0) + +/* Description : Pack even byte elements, extract 0 & 2 index words from pair + * of results and store 4 words in destination memory as per + * stride + * Arguments : Inputs - in0, in1, in2, in3, pdst, stride + */ +#define PCKEV_ST4x4_UB(in0, in1, in2, in3, pdst, stride) do { \ + v16i8 tmp0_m, tmp1_m; \ + PCKEV_B2_SB(in1, in0, in3, in2, tmp0_m, tmp1_m); \ + ST4x4_UB(tmp0_m, tmp1_m, 0, 2, 0, 2, pdst, stride); \ +} while (0) + +/* Description : average with rounding (in0 + in1 + 1) / 2. + * Arguments : Inputs - in0, in1, in2, in3, + * Outputs - out0, out1 + * Return Type - as per RTYPE + * Details : Each unsigned byte element from 'in0' vector is added with + * each unsigned byte element from 'in1' vector. Then the average + * with rounding is calculated and written to 'out0' + */ +#define AVER_UB2(RTYPE, in0, in1, in2, in3, out0, out1) do { \ + out0 = (RTYPE)__msa_aver_u_b((v16u8)in0, (v16u8)in1); \ + out1 = (RTYPE)__msa_aver_u_b((v16u8)in2, (v16u8)in3); \ +} while (0) +#define AVER_UB2_UB(...) AVER_UB2(v16u8, __VA_ARGS__) + +#endif // WEBP_USE_MSA +#endif // WEBP_DSP_MSA_MACRO_H_ diff --git a/third-party/webp/libwebp/src/dsp/neon.h b/third-party/webp/libwebp/src/dsp/neon.h new file mode 100644 index 0000000000..14acb4044b --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/neon.h @@ -0,0 +1,104 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// NEON common code. + +#ifndef WEBP_DSP_NEON_H_ +#define WEBP_DSP_NEON_H_ + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_NEON) + +#include + +// Right now, some intrinsics functions seem slower, so we disable them +// everywhere except newer clang/gcc or aarch64 where the inline assembly is +// incompatible. +#if LOCAL_CLANG_PREREQ(3, 8) || LOCAL_GCC_PREREQ(4, 9) || WEBP_AARCH64 +#define WEBP_USE_INTRINSICS // use intrinsics when possible +#endif + +#define INIT_VECTOR2(v, a, b) do { \ + v.val[0] = a; \ + v.val[1] = b; \ +} while (0) + +#define INIT_VECTOR3(v, a, b, c) do { \ + v.val[0] = a; \ + v.val[1] = b; \ + v.val[2] = c; \ +} while (0) + +#define INIT_VECTOR4(v, a, b, c, d) do { \ + v.val[0] = a; \ + v.val[1] = b; \ + v.val[2] = c; \ + v.val[3] = d; \ +} while (0) + +// if using intrinsics, this flag avoids some functions that make gcc-4.6.3 +// crash ("internal compiler error: in immed_double_const, at emit-rtl."). +// (probably similar to gcc.gnu.org/bugzilla/show_bug.cgi?id=48183) +#if !(LOCAL_CLANG_PREREQ(3, 8) || LOCAL_GCC_PREREQ(4, 8) || WEBP_AARCH64) +#define WORK_AROUND_GCC +#endif + +static WEBP_INLINE int32x4x4_t Transpose4x4_NEON(const int32x4x4_t rows) { + uint64x2x2_t row01, row23; + + row01.val[0] = vreinterpretq_u64_s32(rows.val[0]); + row01.val[1] = vreinterpretq_u64_s32(rows.val[1]); + row23.val[0] = vreinterpretq_u64_s32(rows.val[2]); + row23.val[1] = vreinterpretq_u64_s32(rows.val[3]); + // Transpose 64-bit values (there's no vswp equivalent) + { + const uint64x1_t row0h = vget_high_u64(row01.val[0]); + const uint64x1_t row2l = vget_low_u64(row23.val[0]); + const uint64x1_t row1h = vget_high_u64(row01.val[1]); + const uint64x1_t row3l = vget_low_u64(row23.val[1]); + row01.val[0] = vcombine_u64(vget_low_u64(row01.val[0]), row2l); + row23.val[0] = vcombine_u64(row0h, vget_high_u64(row23.val[0])); + row01.val[1] = vcombine_u64(vget_low_u64(row01.val[1]), row3l); + row23.val[1] = vcombine_u64(row1h, vget_high_u64(row23.val[1])); + } + { + const int32x4x2_t out01 = vtrnq_s32(vreinterpretq_s32_u64(row01.val[0]), + vreinterpretq_s32_u64(row01.val[1])); + const int32x4x2_t out23 = vtrnq_s32(vreinterpretq_s32_u64(row23.val[0]), + vreinterpretq_s32_u64(row23.val[1])); + int32x4x4_t out; + out.val[0] = out01.val[0]; + out.val[1] = out01.val[1]; + out.val[2] = out23.val[0]; + out.val[3] = out23.val[1]; + return out; + } +} + +#if 0 // Useful debug macro. +#include +#define PRINT_REG(REG, SIZE) do { \ + int i; \ + printf("%s \t[%d]: 0x", #REG, SIZE); \ + if (SIZE == 8) { \ + uint8_t _tmp[8]; \ + vst1_u8(_tmp, (REG)); \ + for (i = 0; i < 8; ++i) printf("%.2x ", _tmp[i]); \ + } else if (SIZE == 16) { \ + uint16_t _tmp[4]; \ + vst1_u16(_tmp, (REG)); \ + for (i = 0; i < 4; ++i) printf("%.4x ", _tmp[i]); \ + } \ + printf("\n"); \ +} while (0) +#endif + +#endif // WEBP_USE_NEON +#endif // WEBP_DSP_NEON_H_ diff --git a/third-party/webp/libwebp/src/dsp/quant.h b/third-party/webp/libwebp/src/dsp/quant.h new file mode 100644 index 0000000000..dcbc11c77c --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/quant.h @@ -0,0 +1,91 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- + +#ifndef WEBP_DSP_QUANT_H_ +#define WEBP_DSP_QUANT_H_ + +#include + +#include "src/dsp/dsp.h" +#include "src/webp/types.h" + +#if defined(WEBP_USE_NEON) && !defined(WEBP_ANDROID_NEON) && \ + !defined(WEBP_HAVE_NEON_RTCD) +#include + +#define IsFlat IsFlat_NEON + +static uint32_t horizontal_add_uint32x4(const uint32x4_t a) { +#if WEBP_AARCH64 + return vaddvq_u32(a); +#else + const uint64x2_t b = vpaddlq_u32(a); + const uint32x2_t c = vadd_u32(vreinterpret_u32_u64(vget_low_u64(b)), + vreinterpret_u32_u64(vget_high_u64(b))); + return vget_lane_u32(c, 0); +#endif +} + +static WEBP_INLINE int IsFlat(const int16_t* levels, int num_blocks, + int thresh) { + const int16x8_t tst_ones = vdupq_n_s16(-1); + uint32x4_t sum = vdupq_n_u32(0); + int i; + + for (i = 0; i < num_blocks; ++i) { + // Set DC to zero. + const int16x8_t a_0 = vsetq_lane_s16(0, vld1q_s16(levels), 0); + const int16x8_t a_1 = vld1q_s16(levels + 8); + + const uint16x8_t b_0 = vshrq_n_u16(vtstq_s16(a_0, tst_ones), 15); + const uint16x8_t b_1 = vshrq_n_u16(vtstq_s16(a_1, tst_ones), 15); + + sum = vpadalq_u16(sum, b_0); + sum = vpadalq_u16(sum, b_1); + + levels += 16; + } + return thresh >= (int)horizontal_add_uint32x4(sum); +} + +#else + +#define IsFlat IsFlat_C + +static WEBP_INLINE int IsFlat(const int16_t* levels, int num_blocks, + int thresh) { + int score = 0; + while (num_blocks-- > 0) { // TODO(skal): refine positional scoring? + int i; + for (i = 1; i < 16; ++i) { // omit DC, we're only interested in AC + score += (levels[i] != 0); + if (score > thresh) return 0; + } + levels += 16; + } + return 1; +} + +#endif // defined(WEBP_USE_NEON) && !defined(WEBP_ANDROID_NEON) && + // !defined(WEBP_HAVE_NEON_RTCD) + +static WEBP_INLINE int IsFlatSource16(const uint8_t* src) { + const uint32_t v = src[0] * 0x01010101u; + int i; + for (i = 0; i < 16; ++i) { + if (memcmp(src + 0, &v, 4) || memcmp(src + 4, &v, 4) || + memcmp(src + 8, &v, 4) || memcmp(src + 12, &v, 4)) { + return 0; + } + src += BPS; + } + return 1; +} + +#endif // WEBP_DSP_QUANT_H_ diff --git a/third-party/webp/libwebp/src/dsp/rescaler.c b/third-party/webp/libwebp/src/dsp/rescaler.c new file mode 100644 index 0000000000..325d8be180 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/rescaler.c @@ -0,0 +1,252 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Rescaling functions +// +// Author: Skal (pascal.massimino@gmail.com) + +#include + +#include "src/dsp/dsp.h" +#include "src/utils/rescaler_utils.h" + +//------------------------------------------------------------------------------ +// Implementations of critical functions ImportRow / ExportRow + +#define ROUNDER (WEBP_RESCALER_ONE >> 1) +#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX) +#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX) + +//------------------------------------------------------------------------------ +// Row import + +void WebPRescalerImportRowExpand_C(WebPRescaler* const wrk, + const uint8_t* src) { + const int x_stride = wrk->num_channels; + const int x_out_max = wrk->dst_width * wrk->num_channels; + int channel; + assert(!WebPRescalerInputDone(wrk)); + assert(wrk->x_expand); + for (channel = 0; channel < x_stride; ++channel) { + int x_in = channel; + int x_out = channel; + // simple bilinear interpolation + int accum = wrk->x_add; + rescaler_t left = (rescaler_t)src[x_in]; + rescaler_t right = + (wrk->src_width > 1) ? (rescaler_t)src[x_in + x_stride] : left; + x_in += x_stride; + while (1) { + wrk->frow[x_out] = right * wrk->x_add + (left - right) * accum; + x_out += x_stride; + if (x_out >= x_out_max) break; + accum -= wrk->x_sub; + if (accum < 0) { + left = right; + x_in += x_stride; + assert(x_in < wrk->src_width * x_stride); + right = (rescaler_t)src[x_in]; + accum += wrk->x_add; + } + } + assert(wrk->x_sub == 0 /* <- special case for src_width=1 */ || accum == 0); + } +} + +void WebPRescalerImportRowShrink_C(WebPRescaler* const wrk, + const uint8_t* src) { + const int x_stride = wrk->num_channels; + const int x_out_max = wrk->dst_width * wrk->num_channels; + int channel; + assert(!WebPRescalerInputDone(wrk)); + assert(!wrk->x_expand); + for (channel = 0; channel < x_stride; ++channel) { + int x_in = channel; + int x_out = channel; + uint32_t sum = 0; + int accum = 0; + while (x_out < x_out_max) { + uint32_t base = 0; + accum += wrk->x_add; + while (accum > 0) { + accum -= wrk->x_sub; + assert(x_in < wrk->src_width * x_stride); + base = src[x_in]; + sum += base; + x_in += x_stride; + } + { // Emit next horizontal pixel. + const rescaler_t frac = base * (-accum); + wrk->frow[x_out] = sum * wrk->x_sub - frac; + // fresh fractional start for next pixel + sum = (int)MULT_FIX(frac, wrk->fx_scale); + } + x_out += x_stride; + } + assert(accum == 0); + } +} + +//------------------------------------------------------------------------------ +// Row export + +void WebPRescalerExportRowExpand_C(WebPRescaler* const wrk) { + int x_out; + uint8_t* const dst = wrk->dst; + rescaler_t* const irow = wrk->irow; + const int x_out_max = wrk->dst_width * wrk->num_channels; + const rescaler_t* const frow = wrk->frow; + assert(!WebPRescalerOutputDone(wrk)); + assert(wrk->y_accum <= 0); + assert(wrk->y_expand); + assert(wrk->y_sub != 0); + if (wrk->y_accum == 0) { + for (x_out = 0; x_out < x_out_max; ++x_out) { + const uint32_t J = frow[x_out]; + const int v = (int)MULT_FIX(J, wrk->fy_scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + } + } else { + const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub); + const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B); + for (x_out = 0; x_out < x_out_max; ++x_out) { + const uint64_t I = (uint64_t)A * frow[x_out] + + (uint64_t)B * irow[x_out]; + const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX); + const int v = (int)MULT_FIX(J, wrk->fy_scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + } + } +} + +void WebPRescalerExportRowShrink_C(WebPRescaler* const wrk) { + int x_out; + uint8_t* const dst = wrk->dst; + rescaler_t* const irow = wrk->irow; + const int x_out_max = wrk->dst_width * wrk->num_channels; + const rescaler_t* const frow = wrk->frow; + const uint32_t yscale = wrk->fy_scale * (-wrk->y_accum); + assert(!WebPRescalerOutputDone(wrk)); + assert(wrk->y_accum <= 0); + assert(!wrk->y_expand); + if (yscale) { + for (x_out = 0; x_out < x_out_max; ++x_out) { + const uint32_t frac = (uint32_t)MULT_FIX_FLOOR(frow[x_out], yscale); + const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + irow[x_out] = frac; // new fractional start + } + } else { + for (x_out = 0; x_out < x_out_max; ++x_out) { + const int v = (int)MULT_FIX(irow[x_out], wrk->fxy_scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + irow[x_out] = 0; + } + } +} + +#undef MULT_FIX_FLOOR +#undef MULT_FIX +#undef ROUNDER + +//------------------------------------------------------------------------------ +// Main entry calls + +void WebPRescalerImportRow(WebPRescaler* const wrk, const uint8_t* src) { + assert(!WebPRescalerInputDone(wrk)); + if (!wrk->x_expand) { + WebPRescalerImportRowShrink(wrk, src); + } else { + WebPRescalerImportRowExpand(wrk, src); + } +} + +void WebPRescalerExportRow(WebPRescaler* const wrk) { + if (wrk->y_accum <= 0) { + assert(!WebPRescalerOutputDone(wrk)); + if (wrk->y_expand) { + WebPRescalerExportRowExpand(wrk); + } else if (wrk->fxy_scale) { + WebPRescalerExportRowShrink(wrk); + } else { // special case + int i; + assert(wrk->src_height == wrk->dst_height && wrk->x_add == 1); + assert(wrk->src_width == 1 && wrk->dst_width <= 2); + for (i = 0; i < wrk->num_channels * wrk->dst_width; ++i) { + wrk->dst[i] = wrk->irow[i]; + wrk->irow[i] = 0; + } + } + wrk->y_accum += wrk->y_add; + wrk->dst += wrk->dst_stride; + ++wrk->dst_y; + } +} + +//------------------------------------------------------------------------------ + +WebPRescalerImportRowFunc WebPRescalerImportRowExpand; +WebPRescalerImportRowFunc WebPRescalerImportRowShrink; + +WebPRescalerExportRowFunc WebPRescalerExportRowExpand; +WebPRescalerExportRowFunc WebPRescalerExportRowShrink; + +extern VP8CPUInfo VP8GetCPUInfo; +extern void WebPRescalerDspInitSSE2(void); +extern void WebPRescalerDspInitMIPS32(void); +extern void WebPRescalerDspInitMIPSdspR2(void); +extern void WebPRescalerDspInitMSA(void); +extern void WebPRescalerDspInitNEON(void); + +WEBP_DSP_INIT_FUNC(WebPRescalerDspInit) { +#if !defined(WEBP_REDUCE_SIZE) +#if !WEBP_NEON_OMIT_C_CODE + WebPRescalerExportRowExpand = WebPRescalerExportRowExpand_C; + WebPRescalerExportRowShrink = WebPRescalerExportRowShrink_C; +#endif + + WebPRescalerImportRowExpand = WebPRescalerImportRowExpand_C; + WebPRescalerImportRowShrink = WebPRescalerImportRowShrink_C; + + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_HAVE_SSE2) + if (VP8GetCPUInfo(kSSE2)) { + WebPRescalerDspInitSSE2(); + } +#endif +#if defined(WEBP_USE_MIPS32) + if (VP8GetCPUInfo(kMIPS32)) { + WebPRescalerDspInitMIPS32(); + } +#endif +#if defined(WEBP_USE_MIPS_DSP_R2) + if (VP8GetCPUInfo(kMIPSdspR2)) { + WebPRescalerDspInitMIPSdspR2(); + } +#endif +#if defined(WEBP_USE_MSA) + if (VP8GetCPUInfo(kMSA)) { + WebPRescalerDspInitMSA(); + } +#endif + } + +#if defined(WEBP_HAVE_NEON) + if (WEBP_NEON_OMIT_C_CODE || + (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) { + WebPRescalerDspInitNEON(); + } +#endif + + assert(WebPRescalerExportRowExpand != NULL); + assert(WebPRescalerExportRowShrink != NULL); + assert(WebPRescalerImportRowExpand != NULL); + assert(WebPRescalerImportRowShrink != NULL); +#endif // WEBP_REDUCE_SIZE +} diff --git a/third-party/webp/libwebp/src/dsp/rescaler_mips32.c b/third-party/webp/libwebp/src/dsp/rescaler_mips32.c new file mode 100644 index 0000000000..61f63c616c --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/rescaler_mips32.c @@ -0,0 +1,295 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MIPS version of rescaling functions +// +// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MIPS32) && !defined(WEBP_REDUCE_SIZE) + +#include +#include "src/utils/rescaler_utils.h" + +//------------------------------------------------------------------------------ +// Row import + +static void ImportRowShrink_MIPS32(WebPRescaler* const wrk, + const uint8_t* src) { + const int x_stride = wrk->num_channels; + const int x_out_max = wrk->dst_width * wrk->num_channels; + const int fx_scale = wrk->fx_scale; + const int x_add = wrk->x_add; + const int x_sub = wrk->x_sub; + const int x_stride1 = x_stride << 2; + int channel; + assert(!wrk->x_expand); + assert(!WebPRescalerInputDone(wrk)); + + for (channel = 0; channel < x_stride; ++channel) { + const uint8_t* src1 = src + channel; + rescaler_t* frow = wrk->frow + channel; + int temp1, temp2, temp3; + int base, frac, sum; + int accum, accum1; + int loop_c = x_out_max - channel; + + __asm__ volatile ( + "li %[temp1], 0x8000 \n\t" + "li %[temp2], 0x10000 \n\t" + "li %[sum], 0 \n\t" + "li %[accum], 0 \n\t" + "1: \n\t" + "addu %[accum], %[accum], %[x_add] \n\t" + "li %[base], 0 \n\t" + "blez %[accum], 3f \n\t" + "2: \n\t" + "lbu %[base], 0(%[src1]) \n\t" + "subu %[accum], %[accum], %[x_sub] \n\t" + "addu %[src1], %[src1], %[x_stride] \n\t" + "addu %[sum], %[sum], %[base] \n\t" + "bgtz %[accum], 2b \n\t" + "3: \n\t" + "negu %[accum1], %[accum] \n\t" + "mul %[frac], %[base], %[accum1] \n\t" + "mul %[temp3], %[sum], %[x_sub] \n\t" + "subu %[loop_c], %[loop_c], %[x_stride] \n\t" + "mult %[temp1], %[temp2] \n\t" + "maddu %[frac], %[fx_scale] \n\t" + "mfhi %[sum] \n\t" + "subu %[temp3], %[temp3], %[frac] \n\t" + "sw %[temp3], 0(%[frow]) \n\t" + "addu %[frow], %[frow], %[x_stride1] \n\t" + "bgtz %[loop_c], 1b \n\t" + : [accum]"=&r"(accum), [src1]"+r"(src1), [temp3]"=&r"(temp3), + [sum]"=&r"(sum), [base]"=&r"(base), [frac]"=&r"(frac), + [frow]"+r"(frow), [accum1]"=&r"(accum1), + [temp2]"=&r"(temp2), [temp1]"=&r"(temp1) + : [x_stride]"r"(x_stride), [fx_scale]"r"(fx_scale), + [x_sub]"r"(x_sub), [x_add]"r"(x_add), + [loop_c]"r"(loop_c), [x_stride1]"r"(x_stride1) + : "memory", "hi", "lo" + ); + assert(accum == 0); + } +} + +static void ImportRowExpand_MIPS32(WebPRescaler* const wrk, + const uint8_t* src) { + const int x_stride = wrk->num_channels; + const int x_out_max = wrk->dst_width * wrk->num_channels; + const int x_add = wrk->x_add; + const int x_sub = wrk->x_sub; + const int src_width = wrk->src_width; + const int x_stride1 = x_stride << 2; + int channel; + assert(wrk->x_expand); + assert(!WebPRescalerInputDone(wrk)); + + for (channel = 0; channel < x_stride; ++channel) { + const uint8_t* src1 = src + channel; + rescaler_t* frow = wrk->frow + channel; + int temp1, temp2, temp3, temp4; + int frac; + int accum; + int x_out = channel; + + __asm__ volatile ( + "addiu %[temp3], %[src_width], -1 \n\t" + "lbu %[temp2], 0(%[src1]) \n\t" + "addu %[src1], %[src1], %[x_stride] \n\t" + "bgtz %[temp3], 0f \n\t" + "addiu %[temp1], %[temp2], 0 \n\t" + "b 3f \n\t" + "0: \n\t" + "lbu %[temp1], 0(%[src1]) \n\t" + "3: \n\t" + "addiu %[accum], %[x_add], 0 \n\t" + "1: \n\t" + "subu %[temp3], %[temp2], %[temp1] \n\t" + "mul %[temp3], %[temp3], %[accum] \n\t" + "mul %[temp4], %[temp1], %[x_add] \n\t" + "addu %[temp3], %[temp4], %[temp3] \n\t" + "sw %[temp3], 0(%[frow]) \n\t" + "addu %[frow], %[frow], %[x_stride1] \n\t" + "addu %[x_out], %[x_out], %[x_stride] \n\t" + "subu %[temp3], %[x_out], %[x_out_max] \n\t" + "bgez %[temp3], 2f \n\t" + "subu %[accum], %[accum], %[x_sub] \n\t" + "bgez %[accum], 4f \n\t" + "addiu %[temp2], %[temp1], 0 \n\t" + "addu %[src1], %[src1], %[x_stride] \n\t" + "lbu %[temp1], 0(%[src1]) \n\t" + "addu %[accum], %[accum], %[x_add] \n\t" + "4: \n\t" + "b 1b \n\t" + "2: \n\t" + : [src1]"+r"(src1), [accum]"=&r"(accum), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), + [x_out]"+r"(x_out), [frac]"=&r"(frac), [frow]"+r"(frow) + : [x_stride]"r"(x_stride), [x_add]"r"(x_add), [x_sub]"r"(x_sub), + [x_stride1]"r"(x_stride1), [src_width]"r"(src_width), + [x_out_max]"r"(x_out_max) + : "memory", "hi", "lo" + ); + assert(wrk->x_sub == 0 /* <- special case for src_width=1 */ || accum == 0); + } +} + +//------------------------------------------------------------------------------ +// Row export + +static void ExportRowExpand_MIPS32(WebPRescaler* const wrk) { + uint8_t* dst = wrk->dst; + rescaler_t* irow = wrk->irow; + const int x_out_max = wrk->dst_width * wrk->num_channels; + const rescaler_t* frow = wrk->frow; + int temp0, temp1, temp3, temp4, temp5, loop_end; + const int temp2 = (int)wrk->fy_scale; + const int temp6 = x_out_max << 2; + assert(!WebPRescalerOutputDone(wrk)); + assert(wrk->y_accum <= 0); + assert(wrk->y_expand); + assert(wrk->y_sub != 0); + if (wrk->y_accum == 0) { + __asm__ volatile ( + "li %[temp3], 0x10000 \n\t" + "li %[temp4], 0x8000 \n\t" + "addu %[loop_end], %[frow], %[temp6] \n\t" + "1: \n\t" + "lw %[temp0], 0(%[frow]) \n\t" + "addiu %[dst], %[dst], 1 \n\t" + "addiu %[frow], %[frow], 4 \n\t" + "mult %[temp3], %[temp4] \n\t" + "maddu %[temp0], %[temp2] \n\t" + "mfhi %[temp5] \n\t" + "sb %[temp5], -1(%[dst]) \n\t" + "bne %[frow], %[loop_end], 1b \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow), + [dst]"+r"(dst), [loop_end]"=&r"(loop_end) + : [temp2]"r"(temp2), [temp6]"r"(temp6) + : "memory", "hi", "lo" + ); + } else { + const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub); + const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B); + __asm__ volatile ( + "li %[temp3], 0x10000 \n\t" + "li %[temp4], 0x8000 \n\t" + "addu %[loop_end], %[frow], %[temp6] \n\t" + "1: \n\t" + "lw %[temp0], 0(%[frow]) \n\t" + "lw %[temp1], 0(%[irow]) \n\t" + "addiu %[dst], %[dst], 1 \n\t" + "mult %[temp3], %[temp4] \n\t" + "maddu %[A], %[temp0] \n\t" + "maddu %[B], %[temp1] \n\t" + "addiu %[frow], %[frow], 4 \n\t" + "addiu %[irow], %[irow], 4 \n\t" + "mfhi %[temp5] \n\t" + "mult %[temp3], %[temp4] \n\t" + "maddu %[temp5], %[temp2] \n\t" + "mfhi %[temp5] \n\t" + "sb %[temp5], -1(%[dst]) \n\t" + "bne %[frow], %[loop_end], 1b \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow), + [irow]"+r"(irow), [dst]"+r"(dst), [loop_end]"=&r"(loop_end) + : [temp2]"r"(temp2), [temp6]"r"(temp6), [A]"r"(A), [B]"r"(B) + : "memory", "hi", "lo" + ); + } +} + +#if 0 // disabled for now. TODO(skal): make match the C-code +static void ExportRowShrink_MIPS32(WebPRescaler* const wrk) { + const int x_out_max = wrk->dst_width * wrk->num_channels; + uint8_t* dst = wrk->dst; + rescaler_t* irow = wrk->irow; + const rescaler_t* frow = wrk->frow; + const int yscale = wrk->fy_scale * (-wrk->y_accum); + int temp0, temp1, temp3, temp4, temp5, loop_end; + const int temp2 = (int)wrk->fxy_scale; + const int temp6 = x_out_max << 2; + + assert(!WebPRescalerOutputDone(wrk)); + assert(wrk->y_accum <= 0); + assert(!wrk->y_expand); + assert(wrk->fxy_scale != 0); + if (yscale) { + __asm__ volatile ( + "li %[temp3], 0x10000 \n\t" + "li %[temp4], 0x8000 \n\t" + "addu %[loop_end], %[frow], %[temp6] \n\t" + "1: \n\t" + "lw %[temp0], 0(%[frow]) \n\t" + "mult %[temp3], %[temp4] \n\t" + "addiu %[frow], %[frow], 4 \n\t" + "maddu %[temp0], %[yscale] \n\t" + "mfhi %[temp1] \n\t" + "lw %[temp0], 0(%[irow]) \n\t" + "addiu %[dst], %[dst], 1 \n\t" + "addiu %[irow], %[irow], 4 \n\t" + "subu %[temp0], %[temp0], %[temp1] \n\t" + "mult %[temp3], %[temp4] \n\t" + "maddu %[temp0], %[temp2] \n\t" + "mfhi %[temp5] \n\t" + "sw %[temp1], -4(%[irow]) \n\t" + "sb %[temp5], -1(%[dst]) \n\t" + "bne %[frow], %[loop_end], 1b \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow), + [irow]"+r"(irow), [dst]"+r"(dst), [loop_end]"=&r"(loop_end) + : [temp2]"r"(temp2), [yscale]"r"(yscale), [temp6]"r"(temp6) + : "memory", "hi", "lo" + ); + } else { + __asm__ volatile ( + "li %[temp3], 0x10000 \n\t" + "li %[temp4], 0x8000 \n\t" + "addu %[loop_end], %[irow], %[temp6] \n\t" + "1: \n\t" + "lw %[temp0], 0(%[irow]) \n\t" + "addiu %[dst], %[dst], 1 \n\t" + "addiu %[irow], %[irow], 4 \n\t" + "mult %[temp3], %[temp4] \n\t" + "maddu %[temp0], %[temp2] \n\t" + "mfhi %[temp5] \n\t" + "sw $zero, -4(%[irow]) \n\t" + "sb %[temp5], -1(%[dst]) \n\t" + "bne %[irow], %[loop_end], 1b \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [irow]"+r"(irow), + [dst]"+r"(dst), [loop_end]"=&r"(loop_end) + : [temp2]"r"(temp2), [temp6]"r"(temp6) + : "memory", "hi", "lo" + ); + } +} +#endif // 0 + +//------------------------------------------------------------------------------ +// Entry point + +extern void WebPRescalerDspInitMIPS32(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMIPS32(void) { + WebPRescalerImportRowExpand = ImportRowExpand_MIPS32; + WebPRescalerImportRowShrink = ImportRowShrink_MIPS32; + WebPRescalerExportRowExpand = ExportRowExpand_MIPS32; +// WebPRescalerExportRowShrink = ExportRowShrink_MIPS32; +} + +#else // !WEBP_USE_MIPS32 + +WEBP_DSP_INIT_STUB(WebPRescalerDspInitMIPS32) + +#endif // WEBP_USE_MIPS32 diff --git a/third-party/webp/libwebp/src/dsp/rescaler_mips_dsp_r2.c b/third-party/webp/libwebp/src/dsp/rescaler_mips_dsp_r2.c new file mode 100644 index 0000000000..419b741fa5 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/rescaler_mips_dsp_r2.c @@ -0,0 +1,314 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MIPS version of rescaling functions +// +// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MIPS_DSP_R2) && !defined(WEBP_REDUCE_SIZE) + +#include +#include "src/utils/rescaler_utils.h" + +#define ROUNDER (WEBP_RESCALER_ONE >> 1) +#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX) +#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX) + +//------------------------------------------------------------------------------ +// Row export + +#if 0 // disabled for now. TODO(skal): make match the C-code +static void ExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) { + int i; + const int x_out_max = wrk->dst_width * wrk->num_channels; + uint8_t* dst = wrk->dst; + rescaler_t* irow = wrk->irow; + const rescaler_t* frow = wrk->frow; + const int yscale = wrk->fy_scale * (-wrk->y_accum); + int temp0, temp1, temp2, temp3, temp4, temp5, loop_end; + const int temp7 = (int)wrk->fxy_scale; + const int temp6 = (x_out_max & ~0x3) << 2; + assert(!WebPRescalerOutputDone(wrk)); + assert(wrk->y_accum <= 0); + assert(!wrk->y_expand); + assert(wrk->fxy_scale != 0); + if (yscale) { + if (x_out_max >= 4) { + int temp8, temp9, temp10, temp11; + __asm__ volatile ( + "li %[temp3], 0x10000 \n\t" + "li %[temp4], 0x8000 \n\t" + "addu %[loop_end], %[frow], %[temp6] \n\t" + "1: \n\t" + "lw %[temp0], 0(%[frow]) \n\t" + "lw %[temp1], 4(%[frow]) \n\t" + "lw %[temp2], 8(%[frow]) \n\t" + "lw %[temp5], 12(%[frow]) \n\t" + "mult $ac0, %[temp3], %[temp4] \n\t" + "maddu $ac0, %[temp0], %[yscale] \n\t" + "mult $ac1, %[temp3], %[temp4] \n\t" + "maddu $ac1, %[temp1], %[yscale] \n\t" + "mult $ac2, %[temp3], %[temp4] \n\t" + "maddu $ac2, %[temp2], %[yscale] \n\t" + "mult $ac3, %[temp3], %[temp4] \n\t" + "maddu $ac3, %[temp5], %[yscale] \n\t" + "addiu %[frow], %[frow], 16 \n\t" + "mfhi %[temp0], $ac0 \n\t" + "mfhi %[temp1], $ac1 \n\t" + "mfhi %[temp2], $ac2 \n\t" + "mfhi %[temp5], $ac3 \n\t" + "lw %[temp8], 0(%[irow]) \n\t" + "lw %[temp9], 4(%[irow]) \n\t" + "lw %[temp10], 8(%[irow]) \n\t" + "lw %[temp11], 12(%[irow]) \n\t" + "addiu %[dst], %[dst], 4 \n\t" + "addiu %[irow], %[irow], 16 \n\t" + "subu %[temp8], %[temp8], %[temp0] \n\t" + "subu %[temp9], %[temp9], %[temp1] \n\t" + "subu %[temp10], %[temp10], %[temp2] \n\t" + "subu %[temp11], %[temp11], %[temp5] \n\t" + "mult $ac0, %[temp3], %[temp4] \n\t" + "maddu $ac0, %[temp8], %[temp7] \n\t" + "mult $ac1, %[temp3], %[temp4] \n\t" + "maddu $ac1, %[temp9], %[temp7] \n\t" + "mult $ac2, %[temp3], %[temp4] \n\t" + "maddu $ac2, %[temp10], %[temp7] \n\t" + "mult $ac3, %[temp3], %[temp4] \n\t" + "maddu $ac3, %[temp11], %[temp7] \n\t" + "mfhi %[temp8], $ac0 \n\t" + "mfhi %[temp9], $ac1 \n\t" + "mfhi %[temp10], $ac2 \n\t" + "mfhi %[temp11], $ac3 \n\t" + "sw %[temp0], -16(%[irow]) \n\t" + "sw %[temp1], -12(%[irow]) \n\t" + "sw %[temp2], -8(%[irow]) \n\t" + "sw %[temp5], -4(%[irow]) \n\t" + "sb %[temp8], -4(%[dst]) \n\t" + "sb %[temp9], -3(%[dst]) \n\t" + "sb %[temp10], -2(%[dst]) \n\t" + "sb %[temp11], -1(%[dst]) \n\t" + "bne %[frow], %[loop_end], 1b \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow), + [irow]"+r"(irow), [dst]"+r"(dst), [loop_end]"=&r"(loop_end), + [temp8]"=&r"(temp8), [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), + [temp11]"=&r"(temp11), [temp2]"=&r"(temp2) + : [temp7]"r"(temp7), [yscale]"r"(yscale), [temp6]"r"(temp6) + : "memory", "hi", "lo", "$ac1hi", "$ac1lo", + "$ac2hi", "$ac2lo", "$ac3hi", "$ac3lo" + ); + } + for (i = 0; i < (x_out_max & 0x3); ++i) { + const uint32_t frac = (uint32_t)MULT_FIX_FLOOR(*frow++, yscale); + const int v = (int)MULT_FIX(*irow - frac, wrk->fxy_scale); + *dst++ = (v > 255) ? 255u : (uint8_t)v; + *irow++ = frac; // new fractional start + } + } else { + if (x_out_max >= 4) { + __asm__ volatile ( + "li %[temp3], 0x10000 \n\t" + "li %[temp4], 0x8000 \n\t" + "addu %[loop_end], %[irow], %[temp6] \n\t" + "1: \n\t" + "lw %[temp0], 0(%[irow]) \n\t" + "lw %[temp1], 4(%[irow]) \n\t" + "lw %[temp2], 8(%[irow]) \n\t" + "lw %[temp5], 12(%[irow]) \n\t" + "addiu %[dst], %[dst], 4 \n\t" + "addiu %[irow], %[irow], 16 \n\t" + "mult $ac0, %[temp3], %[temp4] \n\t" + "maddu $ac0, %[temp0], %[temp7] \n\t" + "mult $ac1, %[temp3], %[temp4] \n\t" + "maddu $ac1, %[temp1], %[temp7] \n\t" + "mult $ac2, %[temp3], %[temp4] \n\t" + "maddu $ac2, %[temp2], %[temp7] \n\t" + "mult $ac3, %[temp3], %[temp4] \n\t" + "maddu $ac3, %[temp5], %[temp7] \n\t" + "mfhi %[temp0], $ac0 \n\t" + "mfhi %[temp1], $ac1 \n\t" + "mfhi %[temp2], $ac2 \n\t" + "mfhi %[temp5], $ac3 \n\t" + "sw $zero, -16(%[irow]) \n\t" + "sw $zero, -12(%[irow]) \n\t" + "sw $zero, -8(%[irow]) \n\t" + "sw $zero, -4(%[irow]) \n\t" + "sb %[temp0], -4(%[dst]) \n\t" + "sb %[temp1], -3(%[dst]) \n\t" + "sb %[temp2], -2(%[dst]) \n\t" + "sb %[temp5], -1(%[dst]) \n\t" + "bne %[irow], %[loop_end], 1b \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [irow]"+r"(irow), + [dst]"+r"(dst), [loop_end]"=&r"(loop_end), [temp2]"=&r"(temp2) + : [temp7]"r"(temp7), [temp6]"r"(temp6) + : "memory", "hi", "lo", "$ac1hi", "$ac1lo", + "$ac2hi", "$ac2lo", "$ac3hi", "$ac3lo" + ); + } + for (i = 0; i < (x_out_max & 0x3); ++i) { + const int v = (int)MULT_FIX_FLOOR(*irow, wrk->fxy_scale); + *dst++ = (v > 255) ? 255u : (uint8_t)v; + *irow++ = 0; + } + } +} +#endif // 0 + +static void ExportRowExpand_MIPSdspR2(WebPRescaler* const wrk) { + int i; + uint8_t* dst = wrk->dst; + rescaler_t* irow = wrk->irow; + const int x_out_max = wrk->dst_width * wrk->num_channels; + const rescaler_t* frow = wrk->frow; + int temp0, temp1, temp2, temp3, temp4, temp5, loop_end; + const int temp6 = (x_out_max & ~0x3) << 2; + const int temp7 = (int)wrk->fy_scale; + assert(!WebPRescalerOutputDone(wrk)); + assert(wrk->y_accum <= 0); + assert(wrk->y_expand); + assert(wrk->y_sub != 0); + if (wrk->y_accum == 0) { + if (x_out_max >= 4) { + __asm__ volatile ( + "li %[temp4], 0x10000 \n\t" + "li %[temp5], 0x8000 \n\t" + "addu %[loop_end], %[frow], %[temp6] \n\t" + "1: \n\t" + "lw %[temp0], 0(%[frow]) \n\t" + "lw %[temp1], 4(%[frow]) \n\t" + "lw %[temp2], 8(%[frow]) \n\t" + "lw %[temp3], 12(%[frow]) \n\t" + "addiu %[dst], %[dst], 4 \n\t" + "addiu %[frow], %[frow], 16 \n\t" + "mult $ac0, %[temp4], %[temp5] \n\t" + "maddu $ac0, %[temp0], %[temp7] \n\t" + "mult $ac1, %[temp4], %[temp5] \n\t" + "maddu $ac1, %[temp1], %[temp7] \n\t" + "mult $ac2, %[temp4], %[temp5] \n\t" + "maddu $ac2, %[temp2], %[temp7] \n\t" + "mult $ac3, %[temp4], %[temp5] \n\t" + "maddu $ac3, %[temp3], %[temp7] \n\t" + "mfhi %[temp0], $ac0 \n\t" + "mfhi %[temp1], $ac1 \n\t" + "mfhi %[temp2], $ac2 \n\t" + "mfhi %[temp3], $ac3 \n\t" + "sb %[temp0], -4(%[dst]) \n\t" + "sb %[temp1], -3(%[dst]) \n\t" + "sb %[temp2], -2(%[dst]) \n\t" + "sb %[temp3], -1(%[dst]) \n\t" + "bne %[frow], %[loop_end], 1b \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow), + [dst]"+r"(dst), [loop_end]"=&r"(loop_end), [temp2]"=&r"(temp2) + : [temp7]"r"(temp7), [temp6]"r"(temp6) + : "memory", "hi", "lo", "$ac1hi", "$ac1lo", + "$ac2hi", "$ac2lo", "$ac3hi", "$ac3lo" + ); + } + for (i = 0; i < (x_out_max & 0x3); ++i) { + const uint32_t J = *frow++; + const int v = (int)MULT_FIX(J, wrk->fy_scale); + *dst++ = (v > 255) ? 255u : (uint8_t)v; + } + } else { + const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub); + const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B); + if (x_out_max >= 4) { + int temp8, temp9, temp10, temp11; + __asm__ volatile ( + "li %[temp8], 0x10000 \n\t" + "li %[temp9], 0x8000 \n\t" + "addu %[loop_end], %[frow], %[temp6] \n\t" + "1: \n\t" + "lw %[temp0], 0(%[frow]) \n\t" + "lw %[temp1], 4(%[frow]) \n\t" + "lw %[temp2], 8(%[frow]) \n\t" + "lw %[temp3], 12(%[frow]) \n\t" + "lw %[temp4], 0(%[irow]) \n\t" + "lw %[temp5], 4(%[irow]) \n\t" + "lw %[temp10], 8(%[irow]) \n\t" + "lw %[temp11], 12(%[irow]) \n\t" + "addiu %[dst], %[dst], 4 \n\t" + "mult $ac0, %[temp8], %[temp9] \n\t" + "maddu $ac0, %[A], %[temp0] \n\t" + "maddu $ac0, %[B], %[temp4] \n\t" + "mult $ac1, %[temp8], %[temp9] \n\t" + "maddu $ac1, %[A], %[temp1] \n\t" + "maddu $ac1, %[B], %[temp5] \n\t" + "mult $ac2, %[temp8], %[temp9] \n\t" + "maddu $ac2, %[A], %[temp2] \n\t" + "maddu $ac2, %[B], %[temp10] \n\t" + "mult $ac3, %[temp8], %[temp9] \n\t" + "maddu $ac3, %[A], %[temp3] \n\t" + "maddu $ac3, %[B], %[temp11] \n\t" + "addiu %[frow], %[frow], 16 \n\t" + "addiu %[irow], %[irow], 16 \n\t" + "mfhi %[temp0], $ac0 \n\t" + "mfhi %[temp1], $ac1 \n\t" + "mfhi %[temp2], $ac2 \n\t" + "mfhi %[temp3], $ac3 \n\t" + "mult $ac0, %[temp8], %[temp9] \n\t" + "maddu $ac0, %[temp0], %[temp7] \n\t" + "mult $ac1, %[temp8], %[temp9] \n\t" + "maddu $ac1, %[temp1], %[temp7] \n\t" + "mult $ac2, %[temp8], %[temp9] \n\t" + "maddu $ac2, %[temp2], %[temp7] \n\t" + "mult $ac3, %[temp8], %[temp9] \n\t" + "maddu $ac3, %[temp3], %[temp7] \n\t" + "mfhi %[temp0], $ac0 \n\t" + "mfhi %[temp1], $ac1 \n\t" + "mfhi %[temp2], $ac2 \n\t" + "mfhi %[temp3], $ac3 \n\t" + "sb %[temp0], -4(%[dst]) \n\t" + "sb %[temp1], -3(%[dst]) \n\t" + "sb %[temp2], -2(%[dst]) \n\t" + "sb %[temp3], -1(%[dst]) \n\t" + "bne %[frow], %[loop_end], 1b \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow), + [irow]"+r"(irow), [dst]"+r"(dst), [loop_end]"=&r"(loop_end), + [temp8]"=&r"(temp8), [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), + [temp11]"=&r"(temp11), [temp2]"=&r"(temp2) + : [temp7]"r"(temp7), [temp6]"r"(temp6), [A]"r"(A), [B]"r"(B) + : "memory", "hi", "lo", "$ac1hi", "$ac1lo", + "$ac2hi", "$ac2lo", "$ac3hi", "$ac3lo" + ); + } + for (i = 0; i < (x_out_max & 0x3); ++i) { + const uint64_t I = (uint64_t)A * *frow++ + + (uint64_t)B * *irow++; + const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX); + const int v = (int)MULT_FIX(J, wrk->fy_scale); + *dst++ = (v > 255) ? 255u : (uint8_t)v; + } + } +} + +#undef MULT_FIX_FLOOR +#undef MULT_FIX +#undef ROUNDER + +//------------------------------------------------------------------------------ +// Entry point + +extern void WebPRescalerDspInitMIPSdspR2(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMIPSdspR2(void) { + WebPRescalerExportRowExpand = ExportRowExpand_MIPSdspR2; +// WebPRescalerExportRowShrink = ExportRowShrink_MIPSdspR2; +} + +#else // !WEBP_USE_MIPS_DSP_R2 + +WEBP_DSP_INIT_STUB(WebPRescalerDspInitMIPSdspR2) + +#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/third-party/webp/libwebp/src/dsp/rescaler_msa.c b/third-party/webp/libwebp/src/dsp/rescaler_msa.c new file mode 100644 index 0000000000..256dbdd437 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/rescaler_msa.c @@ -0,0 +1,443 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MSA version of rescaling functions +// +// Author: Prashant Patil (prashant.patil@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MSA) && !defined(WEBP_REDUCE_SIZE) + +#include + +#include "src/utils/rescaler_utils.h" +#include "src/dsp/msa_macro.h" + +#define ROUNDER (WEBP_RESCALER_ONE >> 1) +#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX) +#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX) + +#define CALC_MULT_FIX_16(in0, in1, in2, in3, scale, shift, dst) do { \ + v4u32 tmp0, tmp1, tmp2, tmp3; \ + v16u8 t0, t1, t2, t3, t4, t5; \ + v2u64 out0, out1, out2, out3; \ + ILVRL_W2_UW(zero, in0, tmp0, tmp1); \ + ILVRL_W2_UW(zero, in1, tmp2, tmp3); \ + DOTP_UW2_UD(tmp0, tmp1, scale, scale, out0, out1); \ + DOTP_UW2_UD(tmp2, tmp3, scale, scale, out2, out3); \ + SRAR_D4_UD(out0, out1, out2, out3, shift); \ + PCKEV_B2_UB(out1, out0, out3, out2, t0, t1); \ + ILVRL_W2_UW(zero, in2, tmp0, tmp1); \ + ILVRL_W2_UW(zero, in3, tmp2, tmp3); \ + DOTP_UW2_UD(tmp0, tmp1, scale, scale, out0, out1); \ + DOTP_UW2_UD(tmp2, tmp3, scale, scale, out2, out3); \ + SRAR_D4_UD(out0, out1, out2, out3, shift); \ + PCKEV_B2_UB(out1, out0, out3, out2, t2, t3); \ + PCKEV_B2_UB(t1, t0, t3, t2, t4, t5); \ + dst = (v16u8)__msa_pckev_b((v16i8)t5, (v16i8)t4); \ +} while (0) + +#define CALC_MULT_FIX_4(in0, scale, shift, dst) do { \ + v4u32 tmp0, tmp1; \ + v16i8 t0, t1; \ + v2u64 out0, out1; \ + ILVRL_W2_UW(zero, in0, tmp0, tmp1); \ + DOTP_UW2_UD(tmp0, tmp1, scale, scale, out0, out1); \ + SRAR_D2_UD(out0, out1, shift); \ + t0 = __msa_pckev_b((v16i8)out1, (v16i8)out0); \ + t1 = __msa_pckev_b(t0, t0); \ + t0 = __msa_pckev_b(t1, t1); \ + dst = __msa_copy_s_w((v4i32)t0, 0); \ +} while (0) + +#define CALC_MULT_FIX1_16(in0, in1, in2, in3, fyscale, shift, \ + dst0, dst1, dst2, dst3) do { \ + v4u32 tmp0, tmp1, tmp2, tmp3; \ + v2u64 out0, out1, out2, out3; \ + ILVRL_W2_UW(zero, in0, tmp0, tmp1); \ + ILVRL_W2_UW(zero, in1, tmp2, tmp3); \ + DOTP_UW2_UD(tmp0, tmp1, fyscale, fyscale, out0, out1); \ + DOTP_UW2_UD(tmp2, tmp3, fyscale, fyscale, out2, out3); \ + SRAR_D4_UD(out0, out1, out2, out3, shift); \ + PCKEV_W2_UW(out1, out0, out3, out2, dst0, dst1); \ + ILVRL_W2_UW(zero, in2, tmp0, tmp1); \ + ILVRL_W2_UW(zero, in3, tmp2, tmp3); \ + DOTP_UW2_UD(tmp0, tmp1, fyscale, fyscale, out0, out1); \ + DOTP_UW2_UD(tmp2, tmp3, fyscale, fyscale, out2, out3); \ + SRAR_D4_UD(out0, out1, out2, out3, shift); \ + PCKEV_W2_UW(out1, out0, out3, out2, dst2, dst3); \ +} while (0) + +#define CALC_MULT_FIX1_4(in0, scale, shift, dst) do { \ + v4u32 tmp0, tmp1; \ + v2u64 out0, out1; \ + ILVRL_W2_UW(zero, in0, tmp0, tmp1); \ + DOTP_UW2_UD(tmp0, tmp1, scale, scale, out0, out1); \ + SRAR_D2_UD(out0, out1, shift); \ + dst = (v4u32)__msa_pckev_w((v4i32)out1, (v4i32)out0); \ +} while (0) + +#define CALC_MULT_FIX2_16(in0, in1, in2, in3, mult, scale, shift, \ + dst0, dst1) do { \ + v4u32 tmp0, tmp1, tmp2, tmp3; \ + v2u64 out0, out1, out2, out3; \ + ILVRL_W2_UW(in0, in2, tmp0, tmp1); \ + ILVRL_W2_UW(in1, in3, tmp2, tmp3); \ + DOTP_UW2_UD(tmp0, tmp1, mult, mult, out0, out1); \ + DOTP_UW2_UD(tmp2, tmp3, mult, mult, out2, out3); \ + SRAR_D4_UD(out0, out1, out2, out3, shift); \ + DOTP_UW2_UD(out0, out1, scale, scale, out0, out1); \ + DOTP_UW2_UD(out2, out3, scale, scale, out2, out3); \ + SRAR_D4_UD(out0, out1, out2, out3, shift); \ + PCKEV_B2_UB(out1, out0, out3, out2, dst0, dst1); \ +} while (0) + +#define CALC_MULT_FIX2_4(in0, in1, mult, scale, shift, dst) do { \ + v4u32 tmp0, tmp1; \ + v2u64 out0, out1; \ + v16i8 t0, t1; \ + ILVRL_W2_UW(in0, in1, tmp0, tmp1); \ + DOTP_UW2_UD(tmp0, tmp1, mult, mult, out0, out1); \ + SRAR_D2_UD(out0, out1, shift); \ + DOTP_UW2_UD(out0, out1, scale, scale, out0, out1); \ + SRAR_D2_UD(out0, out1, shift); \ + t0 = __msa_pckev_b((v16i8)out1, (v16i8)out0); \ + t1 = __msa_pckev_b(t0, t0); \ + t0 = __msa_pckev_b(t1, t1); \ + dst = __msa_copy_s_w((v4i32)t0, 0); \ +} while (0) + +static WEBP_INLINE void ExportRowExpand_0(const uint32_t* frow, uint8_t* dst, + int length, + WebPRescaler* const wrk) { + const v4u32 scale = (v4u32)__msa_fill_w(wrk->fy_scale); + const v4u32 shift = (v4u32)__msa_fill_w(WEBP_RESCALER_RFIX); + const v4i32 zero = { 0 }; + + while (length >= 16) { + v4u32 src0, src1, src2, src3; + v16u8 out; + LD_UW4(frow, 4, src0, src1, src2, src3); + CALC_MULT_FIX_16(src0, src1, src2, src3, scale, shift, out); + ST_UB(out, dst); + length -= 16; + frow += 16; + dst += 16; + } + if (length > 0) { + int x_out; + if (length >= 12) { + uint32_t val0_m, val1_m, val2_m; + v4u32 src0, src1, src2; + LD_UW3(frow, 4, src0, src1, src2); + CALC_MULT_FIX_4(src0, scale, shift, val0_m); + CALC_MULT_FIX_4(src1, scale, shift, val1_m); + CALC_MULT_FIX_4(src2, scale, shift, val2_m); + SW3(val0_m, val1_m, val2_m, dst, 4); + length -= 12; + frow += 12; + dst += 12; + } else if (length >= 8) { + uint32_t val0_m, val1_m; + v4u32 src0, src1; + LD_UW2(frow, 4, src0, src1); + CALC_MULT_FIX_4(src0, scale, shift, val0_m); + CALC_MULT_FIX_4(src1, scale, shift, val1_m); + SW2(val0_m, val1_m, dst, 4); + length -= 8; + frow += 8; + dst += 8; + } else if (length >= 4) { + uint32_t val0_m; + const v4u32 src0 = LD_UW(frow); + CALC_MULT_FIX_4(src0, scale, shift, val0_m); + SW(val0_m, dst); + length -= 4; + frow += 4; + dst += 4; + } + for (x_out = 0; x_out < length; ++x_out) { + const uint32_t J = frow[x_out]; + const int v = (int)MULT_FIX(J, wrk->fy_scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + } + } +} + +static WEBP_INLINE void ExportRowExpand_1(const uint32_t* frow, uint32_t* irow, + uint8_t* dst, int length, + WebPRescaler* const wrk) { + const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub); + const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B); + const v4i32 B1 = __msa_fill_w(B); + const v4i32 A1 = __msa_fill_w(A); + const v4i32 AB = __msa_ilvr_w(A1, B1); + const v4u32 scale = (v4u32)__msa_fill_w(wrk->fy_scale); + const v4u32 shift = (v4u32)__msa_fill_w(WEBP_RESCALER_RFIX); + + while (length >= 16) { + v4u32 frow0, frow1, frow2, frow3, irow0, irow1, irow2, irow3; + v16u8 t0, t1, t2, t3, t4, t5; + LD_UW4(frow, 4, frow0, frow1, frow2, frow3); + LD_UW4(irow, 4, irow0, irow1, irow2, irow3); + CALC_MULT_FIX2_16(frow0, frow1, irow0, irow1, AB, scale, shift, t0, t1); + CALC_MULT_FIX2_16(frow2, frow3, irow2, irow3, AB, scale, shift, t2, t3); + PCKEV_B2_UB(t1, t0, t3, t2, t4, t5); + t0 = (v16u8)__msa_pckev_b((v16i8)t5, (v16i8)t4); + ST_UB(t0, dst); + frow += 16; + irow += 16; + dst += 16; + length -= 16; + } + if (length > 0) { + int x_out; + if (length >= 12) { + uint32_t val0_m, val1_m, val2_m; + v4u32 frow0, frow1, frow2, irow0, irow1, irow2; + LD_UW3(frow, 4, frow0, frow1, frow2); + LD_UW3(irow, 4, irow0, irow1, irow2); + CALC_MULT_FIX2_4(frow0, irow0, AB, scale, shift, val0_m); + CALC_MULT_FIX2_4(frow1, irow1, AB, scale, shift, val1_m); + CALC_MULT_FIX2_4(frow2, irow2, AB, scale, shift, val2_m); + SW3(val0_m, val1_m, val2_m, dst, 4); + frow += 12; + irow += 12; + dst += 12; + length -= 12; + } else if (length >= 8) { + uint32_t val0_m, val1_m; + v4u32 frow0, frow1, irow0, irow1; + LD_UW2(frow, 4, frow0, frow1); + LD_UW2(irow, 4, irow0, irow1); + CALC_MULT_FIX2_4(frow0, irow0, AB, scale, shift, val0_m); + CALC_MULT_FIX2_4(frow1, irow1, AB, scale, shift, val1_m); + SW2(val0_m, val1_m, dst, 4); + frow += 4; + irow += 4; + dst += 4; + length -= 4; + } else if (length >= 4) { + uint32_t val0_m; + const v4u32 frow0 = LD_UW(frow + 0); + const v4u32 irow0 = LD_UW(irow + 0); + CALC_MULT_FIX2_4(frow0, irow0, AB, scale, shift, val0_m); + SW(val0_m, dst); + frow += 4; + irow += 4; + dst += 4; + length -= 4; + } + for (x_out = 0; x_out < length; ++x_out) { + const uint64_t I = (uint64_t)A * frow[x_out] + + (uint64_t)B * irow[x_out]; + const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX); + const int v = (int)MULT_FIX(J, wrk->fy_scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + } + } +} + +static void RescalerExportRowExpand_MIPSdspR2(WebPRescaler* const wrk) { + uint8_t* dst = wrk->dst; + rescaler_t* irow = wrk->irow; + const int x_out_max = wrk->dst_width * wrk->num_channels; + const rescaler_t* frow = wrk->frow; + assert(!WebPRescalerOutputDone(wrk)); + assert(wrk->y_accum <= 0); + assert(wrk->y_expand); + assert(wrk->y_sub != 0); + if (wrk->y_accum == 0) { + ExportRowExpand_0(frow, dst, x_out_max, wrk); + } else { + ExportRowExpand_1(frow, irow, dst, x_out_max, wrk); + } +} + +#if 0 // disabled for now. TODO(skal): make match the C-code +static WEBP_INLINE void ExportRowShrink_0(const uint32_t* frow, uint32_t* irow, + uint8_t* dst, int length, + const uint32_t yscale, + WebPRescaler* const wrk) { + const v4u32 y_scale = (v4u32)__msa_fill_w(yscale); + const v4u32 fxyscale = (v4u32)__msa_fill_w(wrk->fxy_scale); + const v4u32 shiftval = (v4u32)__msa_fill_w(WEBP_RESCALER_RFIX); + const v4i32 zero = { 0 }; + + while (length >= 16) { + v4u32 src0, src1, src2, src3, frac0, frac1, frac2, frac3; + v16u8 out; + LD_UW4(frow, 4, src0, src1, src2, src3); + CALC_MULT_FIX1_16(src0, src1, src2, src3, y_scale, shiftval, + frac0, frac1, frac2, frac3); + LD_UW4(irow, 4, src0, src1, src2, src3); + SUB4(src0, frac0, src1, frac1, src2, frac2, src3, frac3, + src0, src1, src2, src3); + CALC_MULT_FIX_16(src0, src1, src2, src3, fxyscale, shiftval, out); + ST_UB(out, dst); + ST_UW4(frac0, frac1, frac2, frac3, irow, 4); + frow += 16; + irow += 16; + dst += 16; + length -= 16; + } + if (length > 0) { + int x_out; + if (length >= 12) { + uint32_t val0_m, val1_m, val2_m; + v4u32 src0, src1, src2, frac0, frac1, frac2; + LD_UW3(frow, 4, src0, src1, src2); + CALC_MULT_FIX1_4(src0, y_scale, shiftval, frac0); + CALC_MULT_FIX1_4(src1, y_scale, shiftval, frac1); + CALC_MULT_FIX1_4(src2, y_scale, shiftval, frac2); + LD_UW3(irow, 4, src0, src1, src2); + SUB3(src0, frac0, src1, frac1, src2, frac2, src0, src1, src2); + CALC_MULT_FIX_4(src0, fxyscale, shiftval, val0_m); + CALC_MULT_FIX_4(src1, fxyscale, shiftval, val1_m); + CALC_MULT_FIX_4(src2, fxyscale, shiftval, val2_m); + SW3(val0_m, val1_m, val2_m, dst, 4); + ST_UW3(frac0, frac1, frac2, irow, 4); + frow += 12; + irow += 12; + dst += 12; + length -= 12; + } else if (length >= 8) { + uint32_t val0_m, val1_m; + v4u32 src0, src1, frac0, frac1; + LD_UW2(frow, 4, src0, src1); + CALC_MULT_FIX1_4(src0, y_scale, shiftval, frac0); + CALC_MULT_FIX1_4(src1, y_scale, shiftval, frac1); + LD_UW2(irow, 4, src0, src1); + SUB2(src0, frac0, src1, frac1, src0, src1); + CALC_MULT_FIX_4(src0, fxyscale, shiftval, val0_m); + CALC_MULT_FIX_4(src1, fxyscale, shiftval, val1_m); + SW2(val0_m, val1_m, dst, 4); + ST_UW2(frac0, frac1, irow, 4); + frow += 8; + irow += 8; + dst += 8; + length -= 8; + } else if (length >= 4) { + uint32_t val0_m; + v4u32 frac0; + v4u32 src0 = LD_UW(frow); + CALC_MULT_FIX1_4(src0, y_scale, shiftval, frac0); + src0 = LD_UW(irow); + src0 = src0 - frac0; + CALC_MULT_FIX_4(src0, fxyscale, shiftval, val0_m); + SW(val0_m, dst); + ST_UW(frac0, irow); + frow += 4; + irow += 4; + dst += 4; + length -= 4; + } + for (x_out = 0; x_out < length; ++x_out) { + const uint32_t frac = (uint32_t)MULT_FIX_FLOOR(frow[x_out], yscale); + const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + irow[x_out] = frac; + } + } +} + +static WEBP_INLINE void ExportRowShrink_1(uint32_t* irow, uint8_t* dst, + int length, + WebPRescaler* const wrk) { + const v4u32 scale = (v4u32)__msa_fill_w(wrk->fxy_scale); + const v4u32 shift = (v4u32)__msa_fill_w(WEBP_RESCALER_RFIX); + const v4i32 zero = { 0 }; + + while (length >= 16) { + v4u32 src0, src1, src2, src3; + v16u8 dst0; + LD_UW4(irow, 4, src0, src1, src2, src3); + CALC_MULT_FIX_16(src0, src1, src2, src3, scale, shift, dst0); + ST_UB(dst0, dst); + ST_SW4(zero, zero, zero, zero, irow, 4); + length -= 16; + irow += 16; + dst += 16; + } + if (length > 0) { + int x_out; + if (length >= 12) { + uint32_t val0_m, val1_m, val2_m; + v4u32 src0, src1, src2; + LD_UW3(irow, 4, src0, src1, src2); + CALC_MULT_FIX_4(src0, scale, shift, val0_m); + CALC_MULT_FIX_4(src1, scale, shift, val1_m); + CALC_MULT_FIX_4(src2, scale, shift, val2_m); + SW3(val0_m, val1_m, val2_m, dst, 4); + ST_SW3(zero, zero, zero, irow, 4); + length -= 12; + irow += 12; + dst += 12; + } else if (length >= 8) { + uint32_t val0_m, val1_m; + v4u32 src0, src1; + LD_UW2(irow, 4, src0, src1); + CALC_MULT_FIX_4(src0, scale, shift, val0_m); + CALC_MULT_FIX_4(src1, scale, shift, val1_m); + SW2(val0_m, val1_m, dst, 4); + ST_SW2(zero, zero, irow, 4); + length -= 8; + irow += 8; + dst += 8; + } else if (length >= 4) { + uint32_t val0_m; + const v4u32 src0 = LD_UW(irow + 0); + CALC_MULT_FIX_4(src0, scale, shift, val0_m); + SW(val0_m, dst); + ST_SW(zero, irow); + length -= 4; + irow += 4; + dst += 4; + } + for (x_out = 0; x_out < length; ++x_out) { + const int v = (int)MULT_FIX(irow[x_out], wrk->fxy_scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + irow[x_out] = 0; + } + } +} + +static void RescalerExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) { + uint8_t* dst = wrk->dst; + rescaler_t* irow = wrk->irow; + const int x_out_max = wrk->dst_width * wrk->num_channels; + const rescaler_t* frow = wrk->frow; + const uint32_t yscale = wrk->fy_scale * (-wrk->y_accum); + assert(!WebPRescalerOutputDone(wrk)); + assert(wrk->y_accum <= 0); + assert(!wrk->y_expand); + if (yscale) { + ExportRowShrink_0(frow, irow, dst, x_out_max, yscale, wrk); + } else { + ExportRowShrink_1(irow, dst, x_out_max, wrk); + } +} +#endif // 0 + +//------------------------------------------------------------------------------ +// Entry point + +extern void WebPRescalerDspInitMSA(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMSA(void) { + WebPRescalerExportRowExpand = RescalerExportRowExpand_MIPSdspR2; +// WebPRescalerExportRowShrink = RescalerExportRowShrink_MIPSdspR2; +} + +#else // !WEBP_USE_MSA + +WEBP_DSP_INIT_STUB(WebPRescalerDspInitMSA) + +#endif // WEBP_USE_MSA diff --git a/third-party/webp/libwebp/src/dsp/rescaler_neon.c b/third-party/webp/libwebp/src/dsp/rescaler_neon.c new file mode 100644 index 0000000000..b976a852cf --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/rescaler_neon.c @@ -0,0 +1,192 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// NEON version of rescaling functions +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_NEON) && !defined(WEBP_REDUCE_SIZE) + +#include +#include +#include "src/dsp/neon.h" +#include "src/utils/rescaler_utils.h" + +#define ROUNDER (WEBP_RESCALER_ONE >> 1) +#define MULT_FIX_C(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX) +#define MULT_FIX_FLOOR_C(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX) + +#define LOAD_32x4(SRC, DST) const uint32x4_t DST = vld1q_u32((SRC)) +#define LOAD_32x8(SRC, DST0, DST1) \ + LOAD_32x4(SRC + 0, DST0); \ + LOAD_32x4(SRC + 4, DST1) + +#define STORE_32x8(SRC0, SRC1, DST) do { \ + vst1q_u32((DST) + 0, SRC0); \ + vst1q_u32((DST) + 4, SRC1); \ +} while (0); + +#if (WEBP_RESCALER_RFIX == 32) +#define MAKE_HALF_CST(C) vdupq_n_s32((int32_t)((C) >> 1)) +// note: B is actualy scale>>1. See MAKE_HALF_CST +#define MULT_FIX(A, B) \ + vreinterpretq_u32_s32(vqrdmulhq_s32(vreinterpretq_s32_u32((A)), (B))) +#define MULT_FIX_FLOOR(A, B) \ + vreinterpretq_u32_s32(vqdmulhq_s32(vreinterpretq_s32_u32((A)), (B))) +#else +#error "MULT_FIX/WEBP_RESCALER_RFIX need some more work" +#endif + +static uint32x4_t Interpolate_NEON(const rescaler_t* const frow, + const rescaler_t* const irow, + uint32_t A, uint32_t B) { + LOAD_32x4(frow, A0); + LOAD_32x4(irow, B0); + const uint64x2_t C0 = vmull_n_u32(vget_low_u32(A0), A); + const uint64x2_t C1 = vmull_n_u32(vget_high_u32(A0), A); + const uint64x2_t D0 = vmlal_n_u32(C0, vget_low_u32(B0), B); + const uint64x2_t D1 = vmlal_n_u32(C1, vget_high_u32(B0), B); + const uint32x4_t E = vcombine_u32( + vrshrn_n_u64(D0, WEBP_RESCALER_RFIX), + vrshrn_n_u64(D1, WEBP_RESCALER_RFIX)); + return E; +} + +static void RescalerExportRowExpand_NEON(WebPRescaler* const wrk) { + int x_out; + uint8_t* const dst = wrk->dst; + rescaler_t* const irow = wrk->irow; + const int x_out_max = wrk->dst_width * wrk->num_channels; + const int max_span = x_out_max & ~7; + const rescaler_t* const frow = wrk->frow; + const uint32_t fy_scale = wrk->fy_scale; + const int32x4_t fy_scale_half = MAKE_HALF_CST(fy_scale); + assert(!WebPRescalerOutputDone(wrk)); + assert(wrk->y_accum <= 0); + assert(wrk->y_expand); + assert(wrk->y_sub != 0); + if (wrk->y_accum == 0) { + for (x_out = 0; x_out < max_span; x_out += 8) { + LOAD_32x4(frow + x_out + 0, A0); + LOAD_32x4(frow + x_out + 4, A1); + const uint32x4_t B0 = MULT_FIX(A0, fy_scale_half); + const uint32x4_t B1 = MULT_FIX(A1, fy_scale_half); + const uint16x4_t C0 = vmovn_u32(B0); + const uint16x4_t C1 = vmovn_u32(B1); + const uint8x8_t D = vqmovn_u16(vcombine_u16(C0, C1)); + vst1_u8(dst + x_out, D); + } + for (; x_out < x_out_max; ++x_out) { + const uint32_t J = frow[x_out]; + const int v = (int)MULT_FIX_C(J, fy_scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + } + } else { + const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub); + const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B); + for (x_out = 0; x_out < max_span; x_out += 8) { + const uint32x4_t C0 = + Interpolate_NEON(frow + x_out + 0, irow + x_out + 0, A, B); + const uint32x4_t C1 = + Interpolate_NEON(frow + x_out + 4, irow + x_out + 4, A, B); + const uint32x4_t D0 = MULT_FIX(C0, fy_scale_half); + const uint32x4_t D1 = MULT_FIX(C1, fy_scale_half); + const uint16x4_t E0 = vmovn_u32(D0); + const uint16x4_t E1 = vmovn_u32(D1); + const uint8x8_t F = vqmovn_u16(vcombine_u16(E0, E1)); + vst1_u8(dst + x_out, F); + } + for (; x_out < x_out_max; ++x_out) { + const uint64_t I = (uint64_t)A * frow[x_out] + + (uint64_t)B * irow[x_out]; + const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX); + const int v = (int)MULT_FIX_C(J, fy_scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + } + } +} + +static void RescalerExportRowShrink_NEON(WebPRescaler* const wrk) { + int x_out; + uint8_t* const dst = wrk->dst; + rescaler_t* const irow = wrk->irow; + const int x_out_max = wrk->dst_width * wrk->num_channels; + const int max_span = x_out_max & ~7; + const rescaler_t* const frow = wrk->frow; + const uint32_t yscale = wrk->fy_scale * (-wrk->y_accum); + const uint32_t fxy_scale = wrk->fxy_scale; + const uint32x4_t zero = vdupq_n_u32(0); + const int32x4_t yscale_half = MAKE_HALF_CST(yscale); + const int32x4_t fxy_scale_half = MAKE_HALF_CST(fxy_scale); + assert(!WebPRescalerOutputDone(wrk)); + assert(wrk->y_accum <= 0); + assert(!wrk->y_expand); + if (yscale) { + for (x_out = 0; x_out < max_span; x_out += 8) { + LOAD_32x8(frow + x_out, in0, in1); + LOAD_32x8(irow + x_out, in2, in3); + const uint32x4_t A0 = MULT_FIX_FLOOR(in0, yscale_half); + const uint32x4_t A1 = MULT_FIX_FLOOR(in1, yscale_half); + const uint32x4_t B0 = vqsubq_u32(in2, A0); + const uint32x4_t B1 = vqsubq_u32(in3, A1); + const uint32x4_t C0 = MULT_FIX(B0, fxy_scale_half); + const uint32x4_t C1 = MULT_FIX(B1, fxy_scale_half); + const uint16x4_t D0 = vmovn_u32(C0); + const uint16x4_t D1 = vmovn_u32(C1); + const uint8x8_t E = vqmovn_u16(vcombine_u16(D0, D1)); + vst1_u8(dst + x_out, E); + STORE_32x8(A0, A1, irow + x_out); + } + for (; x_out < x_out_max; ++x_out) { + const uint32_t frac = (uint32_t)MULT_FIX_FLOOR_C(frow[x_out], yscale); + const int v = (int)MULT_FIX_C(irow[x_out] - frac, fxy_scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + irow[x_out] = frac; // new fractional start + } + } else { + for (x_out = 0; x_out < max_span; x_out += 8) { + LOAD_32x8(irow + x_out, in0, in1); + const uint32x4_t A0 = MULT_FIX(in0, fxy_scale_half); + const uint32x4_t A1 = MULT_FIX(in1, fxy_scale_half); + const uint16x4_t B0 = vmovn_u32(A0); + const uint16x4_t B1 = vmovn_u32(A1); + const uint8x8_t C = vqmovn_u16(vcombine_u16(B0, B1)); + vst1_u8(dst + x_out, C); + STORE_32x8(zero, zero, irow + x_out); + } + for (; x_out < x_out_max; ++x_out) { + const int v = (int)MULT_FIX_C(irow[x_out], fxy_scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + irow[x_out] = 0; + } + } +} + +#undef MULT_FIX_FLOOR_C +#undef MULT_FIX_C +#undef MULT_FIX_FLOOR +#undef MULT_FIX +#undef ROUNDER + +//------------------------------------------------------------------------------ + +extern void WebPRescalerDspInitNEON(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitNEON(void) { + WebPRescalerExportRowExpand = RescalerExportRowExpand_NEON; + WebPRescalerExportRowShrink = RescalerExportRowShrink_NEON; +} + +#else // !WEBP_USE_NEON + +WEBP_DSP_INIT_STUB(WebPRescalerDspInitNEON) + +#endif // WEBP_USE_NEON diff --git a/third-party/webp/libwebp/src/dsp/rescaler_sse2.c b/third-party/webp/libwebp/src/dsp/rescaler_sse2.c new file mode 100644 index 0000000000..3f18e94e93 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/rescaler_sse2.c @@ -0,0 +1,366 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE2 Rescaling functions +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE2) && !defined(WEBP_REDUCE_SIZE) +#include + +#include +#include "src/utils/rescaler_utils.h" +#include "src/utils/utils.h" + +//------------------------------------------------------------------------------ +// Implementations of critical functions ImportRow / ExportRow + +#define ROUNDER (WEBP_RESCALER_ONE >> 1) +#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX) +#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX) + +// input: 8 bytes ABCDEFGH -> output: A0E0B0F0C0G0D0H0 +static void LoadTwoPixels_SSE2(const uint8_t* const src, __m128i* out) { + const __m128i zero = _mm_setzero_si128(); + const __m128i A = _mm_loadl_epi64((const __m128i*)(src)); // ABCDEFGH + const __m128i B = _mm_unpacklo_epi8(A, zero); // A0B0C0D0E0F0G0H0 + const __m128i C = _mm_srli_si128(B, 8); // E0F0G0H0 + *out = _mm_unpacklo_epi16(B, C); +} + +// input: 8 bytes ABCDEFGH -> output: A0B0C0D0E0F0G0H0 +static void LoadEightPixels_SSE2(const uint8_t* const src, __m128i* out) { + const __m128i zero = _mm_setzero_si128(); + const __m128i A = _mm_loadl_epi64((const __m128i*)(src)); // ABCDEFGH + *out = _mm_unpacklo_epi8(A, zero); +} + +static void RescalerImportRowExpand_SSE2(WebPRescaler* const wrk, + const uint8_t* src) { + rescaler_t* frow = wrk->frow; + const rescaler_t* const frow_end = frow + wrk->dst_width * wrk->num_channels; + const int x_add = wrk->x_add; + int accum = x_add; + __m128i cur_pixels; + + // SSE2 implementation only works with 16b signed arithmetic at max. + if (wrk->src_width < 8 || accum >= (1 << 15)) { + WebPRescalerImportRowExpand_C(wrk, src); + return; + } + + assert(!WebPRescalerInputDone(wrk)); + assert(wrk->x_expand); + if (wrk->num_channels == 4) { + LoadTwoPixels_SSE2(src, &cur_pixels); + src += 4; + while (1) { + const __m128i mult = _mm_set1_epi32(((x_add - accum) << 16) | accum); + const __m128i out = _mm_madd_epi16(cur_pixels, mult); + _mm_storeu_si128((__m128i*)frow, out); + frow += 4; + if (frow >= frow_end) break; + accum -= wrk->x_sub; + if (accum < 0) { + LoadTwoPixels_SSE2(src, &cur_pixels); + src += 4; + accum += x_add; + } + } + } else { + int left; + const uint8_t* const src_limit = src + wrk->src_width - 8; + LoadEightPixels_SSE2(src, &cur_pixels); + src += 7; + left = 7; + while (1) { + const __m128i mult = _mm_cvtsi32_si128(((x_add - accum) << 16) | accum); + const __m128i out = _mm_madd_epi16(cur_pixels, mult); + assert(sizeof(*frow) == sizeof(uint32_t)); + WebPInt32ToMem((uint8_t*)frow, _mm_cvtsi128_si32(out)); + frow += 1; + if (frow >= frow_end) break; + accum -= wrk->x_sub; + if (accum < 0) { + if (--left) { + cur_pixels = _mm_srli_si128(cur_pixels, 2); + } else if (src <= src_limit) { + LoadEightPixels_SSE2(src, &cur_pixels); + src += 7; + left = 7; + } else { // tail + cur_pixels = _mm_srli_si128(cur_pixels, 2); + cur_pixels = _mm_insert_epi16(cur_pixels, src[1], 1); + src += 1; + left = 1; + } + accum += x_add; + } + } + } + assert(accum == 0); +} + +static void RescalerImportRowShrink_SSE2(WebPRescaler* const wrk, + const uint8_t* src) { + const int x_sub = wrk->x_sub; + int accum = 0; + const __m128i zero = _mm_setzero_si128(); + const __m128i mult0 = _mm_set1_epi16(x_sub); + const __m128i mult1 = _mm_set1_epi32(wrk->fx_scale); + const __m128i rounder = _mm_set_epi32(0, ROUNDER, 0, ROUNDER); + __m128i sum = zero; + rescaler_t* frow = wrk->frow; + const rescaler_t* const frow_end = wrk->frow + 4 * wrk->dst_width; + + if (wrk->num_channels != 4 || wrk->x_add > (x_sub << 7)) { + WebPRescalerImportRowShrink_C(wrk, src); + return; + } + assert(!WebPRescalerInputDone(wrk)); + assert(!wrk->x_expand); + + for (; frow < frow_end; frow += 4) { + __m128i base = zero; + accum += wrk->x_add; + while (accum > 0) { + const __m128i A = _mm_cvtsi32_si128(WebPMemToInt32(src)); + src += 4; + base = _mm_unpacklo_epi8(A, zero); + // To avoid overflow, we need: base * x_add / x_sub < 32768 + // => x_add < x_sub << 7. That's a 1/128 reduction ratio limit. + sum = _mm_add_epi16(sum, base); + accum -= x_sub; + } + { // Emit next horizontal pixel. + const __m128i mult = _mm_set1_epi16(-accum); + const __m128i frac0 = _mm_mullo_epi16(base, mult); // 16b x 16b -> 32b + const __m128i frac1 = _mm_mulhi_epu16(base, mult); + const __m128i frac = _mm_unpacklo_epi16(frac0, frac1); // frac is 32b + const __m128i A0 = _mm_mullo_epi16(sum, mult0); + const __m128i A1 = _mm_mulhi_epu16(sum, mult0); + const __m128i B0 = _mm_unpacklo_epi16(A0, A1); // sum * x_sub + const __m128i frow_out = _mm_sub_epi32(B0, frac); // sum * x_sub - frac + const __m128i D0 = _mm_srli_epi64(frac, 32); + const __m128i D1 = _mm_mul_epu32(frac, mult1); // 32b x 16b -> 64b + const __m128i D2 = _mm_mul_epu32(D0, mult1); + const __m128i E1 = _mm_add_epi64(D1, rounder); + const __m128i E2 = _mm_add_epi64(D2, rounder); + const __m128i F1 = _mm_shuffle_epi32(E1, 1 | (3 << 2)); + const __m128i F2 = _mm_shuffle_epi32(E2, 1 | (3 << 2)); + const __m128i G = _mm_unpacklo_epi32(F1, F2); + sum = _mm_packs_epi32(G, zero); + _mm_storeu_si128((__m128i*)frow, frow_out); + } + } + assert(accum == 0); +} + +//------------------------------------------------------------------------------ +// Row export + +// load *src as epi64, multiply by mult and store result in [out0 ... out3] +static WEBP_INLINE void LoadDispatchAndMult_SSE2(const rescaler_t* const src, + const __m128i* const mult, + __m128i* const out0, + __m128i* const out1, + __m128i* const out2, + __m128i* const out3) { + const __m128i A0 = _mm_loadu_si128((const __m128i*)(src + 0)); + const __m128i A1 = _mm_loadu_si128((const __m128i*)(src + 4)); + const __m128i A2 = _mm_srli_epi64(A0, 32); + const __m128i A3 = _mm_srli_epi64(A1, 32); + if (mult != NULL) { + *out0 = _mm_mul_epu32(A0, *mult); + *out1 = _mm_mul_epu32(A1, *mult); + *out2 = _mm_mul_epu32(A2, *mult); + *out3 = _mm_mul_epu32(A3, *mult); + } else { + *out0 = A0; + *out1 = A1; + *out2 = A2; + *out3 = A3; + } +} + +static WEBP_INLINE void ProcessRow_SSE2(const __m128i* const A0, + const __m128i* const A1, + const __m128i* const A2, + const __m128i* const A3, + const __m128i* const mult, + uint8_t* const dst) { + const __m128i rounder = _mm_set_epi32(0, ROUNDER, 0, ROUNDER); + const __m128i mask = _mm_set_epi32(~0, 0, ~0, 0); + const __m128i B0 = _mm_mul_epu32(*A0, *mult); + const __m128i B1 = _mm_mul_epu32(*A1, *mult); + const __m128i B2 = _mm_mul_epu32(*A2, *mult); + const __m128i B3 = _mm_mul_epu32(*A3, *mult); + const __m128i C0 = _mm_add_epi64(B0, rounder); + const __m128i C1 = _mm_add_epi64(B1, rounder); + const __m128i C2 = _mm_add_epi64(B2, rounder); + const __m128i C3 = _mm_add_epi64(B3, rounder); + const __m128i D0 = _mm_srli_epi64(C0, WEBP_RESCALER_RFIX); + const __m128i D1 = _mm_srli_epi64(C1, WEBP_RESCALER_RFIX); +#if (WEBP_RESCALER_RFIX < 32) + const __m128i D2 = + _mm_and_si128(_mm_slli_epi64(C2, 32 - WEBP_RESCALER_RFIX), mask); + const __m128i D3 = + _mm_and_si128(_mm_slli_epi64(C3, 32 - WEBP_RESCALER_RFIX), mask); +#else + const __m128i D2 = _mm_and_si128(C2, mask); + const __m128i D3 = _mm_and_si128(C3, mask); +#endif + const __m128i E0 = _mm_or_si128(D0, D2); + const __m128i E1 = _mm_or_si128(D1, D3); + const __m128i F = _mm_packs_epi32(E0, E1); + const __m128i G = _mm_packus_epi16(F, F); + _mm_storel_epi64((__m128i*)dst, G); +} + +static void RescalerExportRowExpand_SSE2(WebPRescaler* const wrk) { + int x_out; + uint8_t* const dst = wrk->dst; + rescaler_t* const irow = wrk->irow; + const int x_out_max = wrk->dst_width * wrk->num_channels; + const rescaler_t* const frow = wrk->frow; + const __m128i mult = _mm_set_epi32(0, wrk->fy_scale, 0, wrk->fy_scale); + + assert(!WebPRescalerOutputDone(wrk)); + assert(wrk->y_accum <= 0 && wrk->y_sub + wrk->y_accum >= 0); + assert(wrk->y_expand); + if (wrk->y_accum == 0) { + for (x_out = 0; x_out + 8 <= x_out_max; x_out += 8) { + __m128i A0, A1, A2, A3; + LoadDispatchAndMult_SSE2(frow + x_out, NULL, &A0, &A1, &A2, &A3); + ProcessRow_SSE2(&A0, &A1, &A2, &A3, &mult, dst + x_out); + } + for (; x_out < x_out_max; ++x_out) { + const uint32_t J = frow[x_out]; + const int v = (int)MULT_FIX(J, wrk->fy_scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + } + } else { + const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub); + const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B); + const __m128i mA = _mm_set_epi32(0, A, 0, A); + const __m128i mB = _mm_set_epi32(0, B, 0, B); + const __m128i rounder = _mm_set_epi32(0, ROUNDER, 0, ROUNDER); + for (x_out = 0; x_out + 8 <= x_out_max; x_out += 8) { + __m128i A0, A1, A2, A3, B0, B1, B2, B3; + LoadDispatchAndMult_SSE2(frow + x_out, &mA, &A0, &A1, &A2, &A3); + LoadDispatchAndMult_SSE2(irow + x_out, &mB, &B0, &B1, &B2, &B3); + { + const __m128i C0 = _mm_add_epi64(A0, B0); + const __m128i C1 = _mm_add_epi64(A1, B1); + const __m128i C2 = _mm_add_epi64(A2, B2); + const __m128i C3 = _mm_add_epi64(A3, B3); + const __m128i D0 = _mm_add_epi64(C0, rounder); + const __m128i D1 = _mm_add_epi64(C1, rounder); + const __m128i D2 = _mm_add_epi64(C2, rounder); + const __m128i D3 = _mm_add_epi64(C3, rounder); + const __m128i E0 = _mm_srli_epi64(D0, WEBP_RESCALER_RFIX); + const __m128i E1 = _mm_srli_epi64(D1, WEBP_RESCALER_RFIX); + const __m128i E2 = _mm_srli_epi64(D2, WEBP_RESCALER_RFIX); + const __m128i E3 = _mm_srli_epi64(D3, WEBP_RESCALER_RFIX); + ProcessRow_SSE2(&E0, &E1, &E2, &E3, &mult, dst + x_out); + } + } + for (; x_out < x_out_max; ++x_out) { + const uint64_t I = (uint64_t)A * frow[x_out] + + (uint64_t)B * irow[x_out]; + const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX); + const int v = (int)MULT_FIX(J, wrk->fy_scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + } + } +} + +static void RescalerExportRowShrink_SSE2(WebPRescaler* const wrk) { + int x_out; + uint8_t* const dst = wrk->dst; + rescaler_t* const irow = wrk->irow; + const int x_out_max = wrk->dst_width * wrk->num_channels; + const rescaler_t* const frow = wrk->frow; + const uint32_t yscale = wrk->fy_scale * (-wrk->y_accum); + assert(!WebPRescalerOutputDone(wrk)); + assert(wrk->y_accum <= 0); + assert(!wrk->y_expand); + if (yscale) { + const int scale_xy = wrk->fxy_scale; + const __m128i mult_xy = _mm_set_epi32(0, scale_xy, 0, scale_xy); + const __m128i mult_y = _mm_set_epi32(0, yscale, 0, yscale); + for (x_out = 0; x_out + 8 <= x_out_max; x_out += 8) { + __m128i A0, A1, A2, A3, B0, B1, B2, B3; + LoadDispatchAndMult_SSE2(irow + x_out, NULL, &A0, &A1, &A2, &A3); + LoadDispatchAndMult_SSE2(frow + x_out, &mult_y, &B0, &B1, &B2, &B3); + { + const __m128i D0 = _mm_srli_epi64(B0, WEBP_RESCALER_RFIX); // = frac + const __m128i D1 = _mm_srli_epi64(B1, WEBP_RESCALER_RFIX); + const __m128i D2 = _mm_srli_epi64(B2, WEBP_RESCALER_RFIX); + const __m128i D3 = _mm_srli_epi64(B3, WEBP_RESCALER_RFIX); + const __m128i E0 = _mm_sub_epi64(A0, D0); // irow[x] - frac + const __m128i E1 = _mm_sub_epi64(A1, D1); + const __m128i E2 = _mm_sub_epi64(A2, D2); + const __m128i E3 = _mm_sub_epi64(A3, D3); + const __m128i F2 = _mm_slli_epi64(D2, 32); + const __m128i F3 = _mm_slli_epi64(D3, 32); + const __m128i G0 = _mm_or_si128(D0, F2); + const __m128i G1 = _mm_or_si128(D1, F3); + _mm_storeu_si128((__m128i*)(irow + x_out + 0), G0); + _mm_storeu_si128((__m128i*)(irow + x_out + 4), G1); + ProcessRow_SSE2(&E0, &E1, &E2, &E3, &mult_xy, dst + x_out); + } + } + for (; x_out < x_out_max; ++x_out) { + const uint32_t frac = (int)MULT_FIX_FLOOR(frow[x_out], yscale); + const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + irow[x_out] = frac; // new fractional start + } + } else { + const uint32_t scale = wrk->fxy_scale; + const __m128i mult = _mm_set_epi32(0, scale, 0, scale); + const __m128i zero = _mm_setzero_si128(); + for (x_out = 0; x_out + 8 <= x_out_max; x_out += 8) { + __m128i A0, A1, A2, A3; + LoadDispatchAndMult_SSE2(irow + x_out, NULL, &A0, &A1, &A2, &A3); + _mm_storeu_si128((__m128i*)(irow + x_out + 0), zero); + _mm_storeu_si128((__m128i*)(irow + x_out + 4), zero); + ProcessRow_SSE2(&A0, &A1, &A2, &A3, &mult, dst + x_out); + } + for (; x_out < x_out_max; ++x_out) { + const int v = (int)MULT_FIX(irow[x_out], scale); + dst[x_out] = (v > 255) ? 255u : (uint8_t)v; + irow[x_out] = 0; + } + } +} + +#undef MULT_FIX_FLOOR +#undef MULT_FIX +#undef ROUNDER + +//------------------------------------------------------------------------------ + +extern void WebPRescalerDspInitSSE2(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitSSE2(void) { + WebPRescalerImportRowExpand = RescalerImportRowExpand_SSE2; + WebPRescalerImportRowShrink = RescalerImportRowShrink_SSE2; + WebPRescalerExportRowExpand = RescalerExportRowExpand_SSE2; + WebPRescalerExportRowShrink = RescalerExportRowShrink_SSE2; +} + +#else // !WEBP_USE_SSE2 + +WEBP_DSP_INIT_STUB(WebPRescalerDspInitSSE2) + +#endif // WEBP_USE_SSE2 diff --git a/third-party/webp/libwebp/src/dsp/ssim.c b/third-party/webp/libwebp/src/dsp/ssim.c new file mode 100644 index 0000000000..9a1341ed95 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/ssim.c @@ -0,0 +1,160 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// distortion calculation +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include // for abs() + +#include "src/dsp/dsp.h" + +#if !defined(WEBP_REDUCE_SIZE) + +//------------------------------------------------------------------------------ +// SSIM / PSNR + +// hat-shaped filter. Sum of coefficients is equal to 16. +static const uint32_t kWeight[2 * VP8_SSIM_KERNEL + 1] = { + 1, 2, 3, 4, 3, 2, 1 +}; +static const uint32_t kWeightSum = 16 * 16; // sum{kWeight}^2 + +static WEBP_INLINE double SSIMCalculation( + const VP8DistoStats* const stats, uint32_t N /*num samples*/) { + const uint32_t w2 = N * N; + const uint32_t C1 = 20 * w2; + const uint32_t C2 = 60 * w2; + const uint32_t C3 = 8 * 8 * w2; // 'dark' limit ~= 6 + const uint64_t xmxm = (uint64_t)stats->xm * stats->xm; + const uint64_t ymym = (uint64_t)stats->ym * stats->ym; + if (xmxm + ymym >= C3) { + const int64_t xmym = (int64_t)stats->xm * stats->ym; + const int64_t sxy = (int64_t)stats->xym * N - xmym; // can be negative + const uint64_t sxx = (uint64_t)stats->xxm * N - xmxm; + const uint64_t syy = (uint64_t)stats->yym * N - ymym; + // we descale by 8 to prevent overflow during the fnum/fden multiply. + const uint64_t num_S = (2 * (uint64_t)(sxy < 0 ? 0 : sxy) + C2) >> 8; + const uint64_t den_S = (sxx + syy + C2) >> 8; + const uint64_t fnum = (2 * xmym + C1) * num_S; + const uint64_t fden = (xmxm + ymym + C1) * den_S; + const double r = (double)fnum / fden; + assert(r >= 0. && r <= 1.0); + return r; + } + return 1.; // area is too dark to contribute meaningfully +} + +double VP8SSIMFromStats(const VP8DistoStats* const stats) { + return SSIMCalculation(stats, kWeightSum); +} + +double VP8SSIMFromStatsClipped(const VP8DistoStats* const stats) { + return SSIMCalculation(stats, stats->w); +} + +static double SSIMGetClipped_C(const uint8_t* src1, int stride1, + const uint8_t* src2, int stride2, + int xo, int yo, int W, int H) { + VP8DistoStats stats = { 0, 0, 0, 0, 0, 0 }; + const int ymin = (yo - VP8_SSIM_KERNEL < 0) ? 0 : yo - VP8_SSIM_KERNEL; + const int ymax = (yo + VP8_SSIM_KERNEL > H - 1) ? H - 1 + : yo + VP8_SSIM_KERNEL; + const int xmin = (xo - VP8_SSIM_KERNEL < 0) ? 0 : xo - VP8_SSIM_KERNEL; + const int xmax = (xo + VP8_SSIM_KERNEL > W - 1) ? W - 1 + : xo + VP8_SSIM_KERNEL; + int x, y; + src1 += ymin * stride1; + src2 += ymin * stride2; + for (y = ymin; y <= ymax; ++y, src1 += stride1, src2 += stride2) { + for (x = xmin; x <= xmax; ++x) { + const uint32_t w = kWeight[VP8_SSIM_KERNEL + x - xo] + * kWeight[VP8_SSIM_KERNEL + y - yo]; + const uint32_t s1 = src1[x]; + const uint32_t s2 = src2[x]; + stats.w += w; + stats.xm += w * s1; + stats.ym += w * s2; + stats.xxm += w * s1 * s1; + stats.xym += w * s1 * s2; + stats.yym += w * s2 * s2; + } + } + return VP8SSIMFromStatsClipped(&stats); +} + +static double SSIMGet_C(const uint8_t* src1, int stride1, + const uint8_t* src2, int stride2) { + VP8DistoStats stats = { 0, 0, 0, 0, 0, 0 }; + int x, y; + for (y = 0; y <= 2 * VP8_SSIM_KERNEL; ++y, src1 += stride1, src2 += stride2) { + for (x = 0; x <= 2 * VP8_SSIM_KERNEL; ++x) { + const uint32_t w = kWeight[x] * kWeight[y]; + const uint32_t s1 = src1[x]; + const uint32_t s2 = src2[x]; + stats.xm += w * s1; + stats.ym += w * s2; + stats.xxm += w * s1 * s1; + stats.xym += w * s1 * s2; + stats.yym += w * s2 * s2; + } + } + return VP8SSIMFromStats(&stats); +} + +#endif // !defined(WEBP_REDUCE_SIZE) + +//------------------------------------------------------------------------------ + +#if !defined(WEBP_DISABLE_STATS) +static uint32_t AccumulateSSE_C(const uint8_t* src1, + const uint8_t* src2, int len) { + int i; + uint32_t sse2 = 0; + assert(len <= 65535); // to ensure that accumulation fits within uint32_t + for (i = 0; i < len; ++i) { + const int32_t diff = src1[i] - src2[i]; + sse2 += diff * diff; + } + return sse2; +} +#endif + +//------------------------------------------------------------------------------ + +#if !defined(WEBP_REDUCE_SIZE) +VP8SSIMGetFunc VP8SSIMGet; +VP8SSIMGetClippedFunc VP8SSIMGetClipped; +#endif +#if !defined(WEBP_DISABLE_STATS) +VP8AccumulateSSEFunc VP8AccumulateSSE; +#endif + +extern VP8CPUInfo VP8GetCPUInfo; +extern void VP8SSIMDspInitSSE2(void); + +WEBP_DSP_INIT_FUNC(VP8SSIMDspInit) { +#if !defined(WEBP_REDUCE_SIZE) + VP8SSIMGetClipped = SSIMGetClipped_C; + VP8SSIMGet = SSIMGet_C; +#endif + +#if !defined(WEBP_DISABLE_STATS) + VP8AccumulateSSE = AccumulateSSE_C; +#endif + + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_HAVE_SSE2) + if (VP8GetCPUInfo(kSSE2)) { + VP8SSIMDspInitSSE2(); + } +#endif + } +} diff --git a/third-party/webp/libwebp/src/dsp/ssim_sse2.c b/third-party/webp/libwebp/src/dsp/ssim_sse2.c new file mode 100644 index 0000000000..1dcb0eb0ec --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/ssim_sse2.c @@ -0,0 +1,165 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE2 version of distortion calculation +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE2) + +#include +#include + +#include "src/dsp/common_sse2.h" + +#if !defined(WEBP_DISABLE_STATS) + +// Helper function +static WEBP_INLINE void SubtractAndSquare_SSE2(const __m128i a, const __m128i b, + __m128i* const sum) { + // take abs(a-b) in 8b + const __m128i a_b = _mm_subs_epu8(a, b); + const __m128i b_a = _mm_subs_epu8(b, a); + const __m128i abs_a_b = _mm_or_si128(a_b, b_a); + // zero-extend to 16b + const __m128i zero = _mm_setzero_si128(); + const __m128i C0 = _mm_unpacklo_epi8(abs_a_b, zero); + const __m128i C1 = _mm_unpackhi_epi8(abs_a_b, zero); + // multiply with self + const __m128i sum1 = _mm_madd_epi16(C0, C0); + const __m128i sum2 = _mm_madd_epi16(C1, C1); + *sum = _mm_add_epi32(sum1, sum2); +} + +//------------------------------------------------------------------------------ +// SSIM / PSNR entry point + +static uint32_t AccumulateSSE_SSE2(const uint8_t* src1, + const uint8_t* src2, int len) { + int i = 0; + uint32_t sse2 = 0; + if (len >= 16) { + const int limit = len - 32; + int32_t tmp[4]; + __m128i sum1; + __m128i sum = _mm_setzero_si128(); + __m128i a0 = _mm_loadu_si128((const __m128i*)&src1[i]); + __m128i b0 = _mm_loadu_si128((const __m128i*)&src2[i]); + i += 16; + while (i <= limit) { + const __m128i a1 = _mm_loadu_si128((const __m128i*)&src1[i]); + const __m128i b1 = _mm_loadu_si128((const __m128i*)&src2[i]); + __m128i sum2; + i += 16; + SubtractAndSquare_SSE2(a0, b0, &sum1); + sum = _mm_add_epi32(sum, sum1); + a0 = _mm_loadu_si128((const __m128i*)&src1[i]); + b0 = _mm_loadu_si128((const __m128i*)&src2[i]); + i += 16; + SubtractAndSquare_SSE2(a1, b1, &sum2); + sum = _mm_add_epi32(sum, sum2); + } + SubtractAndSquare_SSE2(a0, b0, &sum1); + sum = _mm_add_epi32(sum, sum1); + _mm_storeu_si128((__m128i*)tmp, sum); + sse2 += (tmp[3] + tmp[2] + tmp[1] + tmp[0]); + } + + for (; i < len; ++i) { + const int32_t diff = src1[i] - src2[i]; + sse2 += diff * diff; + } + return sse2; +} +#endif // !defined(WEBP_DISABLE_STATS) + +#if !defined(WEBP_REDUCE_SIZE) + +static uint32_t HorizontalAdd16b_SSE2(const __m128i* const m) { + uint16_t tmp[8]; + const __m128i a = _mm_srli_si128(*m, 8); + const __m128i b = _mm_add_epi16(*m, a); + _mm_storeu_si128((__m128i*)tmp, b); + return (uint32_t)tmp[3] + tmp[2] + tmp[1] + tmp[0]; +} + +static uint32_t HorizontalAdd32b_SSE2(const __m128i* const m) { + const __m128i a = _mm_srli_si128(*m, 8); + const __m128i b = _mm_add_epi32(*m, a); + const __m128i c = _mm_add_epi32(b, _mm_srli_si128(b, 4)); + return (uint32_t)_mm_cvtsi128_si32(c); +} + +static const uint16_t kWeight[] = { 1, 2, 3, 4, 3, 2, 1, 0 }; + +#define ACCUMULATE_ROW(WEIGHT) do { \ + /* compute row weight (Wx * Wy) */ \ + const __m128i Wy = _mm_set1_epi16((WEIGHT)); \ + const __m128i W = _mm_mullo_epi16(Wx, Wy); \ + /* process 8 bytes at a time (7 bytes, actually) */ \ + const __m128i a0 = _mm_loadl_epi64((const __m128i*)src1); \ + const __m128i b0 = _mm_loadl_epi64((const __m128i*)src2); \ + /* convert to 16b and multiply by weight */ \ + const __m128i a1 = _mm_unpacklo_epi8(a0, zero); \ + const __m128i b1 = _mm_unpacklo_epi8(b0, zero); \ + const __m128i wa1 = _mm_mullo_epi16(a1, W); \ + const __m128i wb1 = _mm_mullo_epi16(b1, W); \ + /* accumulate */ \ + xm = _mm_add_epi16(xm, wa1); \ + ym = _mm_add_epi16(ym, wb1); \ + xxm = _mm_add_epi32(xxm, _mm_madd_epi16(a1, wa1)); \ + xym = _mm_add_epi32(xym, _mm_madd_epi16(a1, wb1)); \ + yym = _mm_add_epi32(yym, _mm_madd_epi16(b1, wb1)); \ + src1 += stride1; \ + src2 += stride2; \ +} while (0) + +static double SSIMGet_SSE2(const uint8_t* src1, int stride1, + const uint8_t* src2, int stride2) { + VP8DistoStats stats; + const __m128i zero = _mm_setzero_si128(); + __m128i xm = zero, ym = zero; // 16b accums + __m128i xxm = zero, yym = zero, xym = zero; // 32b accum + const __m128i Wx = _mm_loadu_si128((const __m128i*)kWeight); + assert(2 * VP8_SSIM_KERNEL + 1 == 7); + ACCUMULATE_ROW(1); + ACCUMULATE_ROW(2); + ACCUMULATE_ROW(3); + ACCUMULATE_ROW(4); + ACCUMULATE_ROW(3); + ACCUMULATE_ROW(2); + ACCUMULATE_ROW(1); + stats.xm = HorizontalAdd16b_SSE2(&xm); + stats.ym = HorizontalAdd16b_SSE2(&ym); + stats.xxm = HorizontalAdd32b_SSE2(&xxm); + stats.xym = HorizontalAdd32b_SSE2(&xym); + stats.yym = HorizontalAdd32b_SSE2(&yym); + return VP8SSIMFromStats(&stats); +} + +#endif // !defined(WEBP_REDUCE_SIZE) + +extern void VP8SSIMDspInitSSE2(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8SSIMDspInitSSE2(void) { +#if !defined(WEBP_DISABLE_STATS) + VP8AccumulateSSE = AccumulateSSE_SSE2; +#endif +#if !defined(WEBP_REDUCE_SIZE) + VP8SSIMGet = SSIMGet_SSE2; +#endif +} + +#else // !WEBP_USE_SSE2 + +WEBP_DSP_INIT_STUB(VP8SSIMDspInitSSE2) + +#endif // WEBP_USE_SSE2 diff --git a/third-party/webp/libwebp/src/dsp/upsampling.c b/third-party/webp/libwebp/src/dsp/upsampling.c new file mode 100644 index 0000000000..983b9c42d3 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/upsampling.c @@ -0,0 +1,328 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// YUV to RGB upsampling functions. +// +// Author: somnath@google.com (Somnath Banerjee) + +#include "src/dsp/dsp.h" +#include "src/dsp/yuv.h" + +#include + +//------------------------------------------------------------------------------ +// Fancy upsampler + +#ifdef FANCY_UPSAMPLING + +// Fancy upsampling functions to convert YUV to RGB +WebPUpsampleLinePairFunc WebPUpsamplers[MODE_LAST]; + +// Given samples laid out in a square as: +// [a b] +// [c d] +// we interpolate u/v as: +// ([9*a + 3*b + 3*c + d 3*a + 9*b + 3*c + d] + [8 8]) / 16 +// ([3*a + b + 9*c + 3*d a + 3*b + 3*c + 9*d] [8 8]) / 16 + +// We process u and v together stashed into 32bit (16bit each). +#define LOAD_UV(u, v) ((u) | ((v) << 16)) + +#define UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \ +static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \ + const uint8_t* top_u, const uint8_t* top_v, \ + const uint8_t* cur_u, const uint8_t* cur_v, \ + uint8_t* top_dst, uint8_t* bottom_dst, int len) { \ + int x; \ + const int last_pixel_pair = (len - 1) >> 1; \ + uint32_t tl_uv = LOAD_UV(top_u[0], top_v[0]); /* top-left sample */ \ + uint32_t l_uv = LOAD_UV(cur_u[0], cur_v[0]); /* left-sample */ \ + assert(top_y != NULL); \ + { \ + const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \ + FUNC(top_y[0], uv0 & 0xff, (uv0 >> 16), top_dst); \ + } \ + if (bottom_y != NULL) { \ + const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \ + FUNC(bottom_y[0], uv0 & 0xff, (uv0 >> 16), bottom_dst); \ + } \ + for (x = 1; x <= last_pixel_pair; ++x) { \ + const uint32_t t_uv = LOAD_UV(top_u[x], top_v[x]); /* top sample */ \ + const uint32_t uv = LOAD_UV(cur_u[x], cur_v[x]); /* sample */ \ + /* precompute invariant values associated with first and second diagonals*/\ + const uint32_t avg = tl_uv + t_uv + l_uv + uv + 0x00080008u; \ + const uint32_t diag_12 = (avg + 2 * (t_uv + l_uv)) >> 3; \ + const uint32_t diag_03 = (avg + 2 * (tl_uv + uv)) >> 3; \ + { \ + const uint32_t uv0 = (diag_12 + tl_uv) >> 1; \ + const uint32_t uv1 = (diag_03 + t_uv) >> 1; \ + FUNC(top_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \ + top_dst + (2 * x - 1) * (XSTEP)); \ + FUNC(top_y[2 * x - 0], uv1 & 0xff, (uv1 >> 16), \ + top_dst + (2 * x - 0) * (XSTEP)); \ + } \ + if (bottom_y != NULL) { \ + const uint32_t uv0 = (diag_03 + l_uv) >> 1; \ + const uint32_t uv1 = (diag_12 + uv) >> 1; \ + FUNC(bottom_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \ + bottom_dst + (2 * x - 1) * (XSTEP)); \ + FUNC(bottom_y[2 * x + 0], uv1 & 0xff, (uv1 >> 16), \ + bottom_dst + (2 * x + 0) * (XSTEP)); \ + } \ + tl_uv = t_uv; \ + l_uv = uv; \ + } \ + if (!(len & 1)) { \ + { \ + const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \ + FUNC(top_y[len - 1], uv0 & 0xff, (uv0 >> 16), \ + top_dst + (len - 1) * (XSTEP)); \ + } \ + if (bottom_y != NULL) { \ + const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \ + FUNC(bottom_y[len - 1], uv0 & 0xff, (uv0 >> 16), \ + bottom_dst + (len - 1) * (XSTEP)); \ + } \ + } \ +} + +// All variants implemented. +#if !WEBP_NEON_OMIT_C_CODE +UPSAMPLE_FUNC(UpsampleRgbaLinePair_C, VP8YuvToRgba, 4) +UPSAMPLE_FUNC(UpsampleBgraLinePair_C, VP8YuvToBgra, 4) +#if !defined(WEBP_REDUCE_CSP) +UPSAMPLE_FUNC(UpsampleArgbLinePair_C, VP8YuvToArgb, 4) +UPSAMPLE_FUNC(UpsampleRgbLinePair_C, VP8YuvToRgb, 3) +UPSAMPLE_FUNC(UpsampleBgrLinePair_C, VP8YuvToBgr, 3) +UPSAMPLE_FUNC(UpsampleRgba4444LinePair_C, VP8YuvToRgba4444, 2) +UPSAMPLE_FUNC(UpsampleRgb565LinePair_C, VP8YuvToRgb565, 2) +#else +static void EmptyUpsampleFunc(const uint8_t* top_y, const uint8_t* bottom_y, + const uint8_t* top_u, const uint8_t* top_v, + const uint8_t* cur_u, const uint8_t* cur_v, + uint8_t* top_dst, uint8_t* bottom_dst, int len) { + (void)top_y; + (void)bottom_y; + (void)top_u; + (void)top_v; + (void)cur_u; + (void)cur_v; + (void)top_dst; + (void)bottom_dst; + (void)len; + assert(0); // COLORSPACE SUPPORT NOT COMPILED +} +#define UpsampleArgbLinePair_C EmptyUpsampleFunc +#define UpsampleRgbLinePair_C EmptyUpsampleFunc +#define UpsampleBgrLinePair_C EmptyUpsampleFunc +#define UpsampleRgba4444LinePair_C EmptyUpsampleFunc +#define UpsampleRgb565LinePair_C EmptyUpsampleFunc +#endif // WEBP_REDUCE_CSP + +#endif + +#undef LOAD_UV +#undef UPSAMPLE_FUNC + +#endif // FANCY_UPSAMPLING + +//------------------------------------------------------------------------------ + +#if !defined(FANCY_UPSAMPLING) +#define DUAL_SAMPLE_FUNC(FUNC_NAME, FUNC) \ +static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bot_y, \ + const uint8_t* top_u, const uint8_t* top_v, \ + const uint8_t* bot_u, const uint8_t* bot_v, \ + uint8_t* top_dst, uint8_t* bot_dst, int len) { \ + const int half_len = len >> 1; \ + int x; \ + assert(top_dst != NULL); \ + { \ + for (x = 0; x < half_len; ++x) { \ + FUNC(top_y[2 * x + 0], top_u[x], top_v[x], top_dst + 8 * x + 0); \ + FUNC(top_y[2 * x + 1], top_u[x], top_v[x], top_dst + 8 * x + 4); \ + } \ + if (len & 1) FUNC(top_y[2 * x + 0], top_u[x], top_v[x], top_dst + 8 * x); \ + } \ + if (bot_dst != NULL) { \ + for (x = 0; x < half_len; ++x) { \ + FUNC(bot_y[2 * x + 0], bot_u[x], bot_v[x], bot_dst + 8 * x + 0); \ + FUNC(bot_y[2 * x + 1], bot_u[x], bot_v[x], bot_dst + 8 * x + 4); \ + } \ + if (len & 1) FUNC(bot_y[2 * x + 0], bot_u[x], bot_v[x], bot_dst + 8 * x); \ + } \ +} + +DUAL_SAMPLE_FUNC(DualLineSamplerBGRA, VP8YuvToBgra) +DUAL_SAMPLE_FUNC(DualLineSamplerARGB, VP8YuvToArgb) +#undef DUAL_SAMPLE_FUNC + +#endif // !FANCY_UPSAMPLING + +WebPUpsampleLinePairFunc WebPGetLinePairConverter(int alpha_is_last) { + WebPInitUpsamplers(); +#ifdef FANCY_UPSAMPLING + return WebPUpsamplers[alpha_is_last ? MODE_BGRA : MODE_ARGB]; +#else + return (alpha_is_last ? DualLineSamplerBGRA : DualLineSamplerARGB); +#endif +} + +//------------------------------------------------------------------------------ +// YUV444 converter + +#define YUV444_FUNC(FUNC_NAME, FUNC, XSTEP) \ +extern void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ + uint8_t* dst, int len); \ +void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ + uint8_t* dst, int len) { \ + int i; \ + for (i = 0; i < len; ++i) FUNC(y[i], u[i], v[i], &dst[i * (XSTEP)]); \ +} + +YUV444_FUNC(WebPYuv444ToRgba_C, VP8YuvToRgba, 4) +YUV444_FUNC(WebPYuv444ToBgra_C, VP8YuvToBgra, 4) +#if !defined(WEBP_REDUCE_CSP) +YUV444_FUNC(WebPYuv444ToRgb_C, VP8YuvToRgb, 3) +YUV444_FUNC(WebPYuv444ToBgr_C, VP8YuvToBgr, 3) +YUV444_FUNC(WebPYuv444ToArgb_C, VP8YuvToArgb, 4) +YUV444_FUNC(WebPYuv444ToRgba4444_C, VP8YuvToRgba4444, 2) +YUV444_FUNC(WebPYuv444ToRgb565_C, VP8YuvToRgb565, 2) +#else +static void EmptyYuv444Func(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len) { + (void)y; + (void)u; + (void)v; + (void)dst; + (void)len; +} +#define WebPYuv444ToRgb_C EmptyYuv444Func +#define WebPYuv444ToBgr_C EmptyYuv444Func +#define WebPYuv444ToArgb_C EmptyYuv444Func +#define WebPYuv444ToRgba4444_C EmptyYuv444Func +#define WebPYuv444ToRgb565_C EmptyYuv444Func +#endif // WEBP_REDUCE_CSP + +#undef YUV444_FUNC + +WebPYUV444Converter WebPYUV444Converters[MODE_LAST]; + +extern VP8CPUInfo VP8GetCPUInfo; +extern void WebPInitYUV444ConvertersMIPSdspR2(void); +extern void WebPInitYUV444ConvertersSSE2(void); +extern void WebPInitYUV444ConvertersSSE41(void); + +WEBP_DSP_INIT_FUNC(WebPInitYUV444Converters) { + WebPYUV444Converters[MODE_RGBA] = WebPYuv444ToRgba_C; + WebPYUV444Converters[MODE_BGRA] = WebPYuv444ToBgra_C; + WebPYUV444Converters[MODE_RGB] = WebPYuv444ToRgb_C; + WebPYUV444Converters[MODE_BGR] = WebPYuv444ToBgr_C; + WebPYUV444Converters[MODE_ARGB] = WebPYuv444ToArgb_C; + WebPYUV444Converters[MODE_RGBA_4444] = WebPYuv444ToRgba4444_C; + WebPYUV444Converters[MODE_RGB_565] = WebPYuv444ToRgb565_C; + WebPYUV444Converters[MODE_rgbA] = WebPYuv444ToRgba_C; + WebPYUV444Converters[MODE_bgrA] = WebPYuv444ToBgra_C; + WebPYUV444Converters[MODE_Argb] = WebPYuv444ToArgb_C; + WebPYUV444Converters[MODE_rgbA_4444] = WebPYuv444ToRgba4444_C; + + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_HAVE_SSE2) + if (VP8GetCPUInfo(kSSE2)) { + WebPInitYUV444ConvertersSSE2(); + } +#endif +#if defined(WEBP_HAVE_SSE41) + if (VP8GetCPUInfo(kSSE4_1)) { + WebPInitYUV444ConvertersSSE41(); + } +#endif +#if defined(WEBP_USE_MIPS_DSP_R2) + if (VP8GetCPUInfo(kMIPSdspR2)) { + WebPInitYUV444ConvertersMIPSdspR2(); + } +#endif + } +} + +//------------------------------------------------------------------------------ +// Main calls + +extern void WebPInitUpsamplersSSE2(void); +extern void WebPInitUpsamplersSSE41(void); +extern void WebPInitUpsamplersNEON(void); +extern void WebPInitUpsamplersMIPSdspR2(void); +extern void WebPInitUpsamplersMSA(void); + +WEBP_DSP_INIT_FUNC(WebPInitUpsamplers) { +#ifdef FANCY_UPSAMPLING +#if !WEBP_NEON_OMIT_C_CODE + WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair_C; + WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair_C; + WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair_C; + WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair_C; + WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair_C; + WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair_C; + WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair_C; + WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair_C; + WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair_C; + WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair_C; + WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair_C; +#endif + + // If defined, use CPUInfo() to overwrite some pointers with faster versions. + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_HAVE_SSE2) + if (VP8GetCPUInfo(kSSE2)) { + WebPInitUpsamplersSSE2(); + } +#endif +#if defined(WEBP_HAVE_SSE41) + if (VP8GetCPUInfo(kSSE4_1)) { + WebPInitUpsamplersSSE41(); + } +#endif +#if defined(WEBP_USE_MIPS_DSP_R2) + if (VP8GetCPUInfo(kMIPSdspR2)) { + WebPInitUpsamplersMIPSdspR2(); + } +#endif +#if defined(WEBP_USE_MSA) + if (VP8GetCPUInfo(kMSA)) { + WebPInitUpsamplersMSA(); + } +#endif + } + +#if defined(WEBP_HAVE_NEON) + if (WEBP_NEON_OMIT_C_CODE || + (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) { + WebPInitUpsamplersNEON(); + } +#endif + + assert(WebPUpsamplers[MODE_RGBA] != NULL); + assert(WebPUpsamplers[MODE_BGRA] != NULL); + assert(WebPUpsamplers[MODE_rgbA] != NULL); + assert(WebPUpsamplers[MODE_bgrA] != NULL); +#if !defined(WEBP_REDUCE_CSP) || !WEBP_NEON_OMIT_C_CODE + assert(WebPUpsamplers[MODE_RGB] != NULL); + assert(WebPUpsamplers[MODE_BGR] != NULL); + assert(WebPUpsamplers[MODE_ARGB] != NULL); + assert(WebPUpsamplers[MODE_RGBA_4444] != NULL); + assert(WebPUpsamplers[MODE_RGB_565] != NULL); + assert(WebPUpsamplers[MODE_Argb] != NULL); + assert(WebPUpsamplers[MODE_rgbA_4444] != NULL); +#endif + +#endif // FANCY_UPSAMPLING +} + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/src/dsp/upsampling_mips_dsp_r2.c b/third-party/webp/libwebp/src/dsp/upsampling_mips_dsp_r2.c new file mode 100644 index 0000000000..10d499d771 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/upsampling_mips_dsp_r2.c @@ -0,0 +1,291 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// YUV to RGB upsampling functions. +// +// Author(s): Branimir Vasic (branimir.vasic@imgtec.com) +// Djordje Pesut (djordje.pesut@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MIPS_DSP_R2) + +#include +#include "src/dsp/yuv.h" + +#define YUV_TO_RGB(Y, U, V, R, G, B) do { \ + const int t1 = MultHi(Y, 19077); \ + const int t2 = MultHi(V, 13320); \ + R = MultHi(V, 26149); \ + G = MultHi(U, 6419); \ + B = MultHi(U, 33050); \ + R = t1 + R; \ + G = t1 - G; \ + B = t1 + B; \ + R = R - 14234; \ + G = G - t2 + 8708; \ + B = B - 17685; \ + __asm__ volatile ( \ + "shll_s.w %[" #R "], %[" #R "], 17 \n\t" \ + "shll_s.w %[" #G "], %[" #G "], 17 \n\t" \ + "shll_s.w %[" #B "], %[" #B "], 17 \n\t" \ + "precrqu_s.qb.ph %[" #R "], %[" #R "], $zero \n\t" \ + "precrqu_s.qb.ph %[" #G "], %[" #G "], $zero \n\t" \ + "precrqu_s.qb.ph %[" #B "], %[" #B "], $zero \n\t" \ + "srl %[" #R "], %[" #R "], 24 \n\t" \ + "srl %[" #G "], %[" #G "], 24 \n\t" \ + "srl %[" #B "], %[" #B "], 24 \n\t" \ + : [R]"+r"(R), [G]"+r"(G), [B]"+r"(B) \ + : \ + ); \ + } while (0) + +#if !defined(WEBP_REDUCE_CSP) +static WEBP_INLINE void YuvToRgb(int y, int u, int v, uint8_t* const rgb) { + int r, g, b; + YUV_TO_RGB(y, u, v, r, g, b); + rgb[0] = r; + rgb[1] = g; + rgb[2] = b; +} +static WEBP_INLINE void YuvToBgr(int y, int u, int v, uint8_t* const bgr) { + int r, g, b; + YUV_TO_RGB(y, u, v, r, g, b); + bgr[0] = b; + bgr[1] = g; + bgr[2] = r; +} +static WEBP_INLINE void YuvToRgb565(int y, int u, int v, uint8_t* const rgb) { + int r, g, b; + YUV_TO_RGB(y, u, v, r, g, b); + { + const int rg = (r & 0xf8) | (g >> 5); + const int gb = ((g << 3) & 0xe0) | (b >> 3); +#if (WEBP_SWAP_16BIT_CSP == 1) + rgb[0] = gb; + rgb[1] = rg; +#else + rgb[0] = rg; + rgb[1] = gb; +#endif + } +} +static WEBP_INLINE void YuvToRgba4444(int y, int u, int v, + uint8_t* const argb) { + int r, g, b; + YUV_TO_RGB(y, u, v, r, g, b); + { + const int rg = (r & 0xf0) | (g >> 4); + const int ba = (b & 0xf0) | 0x0f; // overwrite the lower 4 bits +#if (WEBP_SWAP_16BIT_CSP == 1) + argb[0] = ba; + argb[1] = rg; +#else + argb[0] = rg; + argb[1] = ba; +#endif + } +} +#endif // WEBP_REDUCE_CSP + +//----------------------------------------------------------------------------- +// Alpha handling variants + +#if !defined(WEBP_REDUCE_CSP) +static WEBP_INLINE void YuvToArgb(uint8_t y, uint8_t u, uint8_t v, + uint8_t* const argb) { + int r, g, b; + YUV_TO_RGB(y, u, v, r, g, b); + argb[0] = 0xff; + argb[1] = r; + argb[2] = g; + argb[3] = b; +} +#endif // WEBP_REDUCE_CSP +static WEBP_INLINE void YuvToBgra(uint8_t y, uint8_t u, uint8_t v, + uint8_t* const bgra) { + int r, g, b; + YUV_TO_RGB(y, u, v, r, g, b); + bgra[0] = b; + bgra[1] = g; + bgra[2] = r; + bgra[3] = 0xff; +} +static WEBP_INLINE void YuvToRgba(uint8_t y, uint8_t u, uint8_t v, + uint8_t* const rgba) { + int r, g, b; + YUV_TO_RGB(y, u, v, r, g, b); + rgba[0] = r; + rgba[1] = g; + rgba[2] = b; + rgba[3] = 0xff; +} + +//------------------------------------------------------------------------------ +// Fancy upsampler + +#ifdef FANCY_UPSAMPLING + +// Given samples laid out in a square as: +// [a b] +// [c d] +// we interpolate u/v as: +// ([9*a + 3*b + 3*c + d 3*a + 9*b + 3*c + d] + [8 8]) / 16 +// ([3*a + b + 9*c + 3*d a + 3*b + 3*c + 9*d] [8 8]) / 16 + +// We process u and v together stashed into 32bit (16bit each). +#define LOAD_UV(u, v) ((u) | ((v) << 16)) + +#define UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \ +static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \ + const uint8_t* top_u, const uint8_t* top_v, \ + const uint8_t* cur_u, const uint8_t* cur_v, \ + uint8_t* top_dst, uint8_t* bottom_dst, int len) { \ + int x; \ + const int last_pixel_pair = (len - 1) >> 1; \ + uint32_t tl_uv = LOAD_UV(top_u[0], top_v[0]); /* top-left sample */ \ + uint32_t l_uv = LOAD_UV(cur_u[0], cur_v[0]); /* left-sample */ \ + assert(top_y != NULL); \ + { \ + const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \ + FUNC(top_y[0], uv0 & 0xff, (uv0 >> 16), top_dst); \ + } \ + if (bottom_y != NULL) { \ + const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \ + FUNC(bottom_y[0], uv0 & 0xff, (uv0 >> 16), bottom_dst); \ + } \ + for (x = 1; x <= last_pixel_pair; ++x) { \ + const uint32_t t_uv = LOAD_UV(top_u[x], top_v[x]); /* top sample */ \ + const uint32_t uv = LOAD_UV(cur_u[x], cur_v[x]); /* sample */ \ + /* precompute invariant values associated with first and second diagonals*/\ + const uint32_t avg = tl_uv + t_uv + l_uv + uv + 0x00080008u; \ + const uint32_t diag_12 = (avg + 2 * (t_uv + l_uv)) >> 3; \ + const uint32_t diag_03 = (avg + 2 * (tl_uv + uv)) >> 3; \ + { \ + const uint32_t uv0 = (diag_12 + tl_uv) >> 1; \ + const uint32_t uv1 = (diag_03 + t_uv) >> 1; \ + FUNC(top_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \ + top_dst + (2 * x - 1) * XSTEP); \ + FUNC(top_y[2 * x - 0], uv1 & 0xff, (uv1 >> 16), \ + top_dst + (2 * x - 0) * XSTEP); \ + } \ + if (bottom_y != NULL) { \ + const uint32_t uv0 = (diag_03 + l_uv) >> 1; \ + const uint32_t uv1 = (diag_12 + uv) >> 1; \ + FUNC(bottom_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \ + bottom_dst + (2 * x - 1) * XSTEP); \ + FUNC(bottom_y[2 * x + 0], uv1 & 0xff, (uv1 >> 16), \ + bottom_dst + (2 * x + 0) * XSTEP); \ + } \ + tl_uv = t_uv; \ + l_uv = uv; \ + } \ + if (!(len & 1)) { \ + { \ + const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \ + FUNC(top_y[len - 1], uv0 & 0xff, (uv0 >> 16), \ + top_dst + (len - 1) * XSTEP); \ + } \ + if (bottom_y != NULL) { \ + const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \ + FUNC(bottom_y[len - 1], uv0 & 0xff, (uv0 >> 16), \ + bottom_dst + (len - 1) * XSTEP); \ + } \ + } \ +} + +// All variants implemented. +UPSAMPLE_FUNC(UpsampleRgbaLinePair, YuvToRgba, 4) +UPSAMPLE_FUNC(UpsampleBgraLinePair, YuvToBgra, 4) +#if !defined(WEBP_REDUCE_CSP) +UPSAMPLE_FUNC(UpsampleRgbLinePair, YuvToRgb, 3) +UPSAMPLE_FUNC(UpsampleBgrLinePair, YuvToBgr, 3) +UPSAMPLE_FUNC(UpsampleArgbLinePair, YuvToArgb, 4) +UPSAMPLE_FUNC(UpsampleRgba4444LinePair, YuvToRgba4444, 2) +UPSAMPLE_FUNC(UpsampleRgb565LinePair, YuvToRgb565, 2) +#endif // WEBP_REDUCE_CSP + +#undef LOAD_UV +#undef UPSAMPLE_FUNC + +//------------------------------------------------------------------------------ +// Entry point + +extern void WebPInitUpsamplersMIPSdspR2(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplersMIPSdspR2(void) { + WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair; + WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair; + WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair; + WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair; +#if !defined(WEBP_REDUCE_CSP) + WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair; + WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair; + WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair; + WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair; + WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair; + WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair; + WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair; +#endif // WEBP_REDUCE_CSP +} + +#endif // FANCY_UPSAMPLING + +//------------------------------------------------------------------------------ +// YUV444 converter + +#define YUV444_FUNC(FUNC_NAME, FUNC, XSTEP) \ +static void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ + uint8_t* dst, int len) { \ + int i; \ + for (i = 0; i < len; ++i) FUNC(y[i], u[i], v[i], &dst[i * XSTEP]); \ +} + +YUV444_FUNC(Yuv444ToRgba, YuvToRgba, 4) +YUV444_FUNC(Yuv444ToBgra, YuvToBgra, 4) +#if !defined(WEBP_REDUCE_CSP) +YUV444_FUNC(Yuv444ToRgb, YuvToRgb, 3) +YUV444_FUNC(Yuv444ToBgr, YuvToBgr, 3) +YUV444_FUNC(Yuv444ToArgb, YuvToArgb, 4) +YUV444_FUNC(Yuv444ToRgba4444, YuvToRgba4444, 2) +YUV444_FUNC(Yuv444ToRgb565, YuvToRgb565, 2) +#endif // WEBP_REDUCE_CSP + +#undef YUV444_FUNC + +//------------------------------------------------------------------------------ +// Entry point + +extern void WebPInitYUV444ConvertersMIPSdspR2(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444ConvertersMIPSdspR2(void) { + WebPYUV444Converters[MODE_RGBA] = Yuv444ToRgba; + WebPYUV444Converters[MODE_BGRA] = Yuv444ToBgra; + WebPYUV444Converters[MODE_rgbA] = Yuv444ToRgba; + WebPYUV444Converters[MODE_bgrA] = Yuv444ToBgra; +#if !defined(WEBP_REDUCE_CSP) + WebPYUV444Converters[MODE_RGB] = Yuv444ToRgb; + WebPYUV444Converters[MODE_BGR] = Yuv444ToBgr; + WebPYUV444Converters[MODE_ARGB] = Yuv444ToArgb; + WebPYUV444Converters[MODE_RGBA_4444] = Yuv444ToRgba4444; + WebPYUV444Converters[MODE_RGB_565] = Yuv444ToRgb565; + WebPYUV444Converters[MODE_Argb] = Yuv444ToArgb; + WebPYUV444Converters[MODE_rgbA_4444] = Yuv444ToRgba4444; +#endif // WEBP_REDUCE_CSP +} + +#else // !WEBP_USE_MIPS_DSP_R2 + +WEBP_DSP_INIT_STUB(WebPInitYUV444ConvertersMIPSdspR2) + +#endif // WEBP_USE_MIPS_DSP_R2 + +#if !(defined(FANCY_UPSAMPLING) && defined(WEBP_USE_MIPS_DSP_R2)) +WEBP_DSP_INIT_STUB(WebPInitUpsamplersMIPSdspR2) +#endif diff --git a/third-party/webp/libwebp/src/dsp/upsampling_msa.c b/third-party/webp/libwebp/src/dsp/upsampling_msa.c new file mode 100644 index 0000000000..f2e03e85e9 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/upsampling_msa.c @@ -0,0 +1,688 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MSA version of YUV to RGB upsampling functions. +// +// Author: Prashant Patil (prashant.patil@imgtec.com) + +#include +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MSA) + +#include "src/dsp/msa_macro.h" +#include "src/dsp/yuv.h" + +#ifdef FANCY_UPSAMPLING + +#define ILVR_UW2(in, out0, out1) do { \ + const v8i16 t0 = (v8i16)__msa_ilvr_b((v16i8)zero, (v16i8)in); \ + out0 = (v4u32)__msa_ilvr_h((v8i16)zero, t0); \ + out1 = (v4u32)__msa_ilvl_h((v8i16)zero, t0); \ +} while (0) + +#define ILVRL_UW4(in, out0, out1, out2, out3) do { \ + v16u8 t0, t1; \ + ILVRL_B2_UB(zero, in, t0, t1); \ + ILVRL_H2_UW(zero, t0, out0, out1); \ + ILVRL_H2_UW(zero, t1, out2, out3); \ +} while (0) + +#define MULTHI_16(in0, in1, in2, in3, cnst, out0, out1) do { \ + const v4i32 const0 = (v4i32)__msa_fill_w(cnst * 256); \ + v4u32 temp0, temp1, temp2, temp3; \ + MUL4(in0, const0, in1, const0, in2, const0, in3, const0, \ + temp0, temp1, temp2, temp3); \ + PCKOD_H2_UH(temp1, temp0, temp3, temp2, out0, out1); \ +} while (0) + +#define MULTHI_8(in0, in1, cnst, out0) do { \ + const v4i32 const0 = (v4i32)__msa_fill_w(cnst * 256); \ + v4u32 temp0, temp1; \ + MUL2(in0, const0, in1, const0, temp0, temp1); \ + out0 = (v8u16)__msa_pckod_h((v8i16)temp1, (v8i16)temp0); \ +} while (0) + +#define CALC_R16(y0, y1, v0, v1, dst) do { \ + const v8i16 const_a = (v8i16)__msa_fill_h(14234); \ + const v8i16 a0 = __msa_adds_s_h((v8i16)y0, (v8i16)v0); \ + const v8i16 a1 = __msa_adds_s_h((v8i16)y1, (v8i16)v1); \ + v8i16 b0 = __msa_subs_s_h(a0, const_a); \ + v8i16 b1 = __msa_subs_s_h(a1, const_a); \ + SRAI_H2_SH(b0, b1, 6); \ + CLIP_SH2_0_255(b0, b1); \ + dst = (v16u8)__msa_pckev_b((v16i8)b1, (v16i8)b0); \ +} while (0) + +#define CALC_R8(y0, v0, dst) do { \ + const v8i16 const_a = (v8i16)__msa_fill_h(14234); \ + const v8i16 a0 = __msa_adds_s_h((v8i16)y0, (v8i16)v0); \ + v8i16 b0 = __msa_subs_s_h(a0, const_a); \ + b0 = SRAI_H(b0, 6); \ + CLIP_SH_0_255(b0); \ + dst = (v16u8)__msa_pckev_b((v16i8)b0, (v16i8)b0); \ +} while (0) + +#define CALC_G16(y0, y1, u0, u1, v0, v1, dst) do { \ + const v8i16 const_a = (v8i16)__msa_fill_h(8708); \ + v8i16 a0 = __msa_subs_s_h((v8i16)y0, (v8i16)u0); \ + v8i16 a1 = __msa_subs_s_h((v8i16)y1, (v8i16)u1); \ + const v8i16 b0 = __msa_subs_s_h(a0, (v8i16)v0); \ + const v8i16 b1 = __msa_subs_s_h(a1, (v8i16)v1); \ + a0 = __msa_adds_s_h(b0, const_a); \ + a1 = __msa_adds_s_h(b1, const_a); \ + SRAI_H2_SH(a0, a1, 6); \ + CLIP_SH2_0_255(a0, a1); \ + dst = (v16u8)__msa_pckev_b((v16i8)a1, (v16i8)a0); \ +} while (0) + +#define CALC_G8(y0, u0, v0, dst) do { \ + const v8i16 const_a = (v8i16)__msa_fill_h(8708); \ + v8i16 a0 = __msa_subs_s_h((v8i16)y0, (v8i16)u0); \ + const v8i16 b0 = __msa_subs_s_h(a0, (v8i16)v0); \ + a0 = __msa_adds_s_h(b0, const_a); \ + a0 = SRAI_H(a0, 6); \ + CLIP_SH_0_255(a0); \ + dst = (v16u8)__msa_pckev_b((v16i8)a0, (v16i8)a0); \ +} while (0) + +#define CALC_B16(y0, y1, u0, u1, dst) do { \ + const v8u16 const_a = (v8u16)__msa_fill_h(17685); \ + const v8u16 a0 = __msa_adds_u_h((v8u16)y0, u0); \ + const v8u16 a1 = __msa_adds_u_h((v8u16)y1, u1); \ + v8u16 b0 = __msa_subs_u_h(a0, const_a); \ + v8u16 b1 = __msa_subs_u_h(a1, const_a); \ + SRAI_H2_UH(b0, b1, 6); \ + CLIP_UH2_0_255(b0, b1); \ + dst = (v16u8)__msa_pckev_b((v16i8)b1, (v16i8)b0); \ +} while (0) + +#define CALC_B8(y0, u0, dst) do { \ + const v8u16 const_a = (v8u16)__msa_fill_h(17685); \ + const v8u16 a0 = __msa_adds_u_h((v8u16)y0, u0); \ + v8u16 b0 = __msa_subs_u_h(a0, const_a); \ + b0 = SRAI_H(b0, 6); \ + CLIP_UH_0_255(b0); \ + dst = (v16u8)__msa_pckev_b((v16i8)b0, (v16i8)b0); \ +} while (0) + +#define CALC_RGB16(y, u, v, R, G, B) do { \ + const v16u8 zero = { 0 }; \ + v8u16 y0, y1, u0, u1, v0, v1; \ + v4u32 p0, p1, p2, p3; \ + const v16u8 in_y = LD_UB(y); \ + const v16u8 in_u = LD_UB(u); \ + const v16u8 in_v = LD_UB(v); \ + ILVRL_UW4(in_y, p0, p1, p2, p3); \ + MULTHI_16(p0, p1, p2, p3, 19077, y0, y1); \ + ILVRL_UW4(in_v, p0, p1, p2, p3); \ + MULTHI_16(p0, p1, p2, p3, 26149, v0, v1); \ + CALC_R16(y0, y1, v0, v1, R); \ + MULTHI_16(p0, p1, p2, p3, 13320, v0, v1); \ + ILVRL_UW4(in_u, p0, p1, p2, p3); \ + MULTHI_16(p0, p1, p2, p3, 6419, u0, u1); \ + CALC_G16(y0, y1, u0, u1, v0, v1, G); \ + MULTHI_16(p0, p1, p2, p3, 33050, u0, u1); \ + CALC_B16(y0, y1, u0, u1, B); \ +} while (0) + +#define CALC_RGB8(y, u, v, R, G, B) do { \ + const v16u8 zero = { 0 }; \ + v8u16 y0, u0, v0; \ + v4u32 p0, p1; \ + const v16u8 in_y = LD_UB(y); \ + const v16u8 in_u = LD_UB(u); \ + const v16u8 in_v = LD_UB(v); \ + ILVR_UW2(in_y, p0, p1); \ + MULTHI_8(p0, p1, 19077, y0); \ + ILVR_UW2(in_v, p0, p1); \ + MULTHI_8(p0, p1, 26149, v0); \ + CALC_R8(y0, v0, R); \ + MULTHI_8(p0, p1, 13320, v0); \ + ILVR_UW2(in_u, p0, p1); \ + MULTHI_8(p0, p1, 6419, u0); \ + CALC_G8(y0, u0, v0, G); \ + MULTHI_8(p0, p1, 33050, u0); \ + CALC_B8(y0, u0, B); \ +} while (0) + +#define STORE16_3(a0, a1, a2, dst) do { \ + const v16u8 mask0 = { 0, 1, 16, 2, 3, 17, 4, 5, 18, 6, 7, 19, \ + 8, 9, 20, 10 }; \ + const v16u8 mask1 = { 0, 21, 1, 2, 22, 3, 4, 23, 5, 6, 24, 7, \ + 8, 25, 9, 10 }; \ + const v16u8 mask2 = { 26, 0, 1, 27, 2, 3, 28, 4, 5, 29, 6, 7, \ + 30, 8, 9, 31 }; \ + v16u8 out0, out1, out2, tmp0, tmp1, tmp2; \ + ILVRL_B2_UB(a1, a0, tmp0, tmp1); \ + out0 = VSHF_UB(tmp0, a2, mask0); \ + tmp2 = SLDI_UB(tmp1, tmp0, 11); \ + out1 = VSHF_UB(tmp2, a2, mask1); \ + tmp2 = SLDI_UB(tmp1, tmp1, 6); \ + out2 = VSHF_UB(tmp2, a2, mask2); \ + ST_UB(out0, dst + 0); \ + ST_UB(out1, dst + 16); \ + ST_UB(out2, dst + 32); \ +} while (0) + +#define STORE8_3(a0, a1, a2, dst) do { \ + int64_t out_m; \ + const v16u8 mask0 = { 0, 1, 16, 2, 3, 17, 4, 5, 18, 6, 7, 19, \ + 8, 9, 20, 10 }; \ + const v16u8 mask1 = { 11, 21, 12, 13, 22, 14, 15, 23, \ + 255, 255, 255, 255, 255, 255, 255, 255 }; \ + const v16u8 tmp0 = (v16u8)__msa_ilvr_b((v16i8)a1, (v16i8)a0); \ + v16u8 out0, out1; \ + VSHF_B2_UB(tmp0, a2, tmp0, a2, mask0, mask1, out0, out1); \ + ST_UB(out0, dst); \ + out_m = __msa_copy_s_d((v2i64)out1, 0); \ + SD(out_m, dst + 16); \ +} while (0) + +#define STORE16_4(a0, a1, a2, a3, dst) do { \ + v16u8 tmp0, tmp1, tmp2, tmp3; \ + v16u8 out0, out1, out2, out3; \ + ILVRL_B2_UB(a1, a0, tmp0, tmp1); \ + ILVRL_B2_UB(a3, a2, tmp2, tmp3); \ + ILVRL_H2_UB(tmp2, tmp0, out0, out1); \ + ILVRL_H2_UB(tmp3, tmp1, out2, out3); \ + ST_UB(out0, dst + 0); \ + ST_UB(out1, dst + 16); \ + ST_UB(out2, dst + 32); \ + ST_UB(out3, dst + 48); \ +} while (0) + +#define STORE8_4(a0, a1, a2, a3, dst) do { \ + v16u8 tmp0, tmp1, tmp2, tmp3; \ + ILVR_B2_UB(a1, a0, a3, a2, tmp0, tmp1); \ + ILVRL_H2_UB(tmp1, tmp0, tmp2, tmp3); \ + ST_UB(tmp2, dst + 0); \ + ST_UB(tmp3, dst + 16); \ +} while (0) + +#define STORE2_16(a0, a1, dst) do { \ + v16u8 out0, out1; \ + ILVRL_B2_UB(a1, a0, out0, out1); \ + ST_UB(out0, dst + 0); \ + ST_UB(out1, dst + 16); \ +} while (0) + +#define STORE2_8(a0, a1, dst) do { \ + const v16u8 out0 = (v16u8)__msa_ilvr_b((v16i8)a1, (v16i8)a0); \ + ST_UB(out0, dst); \ +} while (0) + +#define CALC_RGBA4444(y, u, v, out0, out1, N, dst) do { \ + CALC_RGB##N(y, u, v, R, G, B); \ + tmp0 = ANDI_B(R, 0xf0); \ + tmp1 = SRAI_B(G, 4); \ + RG = tmp0 | tmp1; \ + tmp0 = ANDI_B(B, 0xf0); \ + BA = ORI_B(tmp0, 0x0f); \ + STORE2_##N(out0, out1, dst); \ +} while (0) + +#define CALC_RGB565(y, u, v, out0, out1, N, dst) do { \ + CALC_RGB##N(y, u, v, R, G, B); \ + tmp0 = ANDI_B(R, 0xf8); \ + tmp1 = SRAI_B(G, 5); \ + RG = tmp0 | tmp1; \ + tmp0 = SLLI_B(G, 3); \ + tmp1 = ANDI_B(tmp0, 0xe0); \ + tmp0 = SRAI_B(B, 3); \ + GB = tmp0 | tmp1; \ + STORE2_##N(out0, out1, dst); \ +} while (0) + +static WEBP_INLINE int Clip8(int v) { + return v < 0 ? 0 : v > 255 ? 255 : v; +} + +static void YuvToRgb(int y, int u, int v, uint8_t* const rgb) { + const int y1 = MultHi(y, 19077); + const int r1 = y1 + MultHi(v, 26149) - 14234; + const int g1 = y1 - MultHi(u, 6419) - MultHi(v, 13320) + 8708; + const int b1 = y1 + MultHi(u, 33050) - 17685; + rgb[0] = Clip8(r1 >> 6); + rgb[1] = Clip8(g1 >> 6); + rgb[2] = Clip8(b1 >> 6); +} + +static void YuvToBgr(int y, int u, int v, uint8_t* const bgr) { + const int y1 = MultHi(y, 19077); + const int r1 = y1 + MultHi(v, 26149) - 14234; + const int g1 = y1 - MultHi(u, 6419) - MultHi(v, 13320) + 8708; + const int b1 = y1 + MultHi(u, 33050) - 17685; + bgr[0] = Clip8(b1 >> 6); + bgr[1] = Clip8(g1 >> 6); + bgr[2] = Clip8(r1 >> 6); +} + +#if !defined(WEBP_REDUCE_CSP) +static void YuvToRgb565(int y, int u, int v, uint8_t* const rgb) { + const int y1 = MultHi(y, 19077); + const int r1 = y1 + MultHi(v, 26149) - 14234; + const int g1 = y1 - MultHi(u, 6419) - MultHi(v, 13320) + 8708; + const int b1 = y1 + MultHi(u, 33050) - 17685; + const int r = Clip8(r1 >> 6); + const int g = Clip8(g1 >> 6); + const int b = Clip8(b1 >> 6); + const int rg = (r & 0xf8) | (g >> 5); + const int gb = ((g << 3) & 0xe0) | (b >> 3); +#if (WEBP_SWAP_16BIT_CSP == 1) + rgb[0] = gb; + rgb[1] = rg; +#else + rgb[0] = rg; + rgb[1] = gb; +#endif +} + +static void YuvToRgba4444(int y, int u, int v, uint8_t* const argb) { + const int y1 = MultHi(y, 19077); + const int r1 = y1 + MultHi(v, 26149) - 14234; + const int g1 = y1 - MultHi(u, 6419) - MultHi(v, 13320) + 8708; + const int b1 = y1 + MultHi(u, 33050) - 17685; + const int r = Clip8(r1 >> 6); + const int g = Clip8(g1 >> 6); + const int b = Clip8(b1 >> 6); + const int rg = (r & 0xf0) | (g >> 4); + const int ba = (b & 0xf0) | 0x0f; // overwrite the lower 4 bits +#if (WEBP_SWAP_16BIT_CSP == 1) + argb[0] = ba; + argb[1] = rg; +#else + argb[0] = rg; + argb[1] = ba; +#endif +} + +static void YuvToArgb(uint8_t y, uint8_t u, uint8_t v, uint8_t* const argb) { + argb[0] = 0xff; + YuvToRgb(y, u, v, argb + 1); +} +#endif // WEBP_REDUCE_CSP + +static void YuvToBgra(uint8_t y, uint8_t u, uint8_t v, uint8_t* const bgra) { + YuvToBgr(y, u, v, bgra); + bgra[3] = 0xff; +} + +static void YuvToRgba(uint8_t y, uint8_t u, uint8_t v, uint8_t* const rgba) { + YuvToRgb(y, u, v, rgba); + rgba[3] = 0xff; +} + +#if !defined(WEBP_REDUCE_CSP) +static void YuvToRgbLine(const uint8_t* y, const uint8_t* u, + const uint8_t* v, uint8_t* dst, int length) { + v16u8 R, G, B; + while (length >= 16) { + CALC_RGB16(y, u, v, R, G, B); + STORE16_3(R, G, B, dst); + y += 16; + u += 16; + v += 16; + dst += 16 * 3; + length -= 16; + } + if (length > 8) { + uint8_t temp[3 * 16] = { 0 }; + memcpy(temp, y, length * sizeof(*temp)); + CALC_RGB16(temp, u, v, R, G, B); + STORE16_3(R, G, B, temp); + memcpy(dst, temp, length * 3 * sizeof(*dst)); + } else if (length > 0) { + uint8_t temp[3 * 8] = { 0 }; + memcpy(temp, y, length * sizeof(*temp)); + CALC_RGB8(temp, u, v, R, G, B); + STORE8_3(R, G, B, temp); + memcpy(dst, temp, length * 3 * sizeof(*dst)); + } +} + +static void YuvToBgrLine(const uint8_t* y, const uint8_t* u, + const uint8_t* v, uint8_t* dst, int length) { + v16u8 R, G, B; + while (length >= 16) { + CALC_RGB16(y, u, v, R, G, B); + STORE16_3(B, G, R, dst); + y += 16; + u += 16; + v += 16; + dst += 16 * 3; + length -= 16; + } + if (length > 8) { + uint8_t temp[3 * 16] = { 0 }; + memcpy(temp, y, length * sizeof(*temp)); + CALC_RGB16(temp, u, v, R, G, B); + STORE16_3(B, G, R, temp); + memcpy(dst, temp, length * 3 * sizeof(*dst)); + } else if (length > 0) { + uint8_t temp[3 * 8] = { 0 }; + memcpy(temp, y, length * sizeof(*temp)); + CALC_RGB8(temp, u, v, R, G, B); + STORE8_3(B, G, R, temp); + memcpy(dst, temp, length * 3 * sizeof(*dst)); + } +} +#endif // WEBP_REDUCE_CSP + +static void YuvToRgbaLine(const uint8_t* y, const uint8_t* u, + const uint8_t* v, uint8_t* dst, int length) { + v16u8 R, G, B; + const v16u8 A = (v16u8)__msa_ldi_b(ALPHAVAL); + while (length >= 16) { + CALC_RGB16(y, u, v, R, G, B); + STORE16_4(R, G, B, A, dst); + y += 16; + u += 16; + v += 16; + dst += 16 * 4; + length -= 16; + } + if (length > 8) { + uint8_t temp[4 * 16] = { 0 }; + memcpy(temp, y, length * sizeof(*temp)); + CALC_RGB16(&temp[0], u, v, R, G, B); + STORE16_4(R, G, B, A, temp); + memcpy(dst, temp, length * 4 * sizeof(*dst)); + } else if (length > 0) { + uint8_t temp[4 * 8] = { 0 }; + memcpy(temp, y, length * sizeof(*temp)); + CALC_RGB8(temp, u, v, R, G, B); + STORE8_4(R, G, B, A, temp); + memcpy(dst, temp, length * 4 * sizeof(*dst)); + } +} + +static void YuvToBgraLine(const uint8_t* y, const uint8_t* u, + const uint8_t* v, uint8_t* dst, int length) { + v16u8 R, G, B; + const v16u8 A = (v16u8)__msa_ldi_b(ALPHAVAL); + while (length >= 16) { + CALC_RGB16(y, u, v, R, G, B); + STORE16_4(B, G, R, A, dst); + y += 16; + u += 16; + v += 16; + dst += 16 * 4; + length -= 16; + } + if (length > 8) { + uint8_t temp[4 * 16] = { 0 }; + memcpy(temp, y, length * sizeof(*temp)); + CALC_RGB16(temp, u, v, R, G, B); + STORE16_4(B, G, R, A, temp); + memcpy(dst, temp, length * 4 * sizeof(*dst)); + } else if (length > 0) { + uint8_t temp[4 * 8] = { 0 }; + memcpy(temp, y, length * sizeof(*temp)); + CALC_RGB8(temp, u, v, R, G, B); + STORE8_4(B, G, R, A, temp); + memcpy(dst, temp, length * 4 * sizeof(*dst)); + } +} + +#if !defined(WEBP_REDUCE_CSP) +static void YuvToArgbLine(const uint8_t* y, const uint8_t* u, + const uint8_t* v, uint8_t* dst, int length) { + v16u8 R, G, B; + const v16u8 A = (v16u8)__msa_ldi_b(ALPHAVAL); + while (length >= 16) { + CALC_RGB16(y, u, v, R, G, B); + STORE16_4(A, R, G, B, dst); + y += 16; + u += 16; + v += 16; + dst += 16 * 4; + length -= 16; + } + if (length > 8) { + uint8_t temp[4 * 16] = { 0 }; + memcpy(temp, y, length * sizeof(*temp)); + CALC_RGB16(temp, u, v, R, G, B); + STORE16_4(A, R, G, B, temp); + memcpy(dst, temp, length * 4 * sizeof(*dst)); + } else if (length > 0) { + uint8_t temp[4 * 8] = { 0 }; + memcpy(temp, y, length * sizeof(*temp)); + CALC_RGB8(temp, u, v, R, G, B); + STORE8_4(A, R, G, B, temp); + memcpy(dst, temp, length * 4 * sizeof(*dst)); + } +} + +static void YuvToRgba4444Line(const uint8_t* y, const uint8_t* u, + const uint8_t* v, uint8_t* dst, int length) { + v16u8 R, G, B, RG, BA, tmp0, tmp1; + while (length >= 16) { +#if (WEBP_SWAP_16BIT_CSP == 1) + CALC_RGBA4444(y, u, v, BA, RG, 16, dst); +#else + CALC_RGBA4444(y, u, v, RG, BA, 16, dst); +#endif + y += 16; + u += 16; + v += 16; + dst += 16 * 2; + length -= 16; + } + if (length > 8) { + uint8_t temp[2 * 16] = { 0 }; + memcpy(temp, y, length * sizeof(*temp)); +#if (WEBP_SWAP_16BIT_CSP == 1) + CALC_RGBA4444(temp, u, v, BA, RG, 16, temp); +#else + CALC_RGBA4444(temp, u, v, RG, BA, 16, temp); +#endif + memcpy(dst, temp, length * 2 * sizeof(*dst)); + } else if (length > 0) { + uint8_t temp[2 * 8] = { 0 }; + memcpy(temp, y, length * sizeof(*temp)); +#if (WEBP_SWAP_16BIT_CSP == 1) + CALC_RGBA4444(temp, u, v, BA, RG, 8, temp); +#else + CALC_RGBA4444(temp, u, v, RG, BA, 8, temp); +#endif + memcpy(dst, temp, length * 2 * sizeof(*dst)); + } +} + +static void YuvToRgb565Line(const uint8_t* y, const uint8_t* u, + const uint8_t* v, uint8_t* dst, int length) { + v16u8 R, G, B, RG, GB, tmp0, tmp1; + while (length >= 16) { +#if (WEBP_SWAP_16BIT_CSP == 1) + CALC_RGB565(y, u, v, GB, RG, 16, dst); +#else + CALC_RGB565(y, u, v, RG, GB, 16, dst); +#endif + y += 16; + u += 16; + v += 16; + dst += 16 * 2; + length -= 16; + } + if (length > 8) { + uint8_t temp[2 * 16] = { 0 }; + memcpy(temp, y, length * sizeof(*temp)); +#if (WEBP_SWAP_16BIT_CSP == 1) + CALC_RGB565(temp, u, v, GB, RG, 16, temp); +#else + CALC_RGB565(temp, u, v, RG, GB, 16, temp); +#endif + memcpy(dst, temp, length * 2 * sizeof(*dst)); + } else if (length > 0) { + uint8_t temp[2 * 8] = { 0 }; + memcpy(temp, y, length * sizeof(*temp)); +#if (WEBP_SWAP_16BIT_CSP == 1) + CALC_RGB565(temp, u, v, GB, RG, 8, temp); +#else + CALC_RGB565(temp, u, v, RG, GB, 8, temp); +#endif + memcpy(dst, temp, length * 2 * sizeof(*dst)); + } +} +#endif // WEBP_REDUCE_CSP + +#define UPSAMPLE_32PIXELS(a, b, c, d) do { \ + v16u8 s = __msa_aver_u_b(a, d); \ + v16u8 t = __msa_aver_u_b(b, c); \ + const v16u8 st = s ^ t; \ + v16u8 ad = a ^ d; \ + v16u8 bc = b ^ c; \ + v16u8 t0 = ad | bc; \ + v16u8 t1 = t0 | st; \ + v16u8 t2 = ANDI_B(t1, 1); \ + v16u8 t3 = __msa_aver_u_b(s, t); \ + const v16u8 k = t3 - t2; \ + v16u8 diag1, diag2; \ + AVER_UB2_UB(t, k, s, k, t0, t1); \ + bc = bc & st; \ + ad = ad & st; \ + t = t ^ k; \ + s = s ^ k; \ + t2 = bc | t; \ + t3 = ad | s; \ + t2 = ANDI_B(t2, 1); \ + t3 = ANDI_B(t3, 1); \ + SUB2(t0, t2, t1, t3, diag1, diag2); \ + AVER_UB2_UB(a, diag1, b, diag2, t0, t1); \ + ILVRL_B2_UB(t1, t0, a, b); \ + if (pbot_y != NULL) { \ + AVER_UB2_UB(c, diag2, d, diag1, t0, t1); \ + ILVRL_B2_UB(t1, t0, c, d); \ + } \ +} while (0) + +#define UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \ +static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bot_y, \ + const uint8_t* top_u, const uint8_t* top_v, \ + const uint8_t* cur_u, const uint8_t* cur_v, \ + uint8_t* top_dst, uint8_t* bot_dst, int len) \ +{ \ + int size = (len - 1) >> 1; \ + uint8_t temp_u[64]; \ + uint8_t temp_v[64]; \ + const uint32_t tl_uv = ((top_u[0]) | ((top_v[0]) << 16)); \ + const uint32_t l_uv = ((cur_u[0]) | ((cur_v[0]) << 16)); \ + const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \ + const uint8_t* ptop_y = &top_y[1]; \ + uint8_t* ptop_dst = top_dst + XSTEP; \ + const uint8_t* pbot_y = &bot_y[1]; \ + uint8_t* pbot_dst = bot_dst + XSTEP; \ + \ + FUNC(top_y[0], uv0 & 0xff, (uv0 >> 16), top_dst); \ + if (bot_y != NULL) { \ + const uint32_t uv1 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \ + FUNC(bot_y[0], uv1 & 0xff, (uv1 >> 16), bot_dst); \ + } \ + while (size >= 16) { \ + v16u8 tu0, tu1, tv0, tv1, cu0, cu1, cv0, cv1; \ + LD_UB2(top_u, 1, tu0, tu1); \ + LD_UB2(cur_u, 1, cu0, cu1); \ + LD_UB2(top_v, 1, tv0, tv1); \ + LD_UB2(cur_v, 1, cv0, cv1); \ + UPSAMPLE_32PIXELS(tu0, tu1, cu0, cu1); \ + UPSAMPLE_32PIXELS(tv0, tv1, cv0, cv1); \ + ST_UB4(tu0, tu1, cu0, cu1, &temp_u[0], 16); \ + ST_UB4(tv0, tv1, cv0, cv1, &temp_v[0], 16); \ + FUNC##Line(ptop_y, &temp_u[ 0], &temp_v[0], ptop_dst, 32); \ + if (bot_y != NULL) { \ + FUNC##Line(pbot_y, &temp_u[32], &temp_v[32], pbot_dst, 32); \ + } \ + ptop_y += 32; \ + pbot_y += 32; \ + ptop_dst += XSTEP * 32; \ + pbot_dst += XSTEP * 32; \ + top_u += 16; \ + top_v += 16; \ + cur_u += 16; \ + cur_v += 16; \ + size -= 16; \ + } \ + if (size > 0) { \ + v16u8 tu0, tu1, tv0, tv1, cu0, cu1, cv0, cv1; \ + memcpy(&temp_u[ 0], top_u, 17 * sizeof(uint8_t)); \ + memcpy(&temp_u[32], cur_u, 17 * sizeof(uint8_t)); \ + memcpy(&temp_v[ 0], top_v, 17 * sizeof(uint8_t)); \ + memcpy(&temp_v[32], cur_v, 17 * sizeof(uint8_t)); \ + LD_UB2(&temp_u[ 0], 1, tu0, tu1); \ + LD_UB2(&temp_u[32], 1, cu0, cu1); \ + LD_UB2(&temp_v[ 0], 1, tv0, tv1); \ + LD_UB2(&temp_v[32], 1, cv0, cv1); \ + UPSAMPLE_32PIXELS(tu0, tu1, cu0, cu1); \ + UPSAMPLE_32PIXELS(tv0, tv1, cv0, cv1); \ + ST_UB4(tu0, tu1, cu0, cu1, &temp_u[0], 16); \ + ST_UB4(tv0, tv1, cv0, cv1, &temp_v[0], 16); \ + FUNC##Line(ptop_y, &temp_u[ 0], &temp_v[0], ptop_dst, size * 2); \ + if (bot_y != NULL) { \ + FUNC##Line(pbot_y, &temp_u[32], &temp_v[32], pbot_dst, size * 2); \ + } \ + top_u += size; \ + top_v += size; \ + cur_u += size; \ + cur_v += size; \ + } \ + if (!(len & 1)) { \ + const uint32_t t0 = ((top_u[0]) | ((top_v[0]) << 16)); \ + const uint32_t c0 = ((cur_u[0]) | ((cur_v[0]) << 16)); \ + const uint32_t tmp0 = (3 * t0 + c0 + 0x00020002u) >> 2; \ + FUNC(top_y[len - 1], tmp0 & 0xff, (tmp0 >> 16), \ + top_dst + (len - 1) * XSTEP); \ + if (bot_y != NULL) { \ + const uint32_t tmp1 = (3 * c0 + t0 + 0x00020002u) >> 2; \ + FUNC(bot_y[len - 1], tmp1 & 0xff, (tmp1 >> 16), \ + bot_dst + (len - 1) * XSTEP); \ + } \ + } \ +} + +UPSAMPLE_FUNC(UpsampleRgbaLinePair, YuvToRgba, 4) +UPSAMPLE_FUNC(UpsampleBgraLinePair, YuvToBgra, 4) +#if !defined(WEBP_REDUCE_CSP) +UPSAMPLE_FUNC(UpsampleRgbLinePair, YuvToRgb, 3) +UPSAMPLE_FUNC(UpsampleBgrLinePair, YuvToBgr, 3) +UPSAMPLE_FUNC(UpsampleArgbLinePair, YuvToArgb, 4) +UPSAMPLE_FUNC(UpsampleRgba4444LinePair, YuvToRgba4444, 2) +UPSAMPLE_FUNC(UpsampleRgb565LinePair, YuvToRgb565, 2) +#endif // WEBP_REDUCE_CSP + +//------------------------------------------------------------------------------ +// Entry point + +extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */]; + +extern void WebPInitUpsamplersMSA(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplersMSA(void) { + WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair; + WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair; + WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair; + WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair; +#if !defined(WEBP_REDUCE_CSP) + WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair; + WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair; + WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair; + WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair; + WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair; + WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair; + WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair; +#endif // WEBP_REDUCE_CSP +} + +#endif // FANCY_UPSAMPLING + +#endif // WEBP_USE_MSA + +#if !(defined(FANCY_UPSAMPLING) && defined(WEBP_USE_MSA)) +WEBP_DSP_INIT_STUB(WebPInitUpsamplersMSA) +#endif diff --git a/third-party/webp/libwebp/src/dsp/upsampling_neon.c b/third-party/webp/libwebp/src/dsp/upsampling_neon.c new file mode 100644 index 0000000000..bbc000ca2d --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/upsampling_neon.c @@ -0,0 +1,285 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// NEON version of YUV to RGB upsampling functions. +// +// Author: mans@mansr.com (Mans Rullgard) +// Based on SSE code by: somnath@google.com (Somnath Banerjee) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_NEON) + +#include +#include +#include +#include "src/dsp/neon.h" +#include "src/dsp/yuv.h" + +#ifdef FANCY_UPSAMPLING + +//----------------------------------------------------------------------------- +// U/V upsampling + +// Loads 9 pixels each from rows r1 and r2 and generates 16 pixels. +#define UPSAMPLE_16PIXELS(r1, r2, out) do { \ + const uint8x8_t a = vld1_u8(r1 + 0); \ + const uint8x8_t b = vld1_u8(r1 + 1); \ + const uint8x8_t c = vld1_u8(r2 + 0); \ + const uint8x8_t d = vld1_u8(r2 + 1); \ + /* a + b + c + d */ \ + const uint16x8_t ad = vaddl_u8(a, d); \ + const uint16x8_t bc = vaddl_u8(b, c); \ + const uint16x8_t abcd = vaddq_u16(ad, bc); \ + /* 3a + b + c + 3d */ \ + const uint16x8_t al = vaddq_u16(abcd, vshlq_n_u16(ad, 1)); \ + /* a + 3b + 3c + d */ \ + const uint16x8_t bl = vaddq_u16(abcd, vshlq_n_u16(bc, 1)); \ + \ + const uint8x8_t diag2 = vshrn_n_u16(al, 3); \ + const uint8x8_t diag1 = vshrn_n_u16(bl, 3); \ + \ + const uint8x8_t A = vrhadd_u8(a, diag1); \ + const uint8x8_t B = vrhadd_u8(b, diag2); \ + const uint8x8_t C = vrhadd_u8(c, diag2); \ + const uint8x8_t D = vrhadd_u8(d, diag1); \ + \ + uint8x8x2_t A_B, C_D; \ + INIT_VECTOR2(A_B, A, B); \ + INIT_VECTOR2(C_D, C, D); \ + vst2_u8(out + 0, A_B); \ + vst2_u8(out + 32, C_D); \ +} while (0) + +// Turn the macro into a function for reducing code-size when non-critical +static void Upsample16Pixels_NEON(const uint8_t* r1, const uint8_t* r2, + uint8_t* out) { + UPSAMPLE_16PIXELS(r1, r2, out); +} + +#define UPSAMPLE_LAST_BLOCK(tb, bb, num_pixels, out) { \ + uint8_t r1[9], r2[9]; \ + memcpy(r1, (tb), (num_pixels)); \ + memcpy(r2, (bb), (num_pixels)); \ + /* replicate last byte */ \ + memset(r1 + (num_pixels), r1[(num_pixels) - 1], 9 - (num_pixels)); \ + memset(r2 + (num_pixels), r2[(num_pixels) - 1], 9 - (num_pixels)); \ + Upsample16Pixels_NEON(r1, r2, out); \ +} + +//----------------------------------------------------------------------------- +// YUV->RGB conversion + +// note: we represent the 33050 large constant as 32768 + 282 +static const int16_t kCoeffs1[4] = { 19077, 26149, 6419, 13320 }; + +#define v255 vdup_n_u8(255) + +#define STORE_Rgb(out, r, g, b) do { \ + uint8x8x3_t r_g_b; \ + INIT_VECTOR3(r_g_b, r, g, b); \ + vst3_u8(out, r_g_b); \ +} while (0) + +#define STORE_Bgr(out, r, g, b) do { \ + uint8x8x3_t b_g_r; \ + INIT_VECTOR3(b_g_r, b, g, r); \ + vst3_u8(out, b_g_r); \ +} while (0) + +#define STORE_Rgba(out, r, g, b) do { \ + uint8x8x4_t r_g_b_v255; \ + INIT_VECTOR4(r_g_b_v255, r, g, b, v255); \ + vst4_u8(out, r_g_b_v255); \ +} while (0) + +#define STORE_Bgra(out, r, g, b) do { \ + uint8x8x4_t b_g_r_v255; \ + INIT_VECTOR4(b_g_r_v255, b, g, r, v255); \ + vst4_u8(out, b_g_r_v255); \ +} while (0) + +#define STORE_Argb(out, r, g, b) do { \ + uint8x8x4_t v255_r_g_b; \ + INIT_VECTOR4(v255_r_g_b, v255, r, g, b); \ + vst4_u8(out, v255_r_g_b); \ +} while (0) + +#if (WEBP_SWAP_16BIT_CSP == 0) +#define ZIP_U8(lo, hi) vzip_u8((lo), (hi)) +#else +#define ZIP_U8(lo, hi) vzip_u8((hi), (lo)) +#endif + +#define STORE_Rgba4444(out, r, g, b) do { \ + const uint8x8_t rg = vsri_n_u8(r, g, 4); /* shift g, insert r */ \ + const uint8x8_t ba = vsri_n_u8(b, v255, 4); /* shift a, insert b */ \ + const uint8x8x2_t rgba4444 = ZIP_U8(rg, ba); \ + vst1q_u8(out, vcombine_u8(rgba4444.val[0], rgba4444.val[1])); \ +} while (0) + +#define STORE_Rgb565(out, r, g, b) do { \ + const uint8x8_t rg = vsri_n_u8(r, g, 5); /* shift g and insert r */ \ + const uint8x8_t g1 = vshl_n_u8(g, 3); /* pre-shift g: 3bits */ \ + const uint8x8_t gb = vsri_n_u8(g1, b, 3); /* shift b and insert g */ \ + const uint8x8x2_t rgb565 = ZIP_U8(rg, gb); \ + vst1q_u8(out, vcombine_u8(rgb565.val[0], rgb565.val[1])); \ +} while (0) + +#define CONVERT8(FMT, XSTEP, N, src_y, src_uv, out, cur_x) do { \ + int i; \ + for (i = 0; i < N; i += 8) { \ + const int off = ((cur_x) + i) * XSTEP; \ + const uint8x8_t y = vld1_u8((src_y) + (cur_x) + i); \ + const uint8x8_t u = vld1_u8((src_uv) + i + 0); \ + const uint8x8_t v = vld1_u8((src_uv) + i + 16); \ + const int16x8_t Y0 = vreinterpretq_s16_u16(vshll_n_u8(y, 7)); \ + const int16x8_t U0 = vreinterpretq_s16_u16(vshll_n_u8(u, 7)); \ + const int16x8_t V0 = vreinterpretq_s16_u16(vshll_n_u8(v, 7)); \ + const int16x8_t Y1 = vqdmulhq_lane_s16(Y0, coeff1, 0); \ + const int16x8_t R0 = vqdmulhq_lane_s16(V0, coeff1, 1); \ + const int16x8_t G0 = vqdmulhq_lane_s16(U0, coeff1, 2); \ + const int16x8_t G1 = vqdmulhq_lane_s16(V0, coeff1, 3); \ + const int16x8_t B0 = vqdmulhq_n_s16(U0, 282); \ + const int16x8_t R1 = vqaddq_s16(Y1, R_Rounder); \ + const int16x8_t G2 = vqaddq_s16(Y1, G_Rounder); \ + const int16x8_t B1 = vqaddq_s16(Y1, B_Rounder); \ + const int16x8_t R2 = vqaddq_s16(R0, R1); \ + const int16x8_t G3 = vqaddq_s16(G0, G1); \ + const int16x8_t B2 = vqaddq_s16(B0, B1); \ + const int16x8_t G4 = vqsubq_s16(G2, G3); \ + const int16x8_t B3 = vqaddq_s16(B2, U0); \ + const uint8x8_t R = vqshrun_n_s16(R2, YUV_FIX2); \ + const uint8x8_t G = vqshrun_n_s16(G4, YUV_FIX2); \ + const uint8x8_t B = vqshrun_n_s16(B3, YUV_FIX2); \ + STORE_ ## FMT(out + off, R, G, B); \ + } \ +} while (0) + +#define CONVERT1(FUNC, XSTEP, N, src_y, src_uv, rgb, cur_x) { \ + int i; \ + for (i = 0; i < N; i++) { \ + const int off = ((cur_x) + i) * XSTEP; \ + const int y = src_y[(cur_x) + i]; \ + const int u = (src_uv)[i]; \ + const int v = (src_uv)[i + 16]; \ + FUNC(y, u, v, rgb + off); \ + } \ +} + +#define CONVERT2RGB_8(FMT, XSTEP, top_y, bottom_y, uv, \ + top_dst, bottom_dst, cur_x, len) { \ + CONVERT8(FMT, XSTEP, len, top_y, uv, top_dst, cur_x); \ + if (bottom_y != NULL) { \ + CONVERT8(FMT, XSTEP, len, bottom_y, (uv) + 32, bottom_dst, cur_x); \ + } \ +} + +#define CONVERT2RGB_1(FUNC, XSTEP, top_y, bottom_y, uv, \ + top_dst, bottom_dst, cur_x, len) { \ + CONVERT1(FUNC, XSTEP, len, top_y, uv, top_dst, cur_x); \ + if (bottom_y != NULL) { \ + CONVERT1(FUNC, XSTEP, len, bottom_y, (uv) + 32, bottom_dst, cur_x); \ + } \ +} + +#define NEON_UPSAMPLE_FUNC(FUNC_NAME, FMT, XSTEP) \ +static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \ + const uint8_t* top_u, const uint8_t* top_v, \ + const uint8_t* cur_u, const uint8_t* cur_v, \ + uint8_t* top_dst, uint8_t* bottom_dst, int len) { \ + int block; \ + /* 16 byte aligned array to cache reconstructed u and v */ \ + uint8_t uv_buf[2 * 32 + 15]; \ + uint8_t* const r_uv = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~15); \ + const int uv_len = (len + 1) >> 1; \ + /* 9 pixels must be read-able for each block */ \ + const int num_blocks = (uv_len - 1) >> 3; \ + const int leftover = uv_len - num_blocks * 8; \ + const int last_pos = 1 + 16 * num_blocks; \ + \ + const int u_diag = ((top_u[0] + cur_u[0]) >> 1) + 1; \ + const int v_diag = ((top_v[0] + cur_v[0]) >> 1) + 1; \ + \ + const int16x4_t coeff1 = vld1_s16(kCoeffs1); \ + const int16x8_t R_Rounder = vdupq_n_s16(-14234); \ + const int16x8_t G_Rounder = vdupq_n_s16(8708); \ + const int16x8_t B_Rounder = vdupq_n_s16(-17685); \ + \ + /* Treat the first pixel in regular way */ \ + assert(top_y != NULL); \ + { \ + const int u0 = (top_u[0] + u_diag) >> 1; \ + const int v0 = (top_v[0] + v_diag) >> 1; \ + VP8YuvTo ## FMT(top_y[0], u0, v0, top_dst); \ + } \ + if (bottom_y != NULL) { \ + const int u0 = (cur_u[0] + u_diag) >> 1; \ + const int v0 = (cur_v[0] + v_diag) >> 1; \ + VP8YuvTo ## FMT(bottom_y[0], u0, v0, bottom_dst); \ + } \ + \ + for (block = 0; block < num_blocks; ++block) { \ + UPSAMPLE_16PIXELS(top_u, cur_u, r_uv); \ + UPSAMPLE_16PIXELS(top_v, cur_v, r_uv + 16); \ + CONVERT2RGB_8(FMT, XSTEP, top_y, bottom_y, r_uv, \ + top_dst, bottom_dst, 16 * block + 1, 16); \ + top_u += 8; \ + cur_u += 8; \ + top_v += 8; \ + cur_v += 8; \ + } \ + \ + UPSAMPLE_LAST_BLOCK(top_u, cur_u, leftover, r_uv); \ + UPSAMPLE_LAST_BLOCK(top_v, cur_v, leftover, r_uv + 16); \ + CONVERT2RGB_1(VP8YuvTo ## FMT, XSTEP, top_y, bottom_y, r_uv, \ + top_dst, bottom_dst, last_pos, len - last_pos); \ +} + +// NEON variants of the fancy upsampler. +NEON_UPSAMPLE_FUNC(UpsampleRgbaLinePair_NEON, Rgba, 4) +NEON_UPSAMPLE_FUNC(UpsampleBgraLinePair_NEON, Bgra, 4) +#if !defined(WEBP_REDUCE_CSP) +NEON_UPSAMPLE_FUNC(UpsampleRgbLinePair_NEON, Rgb, 3) +NEON_UPSAMPLE_FUNC(UpsampleBgrLinePair_NEON, Bgr, 3) +NEON_UPSAMPLE_FUNC(UpsampleArgbLinePair_NEON, Argb, 4) +NEON_UPSAMPLE_FUNC(UpsampleRgba4444LinePair_NEON, Rgba4444, 2) +NEON_UPSAMPLE_FUNC(UpsampleRgb565LinePair_NEON, Rgb565, 2) +#endif // WEBP_REDUCE_CSP + +//------------------------------------------------------------------------------ +// Entry point + +extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */]; + +extern void WebPInitUpsamplersNEON(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplersNEON(void) { + WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair_NEON; + WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair_NEON; + WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair_NEON; + WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair_NEON; +#if !defined(WEBP_REDUCE_CSP) + WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair_NEON; + WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair_NEON; + WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair_NEON; + WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair_NEON; + WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair_NEON; + WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair_NEON; + WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair_NEON; +#endif // WEBP_REDUCE_CSP +} + +#endif // FANCY_UPSAMPLING + +#endif // WEBP_USE_NEON + +#if !(defined(FANCY_UPSAMPLING) && defined(WEBP_USE_NEON)) +WEBP_DSP_INIT_STUB(WebPInitUpsamplersNEON) +#endif diff --git a/third-party/webp/libwebp/src/dsp/upsampling_sse2.c b/third-party/webp/libwebp/src/dsp/upsampling_sse2.c new file mode 100644 index 0000000000..08b6d0b1cf --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/upsampling_sse2.c @@ -0,0 +1,267 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE2 version of YUV to RGB upsampling functions. +// +// Author: somnath@google.com (Somnath Banerjee) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE2) + +#include +#include +#include +#include "src/dsp/yuv.h" + +#ifdef FANCY_UPSAMPLING + +// We compute (9*a + 3*b + 3*c + d + 8) / 16 as follows +// u = (9*a + 3*b + 3*c + d + 8) / 16 +// = (a + (a + 3*b + 3*c + d) / 8 + 1) / 2 +// = (a + m + 1) / 2 +// where m = (a + 3*b + 3*c + d) / 8 +// = ((a + b + c + d) / 2 + b + c) / 4 +// +// Let's say k = (a + b + c + d) / 4. +// We can compute k as +// k = (s + t + 1) / 2 - ((a^d) | (b^c) | (s^t)) & 1 +// where s = (a + d + 1) / 2 and t = (b + c + 1) / 2 +// +// Then m can be written as +// m = (k + t + 1) / 2 - (((b^c) & (s^t)) | (k^t)) & 1 + +// Computes out = (k + in + 1) / 2 - ((ij & (s^t)) | (k^in)) & 1 +#define GET_M(ij, in, out) do { \ + const __m128i tmp0 = _mm_avg_epu8(k, (in)); /* (k + in + 1) / 2 */ \ + const __m128i tmp1 = _mm_and_si128((ij), st); /* (ij) & (s^t) */ \ + const __m128i tmp2 = _mm_xor_si128(k, (in)); /* (k^in) */ \ + const __m128i tmp3 = _mm_or_si128(tmp1, tmp2); /* ((ij) & (s^t)) | (k^in) */\ + const __m128i tmp4 = _mm_and_si128(tmp3, one); /* & 1 -> lsb_correction */ \ + (out) = _mm_sub_epi8(tmp0, tmp4); /* (k + in + 1) / 2 - lsb_correction */ \ +} while (0) + +// pack and store two alternating pixel rows +#define PACK_AND_STORE(a, b, da, db, out) do { \ + const __m128i t_a = _mm_avg_epu8(a, da); /* (9a + 3b + 3c + d + 8) / 16 */ \ + const __m128i t_b = _mm_avg_epu8(b, db); /* (3a + 9b + c + 3d + 8) / 16 */ \ + const __m128i t_1 = _mm_unpacklo_epi8(t_a, t_b); \ + const __m128i t_2 = _mm_unpackhi_epi8(t_a, t_b); \ + _mm_store_si128(((__m128i*)(out)) + 0, t_1); \ + _mm_store_si128(((__m128i*)(out)) + 1, t_2); \ +} while (0) + +// Loads 17 pixels each from rows r1 and r2 and generates 32 pixels. +#define UPSAMPLE_32PIXELS(r1, r2, out) { \ + const __m128i one = _mm_set1_epi8(1); \ + const __m128i a = _mm_loadu_si128((const __m128i*)&(r1)[0]); \ + const __m128i b = _mm_loadu_si128((const __m128i*)&(r1)[1]); \ + const __m128i c = _mm_loadu_si128((const __m128i*)&(r2)[0]); \ + const __m128i d = _mm_loadu_si128((const __m128i*)&(r2)[1]); \ + \ + const __m128i s = _mm_avg_epu8(a, d); /* s = (a + d + 1) / 2 */ \ + const __m128i t = _mm_avg_epu8(b, c); /* t = (b + c + 1) / 2 */ \ + const __m128i st = _mm_xor_si128(s, t); /* st = s^t */ \ + \ + const __m128i ad = _mm_xor_si128(a, d); /* ad = a^d */ \ + const __m128i bc = _mm_xor_si128(b, c); /* bc = b^c */ \ + \ + const __m128i t1 = _mm_or_si128(ad, bc); /* (a^d) | (b^c) */ \ + const __m128i t2 = _mm_or_si128(t1, st); /* (a^d) | (b^c) | (s^t) */ \ + const __m128i t3 = _mm_and_si128(t2, one); /* (a^d) | (b^c) | (s^t) & 1 */ \ + const __m128i t4 = _mm_avg_epu8(s, t); \ + const __m128i k = _mm_sub_epi8(t4, t3); /* k = (a + b + c + d) / 4 */ \ + __m128i diag1, diag2; \ + \ + GET_M(bc, t, diag1); /* diag1 = (a + 3b + 3c + d) / 8 */ \ + GET_M(ad, s, diag2); /* diag2 = (3a + b + c + 3d) / 8 */ \ + \ + /* pack the alternate pixels */ \ + PACK_AND_STORE(a, b, diag1, diag2, (out) + 0); /* store top */ \ + PACK_AND_STORE(c, d, diag2, diag1, (out) + 2 * 32); /* store bottom */ \ +} + +// Turn the macro into a function for reducing code-size when non-critical +static void Upsample32Pixels_SSE2(const uint8_t r1[], const uint8_t r2[], + uint8_t* const out) { + UPSAMPLE_32PIXELS(r1, r2, out); +} + +#define UPSAMPLE_LAST_BLOCK(tb, bb, num_pixels, out) { \ + uint8_t r1[17], r2[17]; \ + memcpy(r1, (tb), (num_pixels)); \ + memcpy(r2, (bb), (num_pixels)); \ + /* replicate last byte */ \ + memset(r1 + (num_pixels), r1[(num_pixels) - 1], 17 - (num_pixels)); \ + memset(r2 + (num_pixels), r2[(num_pixels) - 1], 17 - (num_pixels)); \ + /* using the shared function instead of the macro saves ~3k code size */ \ + Upsample32Pixels_SSE2(r1, r2, out); \ +} + +#define CONVERT2RGB_32(FUNC, XSTEP, top_y, bottom_y, \ + top_dst, bottom_dst, cur_x) do { \ + FUNC##32_SSE2((top_y) + (cur_x), r_u, r_v, (top_dst) + (cur_x) * (XSTEP)); \ + if ((bottom_y) != NULL) { \ + FUNC##32_SSE2((bottom_y) + (cur_x), r_u + 64, r_v + 64, \ + (bottom_dst) + (cur_x) * (XSTEP)); \ + } \ +} while (0) + +#define SSE2_UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \ +static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \ + const uint8_t* top_u, const uint8_t* top_v, \ + const uint8_t* cur_u, const uint8_t* cur_v, \ + uint8_t* top_dst, uint8_t* bottom_dst, int len) { \ + int uv_pos, pos; \ + /* 16byte-aligned array to cache reconstructed u and v */ \ + uint8_t uv_buf[14 * 32 + 15] = { 0 }; \ + uint8_t* const r_u = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~(uintptr_t)15); \ + uint8_t* const r_v = r_u + 32; \ + \ + assert(top_y != NULL); \ + { /* Treat the first pixel in regular way */ \ + const int u_diag = ((top_u[0] + cur_u[0]) >> 1) + 1; \ + const int v_diag = ((top_v[0] + cur_v[0]) >> 1) + 1; \ + const int u0_t = (top_u[0] + u_diag) >> 1; \ + const int v0_t = (top_v[0] + v_diag) >> 1; \ + FUNC(top_y[0], u0_t, v0_t, top_dst); \ + if (bottom_y != NULL) { \ + const int u0_b = (cur_u[0] + u_diag) >> 1; \ + const int v0_b = (cur_v[0] + v_diag) >> 1; \ + FUNC(bottom_y[0], u0_b, v0_b, bottom_dst); \ + } \ + } \ + /* For UPSAMPLE_32PIXELS, 17 u/v values must be read-able for each block */ \ + for (pos = 1, uv_pos = 0; pos + 32 + 1 <= len; pos += 32, uv_pos += 16) { \ + UPSAMPLE_32PIXELS(top_u + uv_pos, cur_u + uv_pos, r_u); \ + UPSAMPLE_32PIXELS(top_v + uv_pos, cur_v + uv_pos, r_v); \ + CONVERT2RGB_32(FUNC, XSTEP, top_y, bottom_y, top_dst, bottom_dst, pos); \ + } \ + if (len > 1) { \ + const int left_over = ((len + 1) >> 1) - (pos >> 1); \ + uint8_t* const tmp_top_dst = r_u + 4 * 32; \ + uint8_t* const tmp_bottom_dst = tmp_top_dst + 4 * 32; \ + uint8_t* const tmp_top = tmp_bottom_dst + 4 * 32; \ + uint8_t* const tmp_bottom = (bottom_y == NULL) ? NULL : tmp_top + 32; \ + assert(left_over > 0); \ + UPSAMPLE_LAST_BLOCK(top_u + uv_pos, cur_u + uv_pos, left_over, r_u); \ + UPSAMPLE_LAST_BLOCK(top_v + uv_pos, cur_v + uv_pos, left_over, r_v); \ + memcpy(tmp_top, top_y + pos, len - pos); \ + if (bottom_y != NULL) memcpy(tmp_bottom, bottom_y + pos, len - pos); \ + CONVERT2RGB_32(FUNC, XSTEP, tmp_top, tmp_bottom, tmp_top_dst, \ + tmp_bottom_dst, 0); \ + memcpy(top_dst + pos * (XSTEP), tmp_top_dst, (len - pos) * (XSTEP)); \ + if (bottom_y != NULL) { \ + memcpy(bottom_dst + pos * (XSTEP), tmp_bottom_dst, \ + (len - pos) * (XSTEP)); \ + } \ + } \ +} + +// SSE2 variants of the fancy upsampler. +SSE2_UPSAMPLE_FUNC(UpsampleRgbaLinePair_SSE2, VP8YuvToRgba, 4) +SSE2_UPSAMPLE_FUNC(UpsampleBgraLinePair_SSE2, VP8YuvToBgra, 4) + +#if !defined(WEBP_REDUCE_CSP) +SSE2_UPSAMPLE_FUNC(UpsampleRgbLinePair_SSE2, VP8YuvToRgb, 3) +SSE2_UPSAMPLE_FUNC(UpsampleBgrLinePair_SSE2, VP8YuvToBgr, 3) +SSE2_UPSAMPLE_FUNC(UpsampleArgbLinePair_SSE2, VP8YuvToArgb, 4) +SSE2_UPSAMPLE_FUNC(UpsampleRgba4444LinePair_SSE2, VP8YuvToRgba4444, 2) +SSE2_UPSAMPLE_FUNC(UpsampleRgb565LinePair_SSE2, VP8YuvToRgb565, 2) +#endif // WEBP_REDUCE_CSP + +#undef GET_M +#undef PACK_AND_STORE +#undef UPSAMPLE_32PIXELS +#undef UPSAMPLE_LAST_BLOCK +#undef CONVERT2RGB +#undef CONVERT2RGB_32 +#undef SSE2_UPSAMPLE_FUNC + +//------------------------------------------------------------------------------ +// Entry point + +extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */]; + +extern void WebPInitUpsamplersSSE2(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplersSSE2(void) { + WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair_SSE2; + WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair_SSE2; + WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair_SSE2; + WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair_SSE2; +#if !defined(WEBP_REDUCE_CSP) + WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair_SSE2; + WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair_SSE2; + WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair_SSE2; + WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair_SSE2; + WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair_SSE2; + WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair_SSE2; + WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair_SSE2; +#endif // WEBP_REDUCE_CSP +} + +#endif // FANCY_UPSAMPLING + +//------------------------------------------------------------------------------ + +extern WebPYUV444Converter WebPYUV444Converters[/* MODE_LAST */]; +extern void WebPInitYUV444ConvertersSSE2(void); + +#define YUV444_FUNC(FUNC_NAME, CALL, CALL_C, XSTEP) \ +extern void CALL_C(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ + uint8_t* dst, int len); \ +static void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ + uint8_t* dst, int len) { \ + int i; \ + const int max_len = len & ~31; \ + for (i = 0; i < max_len; i += 32) { \ + CALL(y + i, u + i, v + i, dst + i * (XSTEP)); \ + } \ + if (i < len) { /* C-fallback */ \ + CALL_C(y + i, u + i, v + i, dst + i * (XSTEP), len - i); \ + } \ +} + +YUV444_FUNC(Yuv444ToRgba_SSE2, VP8YuvToRgba32_SSE2, WebPYuv444ToRgba_C, 4); +YUV444_FUNC(Yuv444ToBgra_SSE2, VP8YuvToBgra32_SSE2, WebPYuv444ToBgra_C, 4); +#if !defined(WEBP_REDUCE_CSP) +YUV444_FUNC(Yuv444ToRgb_SSE2, VP8YuvToRgb32_SSE2, WebPYuv444ToRgb_C, 3); +YUV444_FUNC(Yuv444ToBgr_SSE2, VP8YuvToBgr32_SSE2, WebPYuv444ToBgr_C, 3); +YUV444_FUNC(Yuv444ToArgb_SSE2, VP8YuvToArgb32_SSE2, WebPYuv444ToArgb_C, 4) +YUV444_FUNC(Yuv444ToRgba4444_SSE2, VP8YuvToRgba444432_SSE2, \ + WebPYuv444ToRgba4444_C, 2) +YUV444_FUNC(Yuv444ToRgb565_SSE2, VP8YuvToRgb56532_SSE2, WebPYuv444ToRgb565_C, 2) +#endif // WEBP_REDUCE_CSP + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444ConvertersSSE2(void) { + WebPYUV444Converters[MODE_RGBA] = Yuv444ToRgba_SSE2; + WebPYUV444Converters[MODE_BGRA] = Yuv444ToBgra_SSE2; + WebPYUV444Converters[MODE_rgbA] = Yuv444ToRgba_SSE2; + WebPYUV444Converters[MODE_bgrA] = Yuv444ToBgra_SSE2; +#if !defined(WEBP_REDUCE_CSP) + WebPYUV444Converters[MODE_RGB] = Yuv444ToRgb_SSE2; + WebPYUV444Converters[MODE_BGR] = Yuv444ToBgr_SSE2; + WebPYUV444Converters[MODE_ARGB] = Yuv444ToArgb_SSE2; + WebPYUV444Converters[MODE_RGBA_4444] = Yuv444ToRgba4444_SSE2; + WebPYUV444Converters[MODE_RGB_565] = Yuv444ToRgb565_SSE2; + WebPYUV444Converters[MODE_Argb] = Yuv444ToArgb_SSE2; + WebPYUV444Converters[MODE_rgbA_4444] = Yuv444ToRgba4444_SSE2; +#endif // WEBP_REDUCE_CSP +} + +#else + +WEBP_DSP_INIT_STUB(WebPInitYUV444ConvertersSSE2) + +#endif // WEBP_USE_SSE2 + +#if !(defined(FANCY_UPSAMPLING) && defined(WEBP_USE_SSE2)) +WEBP_DSP_INIT_STUB(WebPInitUpsamplersSSE2) +#endif diff --git a/third-party/webp/libwebp/src/dsp/upsampling_sse41.c b/third-party/webp/libwebp/src/dsp/upsampling_sse41.c new file mode 100644 index 0000000000..648d456027 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/upsampling_sse41.c @@ -0,0 +1,239 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE41 version of YUV to RGB upsampling functions. +// +// Author: somnath@google.com (Somnath Banerjee) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE41) + +#include +#include +#include +#include "src/dsp/yuv.h" + +#ifdef FANCY_UPSAMPLING + +#if !defined(WEBP_REDUCE_CSP) + +// We compute (9*a + 3*b + 3*c + d + 8) / 16 as follows +// u = (9*a + 3*b + 3*c + d + 8) / 16 +// = (a + (a + 3*b + 3*c + d) / 8 + 1) / 2 +// = (a + m + 1) / 2 +// where m = (a + 3*b + 3*c + d) / 8 +// = ((a + b + c + d) / 2 + b + c) / 4 +// +// Let's say k = (a + b + c + d) / 4. +// We can compute k as +// k = (s + t + 1) / 2 - ((a^d) | (b^c) | (s^t)) & 1 +// where s = (a + d + 1) / 2 and t = (b + c + 1) / 2 +// +// Then m can be written as +// m = (k + t + 1) / 2 - (((b^c) & (s^t)) | (k^t)) & 1 + +// Computes out = (k + in + 1) / 2 - ((ij & (s^t)) | (k^in)) & 1 +#define GET_M(ij, in, out) do { \ + const __m128i tmp0 = _mm_avg_epu8(k, (in)); /* (k + in + 1) / 2 */ \ + const __m128i tmp1 = _mm_and_si128((ij), st); /* (ij) & (s^t) */ \ + const __m128i tmp2 = _mm_xor_si128(k, (in)); /* (k^in) */ \ + const __m128i tmp3 = _mm_or_si128(tmp1, tmp2); /* ((ij) & (s^t)) | (k^in) */\ + const __m128i tmp4 = _mm_and_si128(tmp3, one); /* & 1 -> lsb_correction */ \ + (out) = _mm_sub_epi8(tmp0, tmp4); /* (k + in + 1) / 2 - lsb_correction */ \ +} while (0) + +// pack and store two alternating pixel rows +#define PACK_AND_STORE(a, b, da, db, out) do { \ + const __m128i t_a = _mm_avg_epu8(a, da); /* (9a + 3b + 3c + d + 8) / 16 */ \ + const __m128i t_b = _mm_avg_epu8(b, db); /* (3a + 9b + c + 3d + 8) / 16 */ \ + const __m128i t_1 = _mm_unpacklo_epi8(t_a, t_b); \ + const __m128i t_2 = _mm_unpackhi_epi8(t_a, t_b); \ + _mm_store_si128(((__m128i*)(out)) + 0, t_1); \ + _mm_store_si128(((__m128i*)(out)) + 1, t_2); \ +} while (0) + +// Loads 17 pixels each from rows r1 and r2 and generates 32 pixels. +#define UPSAMPLE_32PIXELS(r1, r2, out) { \ + const __m128i one = _mm_set1_epi8(1); \ + const __m128i a = _mm_loadu_si128((const __m128i*)&(r1)[0]); \ + const __m128i b = _mm_loadu_si128((const __m128i*)&(r1)[1]); \ + const __m128i c = _mm_loadu_si128((const __m128i*)&(r2)[0]); \ + const __m128i d = _mm_loadu_si128((const __m128i*)&(r2)[1]); \ + \ + const __m128i s = _mm_avg_epu8(a, d); /* s = (a + d + 1) / 2 */ \ + const __m128i t = _mm_avg_epu8(b, c); /* t = (b + c + 1) / 2 */ \ + const __m128i st = _mm_xor_si128(s, t); /* st = s^t */ \ + \ + const __m128i ad = _mm_xor_si128(a, d); /* ad = a^d */ \ + const __m128i bc = _mm_xor_si128(b, c); /* bc = b^c */ \ + \ + const __m128i t1 = _mm_or_si128(ad, bc); /* (a^d) | (b^c) */ \ + const __m128i t2 = _mm_or_si128(t1, st); /* (a^d) | (b^c) | (s^t) */ \ + const __m128i t3 = _mm_and_si128(t2, one); /* (a^d) | (b^c) | (s^t) & 1 */ \ + const __m128i t4 = _mm_avg_epu8(s, t); \ + const __m128i k = _mm_sub_epi8(t4, t3); /* k = (a + b + c + d) / 4 */ \ + __m128i diag1, diag2; \ + \ + GET_M(bc, t, diag1); /* diag1 = (a + 3b + 3c + d) / 8 */ \ + GET_M(ad, s, diag2); /* diag2 = (3a + b + c + 3d) / 8 */ \ + \ + /* pack the alternate pixels */ \ + PACK_AND_STORE(a, b, diag1, diag2, (out) + 0); /* store top */ \ + PACK_AND_STORE(c, d, diag2, diag1, (out) + 2 * 32); /* store bottom */ \ +} + +// Turn the macro into a function for reducing code-size when non-critical +static void Upsample32Pixels_SSE41(const uint8_t r1[], const uint8_t r2[], + uint8_t* const out) { + UPSAMPLE_32PIXELS(r1, r2, out); +} + +#define UPSAMPLE_LAST_BLOCK(tb, bb, num_pixels, out) { \ + uint8_t r1[17], r2[17]; \ + memcpy(r1, (tb), (num_pixels)); \ + memcpy(r2, (bb), (num_pixels)); \ + /* replicate last byte */ \ + memset(r1 + (num_pixels), r1[(num_pixels) - 1], 17 - (num_pixels)); \ + memset(r2 + (num_pixels), r2[(num_pixels) - 1], 17 - (num_pixels)); \ + /* using the shared function instead of the macro saves ~3k code size */ \ + Upsample32Pixels_SSE41(r1, r2, out); \ +} + +#define CONVERT2RGB_32(FUNC, XSTEP, top_y, bottom_y, \ + top_dst, bottom_dst, cur_x) do { \ + FUNC##32_SSE41((top_y) + (cur_x), r_u, r_v, (top_dst) + (cur_x) * (XSTEP)); \ + if ((bottom_y) != NULL) { \ + FUNC##32_SSE41((bottom_y) + (cur_x), r_u + 64, r_v + 64, \ + (bottom_dst) + (cur_x) * (XSTEP)); \ + } \ +} while (0) + +#define SSE4_UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \ +static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \ + const uint8_t* top_u, const uint8_t* top_v, \ + const uint8_t* cur_u, const uint8_t* cur_v, \ + uint8_t* top_dst, uint8_t* bottom_dst, int len) { \ + int uv_pos, pos; \ + /* 16byte-aligned array to cache reconstructed u and v */ \ + uint8_t uv_buf[14 * 32 + 15] = { 0 }; \ + uint8_t* const r_u = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~15); \ + uint8_t* const r_v = r_u + 32; \ + \ + assert(top_y != NULL); \ + { /* Treat the first pixel in regular way */ \ + const int u_diag = ((top_u[0] + cur_u[0]) >> 1) + 1; \ + const int v_diag = ((top_v[0] + cur_v[0]) >> 1) + 1; \ + const int u0_t = (top_u[0] + u_diag) >> 1; \ + const int v0_t = (top_v[0] + v_diag) >> 1; \ + FUNC(top_y[0], u0_t, v0_t, top_dst); \ + if (bottom_y != NULL) { \ + const int u0_b = (cur_u[0] + u_diag) >> 1; \ + const int v0_b = (cur_v[0] + v_diag) >> 1; \ + FUNC(bottom_y[0], u0_b, v0_b, bottom_dst); \ + } \ + } \ + /* For UPSAMPLE_32PIXELS, 17 u/v values must be read-able for each block */ \ + for (pos = 1, uv_pos = 0; pos + 32 + 1 <= len; pos += 32, uv_pos += 16) { \ + UPSAMPLE_32PIXELS(top_u + uv_pos, cur_u + uv_pos, r_u); \ + UPSAMPLE_32PIXELS(top_v + uv_pos, cur_v + uv_pos, r_v); \ + CONVERT2RGB_32(FUNC, XSTEP, top_y, bottom_y, top_dst, bottom_dst, pos); \ + } \ + if (len > 1) { \ + const int left_over = ((len + 1) >> 1) - (pos >> 1); \ + uint8_t* const tmp_top_dst = r_u + 4 * 32; \ + uint8_t* const tmp_bottom_dst = tmp_top_dst + 4 * 32; \ + uint8_t* const tmp_top = tmp_bottom_dst + 4 * 32; \ + uint8_t* const tmp_bottom = (bottom_y == NULL) ? NULL : tmp_top + 32; \ + assert(left_over > 0); \ + UPSAMPLE_LAST_BLOCK(top_u + uv_pos, cur_u + uv_pos, left_over, r_u); \ + UPSAMPLE_LAST_BLOCK(top_v + uv_pos, cur_v + uv_pos, left_over, r_v); \ + memcpy(tmp_top, top_y + pos, len - pos); \ + if (bottom_y != NULL) memcpy(tmp_bottom, bottom_y + pos, len - pos); \ + CONVERT2RGB_32(FUNC, XSTEP, tmp_top, tmp_bottom, tmp_top_dst, \ + tmp_bottom_dst, 0); \ + memcpy(top_dst + pos * (XSTEP), tmp_top_dst, (len - pos) * (XSTEP)); \ + if (bottom_y != NULL) { \ + memcpy(bottom_dst + pos * (XSTEP), tmp_bottom_dst, \ + (len - pos) * (XSTEP)); \ + } \ + } \ +} + +// SSE4 variants of the fancy upsampler. +SSE4_UPSAMPLE_FUNC(UpsampleRgbLinePair_SSE41, VP8YuvToRgb, 3) +SSE4_UPSAMPLE_FUNC(UpsampleBgrLinePair_SSE41, VP8YuvToBgr, 3) + +#undef GET_M +#undef PACK_AND_STORE +#undef UPSAMPLE_32PIXELS +#undef UPSAMPLE_LAST_BLOCK +#undef CONVERT2RGB +#undef CONVERT2RGB_32 +#undef SSE4_UPSAMPLE_FUNC + +#endif // WEBP_REDUCE_CSP + +//------------------------------------------------------------------------------ +// Entry point + +extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */]; + +extern void WebPInitUpsamplersSSE41(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplersSSE41(void) { +#if !defined(WEBP_REDUCE_CSP) + WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair_SSE41; + WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair_SSE41; +#endif // WEBP_REDUCE_CSP +} + +#endif // FANCY_UPSAMPLING + +//------------------------------------------------------------------------------ + +extern WebPYUV444Converter WebPYUV444Converters[/* MODE_LAST */]; +extern void WebPInitYUV444ConvertersSSE41(void); + +#define YUV444_FUNC(FUNC_NAME, CALL, CALL_C, XSTEP) \ +extern void CALL_C(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ + uint8_t* dst, int len); \ +static void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ + uint8_t* dst, int len) { \ + int i; \ + const int max_len = len & ~31; \ + for (i = 0; i < max_len; i += 32) { \ + CALL(y + i, u + i, v + i, dst + i * (XSTEP)); \ + } \ + if (i < len) { /* C-fallback */ \ + CALL_C(y + i, u + i, v + i, dst + i * (XSTEP), len - i); \ + } \ +} + +#if !defined(WEBP_REDUCE_CSP) +YUV444_FUNC(Yuv444ToRgb_SSE41, VP8YuvToRgb32_SSE41, WebPYuv444ToRgb_C, 3); +YUV444_FUNC(Yuv444ToBgr_SSE41, VP8YuvToBgr32_SSE41, WebPYuv444ToBgr_C, 3); +#endif // WEBP_REDUCE_CSP + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444ConvertersSSE41(void) { +#if !defined(WEBP_REDUCE_CSP) + WebPYUV444Converters[MODE_RGB] = Yuv444ToRgb_SSE41; + WebPYUV444Converters[MODE_BGR] = Yuv444ToBgr_SSE41; +#endif // WEBP_REDUCE_CSP +} + +#else + +WEBP_DSP_INIT_STUB(WebPInitYUV444ConvertersSSE41) + +#endif // WEBP_USE_SSE41 + +#if !(defined(FANCY_UPSAMPLING) && defined(WEBP_USE_SSE41)) +WEBP_DSP_INIT_STUB(WebPInitUpsamplersSSE41) +#endif diff --git a/third-party/webp/libwebp/src/dsp/yuv.c b/third-party/webp/libwebp/src/dsp/yuv.c new file mode 100644 index 0000000000..8a04b85d82 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/yuv.c @@ -0,0 +1,245 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// YUV->RGB conversion functions +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/yuv.h" + +#include +#include + +//----------------------------------------------------------------------------- +// Plain-C version + +#define ROW_FUNC(FUNC_NAME, FUNC, XSTEP) \ +static void FUNC_NAME(const uint8_t* y, \ + const uint8_t* u, const uint8_t* v, \ + uint8_t* dst, int len) { \ + const uint8_t* const end = dst + (len & ~1) * (XSTEP); \ + while (dst != end) { \ + FUNC(y[0], u[0], v[0], dst); \ + FUNC(y[1], u[0], v[0], dst + (XSTEP)); \ + y += 2; \ + ++u; \ + ++v; \ + dst += 2 * (XSTEP); \ + } \ + if (len & 1) { \ + FUNC(y[0], u[0], v[0], dst); \ + } \ +} \ + +// All variants implemented. +ROW_FUNC(YuvToRgbRow, VP8YuvToRgb, 3) +ROW_FUNC(YuvToBgrRow, VP8YuvToBgr, 3) +ROW_FUNC(YuvToRgbaRow, VP8YuvToRgba, 4) +ROW_FUNC(YuvToBgraRow, VP8YuvToBgra, 4) +ROW_FUNC(YuvToArgbRow, VP8YuvToArgb, 4) +ROW_FUNC(YuvToRgba4444Row, VP8YuvToRgba4444, 2) +ROW_FUNC(YuvToRgb565Row, VP8YuvToRgb565, 2) + +#undef ROW_FUNC + +// Main call for processing a plane with a WebPSamplerRowFunc function: +void WebPSamplerProcessPlane(const uint8_t* y, int y_stride, + const uint8_t* u, const uint8_t* v, int uv_stride, + uint8_t* dst, int dst_stride, + int width, int height, WebPSamplerRowFunc func) { + int j; + for (j = 0; j < height; ++j) { + func(y, u, v, dst, width); + y += y_stride; + if (j & 1) { + u += uv_stride; + v += uv_stride; + } + dst += dst_stride; + } +} + +//----------------------------------------------------------------------------- +// Main call + +WebPSamplerRowFunc WebPSamplers[MODE_LAST]; + +extern VP8CPUInfo VP8GetCPUInfo; +extern void WebPInitSamplersSSE2(void); +extern void WebPInitSamplersSSE41(void); +extern void WebPInitSamplersMIPS32(void); +extern void WebPInitSamplersMIPSdspR2(void); + +WEBP_DSP_INIT_FUNC(WebPInitSamplers) { + WebPSamplers[MODE_RGB] = YuvToRgbRow; + WebPSamplers[MODE_RGBA] = YuvToRgbaRow; + WebPSamplers[MODE_BGR] = YuvToBgrRow; + WebPSamplers[MODE_BGRA] = YuvToBgraRow; + WebPSamplers[MODE_ARGB] = YuvToArgbRow; + WebPSamplers[MODE_RGBA_4444] = YuvToRgba4444Row; + WebPSamplers[MODE_RGB_565] = YuvToRgb565Row; + WebPSamplers[MODE_rgbA] = YuvToRgbaRow; + WebPSamplers[MODE_bgrA] = YuvToBgraRow; + WebPSamplers[MODE_Argb] = YuvToArgbRow; + WebPSamplers[MODE_rgbA_4444] = YuvToRgba4444Row; + + // If defined, use CPUInfo() to overwrite some pointers with faster versions. + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_HAVE_SSE2) + if (VP8GetCPUInfo(kSSE2)) { + WebPInitSamplersSSE2(); + } +#endif // WEBP_HAVE_SSE2 +#if defined(WEBP_HAVE_SSE41) + if (VP8GetCPUInfo(kSSE4_1)) { + WebPInitSamplersSSE41(); + } +#endif // WEBP_HAVE_SSE41 +#if defined(WEBP_USE_MIPS32) + if (VP8GetCPUInfo(kMIPS32)) { + WebPInitSamplersMIPS32(); + } +#endif // WEBP_USE_MIPS32 +#if defined(WEBP_USE_MIPS_DSP_R2) + if (VP8GetCPUInfo(kMIPSdspR2)) { + WebPInitSamplersMIPSdspR2(); + } +#endif // WEBP_USE_MIPS_DSP_R2 + } +} + +//----------------------------------------------------------------------------- +// ARGB -> YUV converters + +static void ConvertARGBToY_C(const uint32_t* argb, uint8_t* y, int width) { + int i; + for (i = 0; i < width; ++i) { + const uint32_t p = argb[i]; + y[i] = VP8RGBToY((p >> 16) & 0xff, (p >> 8) & 0xff, (p >> 0) & 0xff, + YUV_HALF); + } +} + +void WebPConvertARGBToUV_C(const uint32_t* argb, uint8_t* u, uint8_t* v, + int src_width, int do_store) { + // No rounding. Last pixel is dealt with separately. + const int uv_width = src_width >> 1; + int i; + for (i = 0; i < uv_width; ++i) { + const uint32_t v0 = argb[2 * i + 0]; + const uint32_t v1 = argb[2 * i + 1]; + // VP8RGBToU/V expects four accumulated pixels. Hence we need to + // scale r/g/b value by a factor 2. We just shift v0/v1 one bit less. + const int r = ((v0 >> 15) & 0x1fe) + ((v1 >> 15) & 0x1fe); + const int g = ((v0 >> 7) & 0x1fe) + ((v1 >> 7) & 0x1fe); + const int b = ((v0 << 1) & 0x1fe) + ((v1 << 1) & 0x1fe); + const int tmp_u = VP8RGBToU(r, g, b, YUV_HALF << 2); + const int tmp_v = VP8RGBToV(r, g, b, YUV_HALF << 2); + if (do_store) { + u[i] = tmp_u; + v[i] = tmp_v; + } else { + // Approximated average-of-four. But it's an acceptable diff. + u[i] = (u[i] + tmp_u + 1) >> 1; + v[i] = (v[i] + tmp_v + 1) >> 1; + } + } + if (src_width & 1) { // last pixel + const uint32_t v0 = argb[2 * i + 0]; + const int r = (v0 >> 14) & 0x3fc; + const int g = (v0 >> 6) & 0x3fc; + const int b = (v0 << 2) & 0x3fc; + const int tmp_u = VP8RGBToU(r, g, b, YUV_HALF << 2); + const int tmp_v = VP8RGBToV(r, g, b, YUV_HALF << 2); + if (do_store) { + u[i] = tmp_u; + v[i] = tmp_v; + } else { + u[i] = (u[i] + tmp_u + 1) >> 1; + v[i] = (v[i] + tmp_v + 1) >> 1; + } + } +} + +//----------------------------------------------------------------------------- + +static void ConvertRGB24ToY_C(const uint8_t* rgb, uint8_t* y, int width) { + int i; + for (i = 0; i < width; ++i, rgb += 3) { + y[i] = VP8RGBToY(rgb[0], rgb[1], rgb[2], YUV_HALF); + } +} + +static void ConvertBGR24ToY_C(const uint8_t* bgr, uint8_t* y, int width) { + int i; + for (i = 0; i < width; ++i, bgr += 3) { + y[i] = VP8RGBToY(bgr[2], bgr[1], bgr[0], YUV_HALF); + } +} + +void WebPConvertRGBA32ToUV_C(const uint16_t* rgb, + uint8_t* u, uint8_t* v, int width) { + int i; + for (i = 0; i < width; i += 1, rgb += 4) { + const int r = rgb[0], g = rgb[1], b = rgb[2]; + u[i] = VP8RGBToU(r, g, b, YUV_HALF << 2); + v[i] = VP8RGBToV(r, g, b, YUV_HALF << 2); + } +} + +//----------------------------------------------------------------------------- + +void (*WebPConvertRGB24ToY)(const uint8_t* rgb, uint8_t* y, int width); +void (*WebPConvertBGR24ToY)(const uint8_t* bgr, uint8_t* y, int width); +void (*WebPConvertRGBA32ToUV)(const uint16_t* rgb, + uint8_t* u, uint8_t* v, int width); + +void (*WebPConvertARGBToY)(const uint32_t* argb, uint8_t* y, int width); +void (*WebPConvertARGBToUV)(const uint32_t* argb, uint8_t* u, uint8_t* v, + int src_width, int do_store); + +extern void WebPInitConvertARGBToYUVSSE2(void); +extern void WebPInitConvertARGBToYUVSSE41(void); +extern void WebPInitConvertARGBToYUVNEON(void); + +WEBP_DSP_INIT_FUNC(WebPInitConvertARGBToYUV) { + WebPConvertARGBToY = ConvertARGBToY_C; + WebPConvertARGBToUV = WebPConvertARGBToUV_C; + + WebPConvertRGB24ToY = ConvertRGB24ToY_C; + WebPConvertBGR24ToY = ConvertBGR24ToY_C; + + WebPConvertRGBA32ToUV = WebPConvertRGBA32ToUV_C; + + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_HAVE_SSE2) + if (VP8GetCPUInfo(kSSE2)) { + WebPInitConvertARGBToYUVSSE2(); + } +#endif // WEBP_HAVE_SSE2 +#if defined(WEBP_HAVE_SSE41) + if (VP8GetCPUInfo(kSSE4_1)) { + WebPInitConvertARGBToYUVSSE41(); + } +#endif // WEBP_HAVE_SSE41 + } + +#if defined(WEBP_HAVE_NEON) + if (WEBP_NEON_OMIT_C_CODE || + (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) { + WebPInitConvertARGBToYUVNEON(); + } +#endif // WEBP_HAVE_NEON + + assert(WebPConvertARGBToY != NULL); + assert(WebPConvertARGBToUV != NULL); + assert(WebPConvertRGB24ToY != NULL); + assert(WebPConvertBGR24ToY != NULL); + assert(WebPConvertRGBA32ToUV != NULL); +} diff --git a/third-party/webp/libwebp/src/dsp/yuv.h b/third-party/webp/libwebp/src/dsp/yuv.h new file mode 100644 index 0000000000..66a397d117 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/yuv.h @@ -0,0 +1,210 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// inline YUV<->RGB conversion function +// +// The exact naming is Y'CbCr, following the ITU-R BT.601 standard. +// More information at: https://en.wikipedia.org/wiki/YCbCr +// Y = 0.2569 * R + 0.5044 * G + 0.0979 * B + 16 +// U = -0.1483 * R - 0.2911 * G + 0.4394 * B + 128 +// V = 0.4394 * R - 0.3679 * G - 0.0715 * B + 128 +// We use 16bit fixed point operations for RGB->YUV conversion (YUV_FIX). +// +// For the Y'CbCr to RGB conversion, the BT.601 specification reads: +// R = 1.164 * (Y-16) + 1.596 * (V-128) +// G = 1.164 * (Y-16) - 0.813 * (V-128) - 0.391 * (U-128) +// B = 1.164 * (Y-16) + 2.018 * (U-128) +// where Y is in the [16,235] range, and U/V in the [16,240] range. +// +// The fixed-point implementation used here is: +// R = (19077 . y + 26149 . v - 14234) >> 6 +// G = (19077 . y - 6419 . u - 13320 . v + 8708) >> 6 +// B = (19077 . y + 33050 . u - 17685) >> 6 +// where the '.' operator is the mulhi_epu16 variant: +// a . b = ((a << 8) * b) >> 16 +// that preserves 8 bits of fractional precision before final descaling. + +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_DSP_YUV_H_ +#define WEBP_DSP_YUV_H_ + +#include "src/dsp/dsp.h" +#include "src/dec/vp8_dec.h" + +//------------------------------------------------------------------------------ +// YUV -> RGB conversion + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + YUV_FIX = 16, // fixed-point precision for RGB->YUV + YUV_HALF = 1 << (YUV_FIX - 1), + + YUV_FIX2 = 6, // fixed-point precision for YUV->RGB + YUV_MASK2 = (256 << YUV_FIX2) - 1 +}; + +//------------------------------------------------------------------------------ +// slower on x86 by ~7-8%, but bit-exact with the SSE2/NEON version + +static WEBP_INLINE int MultHi(int v, int coeff) { // _mm_mulhi_epu16 emulation + return (v * coeff) >> 8; +} + +static WEBP_INLINE int VP8Clip8(int v) { + return ((v & ~YUV_MASK2) == 0) ? (v >> YUV_FIX2) : (v < 0) ? 0 : 255; +} + +static WEBP_INLINE int VP8YUVToR(int y, int v) { + return VP8Clip8(MultHi(y, 19077) + MultHi(v, 26149) - 14234); +} + +static WEBP_INLINE int VP8YUVToG(int y, int u, int v) { + return VP8Clip8(MultHi(y, 19077) - MultHi(u, 6419) - MultHi(v, 13320) + 8708); +} + +static WEBP_INLINE int VP8YUVToB(int y, int u) { + return VP8Clip8(MultHi(y, 19077) + MultHi(u, 33050) - 17685); +} + +static WEBP_INLINE void VP8YuvToRgb(int y, int u, int v, + uint8_t* const rgb) { + rgb[0] = VP8YUVToR(y, v); + rgb[1] = VP8YUVToG(y, u, v); + rgb[2] = VP8YUVToB(y, u); +} + +static WEBP_INLINE void VP8YuvToBgr(int y, int u, int v, + uint8_t* const bgr) { + bgr[0] = VP8YUVToB(y, u); + bgr[1] = VP8YUVToG(y, u, v); + bgr[2] = VP8YUVToR(y, v); +} + +static WEBP_INLINE void VP8YuvToRgb565(int y, int u, int v, + uint8_t* const rgb) { + const int r = VP8YUVToR(y, v); // 5 usable bits + const int g = VP8YUVToG(y, u, v); // 6 usable bits + const int b = VP8YUVToB(y, u); // 5 usable bits + const int rg = (r & 0xf8) | (g >> 5); + const int gb = ((g << 3) & 0xe0) | (b >> 3); +#if (WEBP_SWAP_16BIT_CSP == 1) + rgb[0] = gb; + rgb[1] = rg; +#else + rgb[0] = rg; + rgb[1] = gb; +#endif +} + +static WEBP_INLINE void VP8YuvToRgba4444(int y, int u, int v, + uint8_t* const argb) { + const int r = VP8YUVToR(y, v); // 4 usable bits + const int g = VP8YUVToG(y, u, v); // 4 usable bits + const int b = VP8YUVToB(y, u); // 4 usable bits + const int rg = (r & 0xf0) | (g >> 4); + const int ba = (b & 0xf0) | 0x0f; // overwrite the lower 4 bits +#if (WEBP_SWAP_16BIT_CSP == 1) + argb[0] = ba; + argb[1] = rg; +#else + argb[0] = rg; + argb[1] = ba; +#endif +} + +//----------------------------------------------------------------------------- +// Alpha handling variants + +static WEBP_INLINE void VP8YuvToArgb(uint8_t y, uint8_t u, uint8_t v, + uint8_t* const argb) { + argb[0] = 0xff; + VP8YuvToRgb(y, u, v, argb + 1); +} + +static WEBP_INLINE void VP8YuvToBgra(uint8_t y, uint8_t u, uint8_t v, + uint8_t* const bgra) { + VP8YuvToBgr(y, u, v, bgra); + bgra[3] = 0xff; +} + +static WEBP_INLINE void VP8YuvToRgba(uint8_t y, uint8_t u, uint8_t v, + uint8_t* const rgba) { + VP8YuvToRgb(y, u, v, rgba); + rgba[3] = 0xff; +} + +//----------------------------------------------------------------------------- +// SSE2 extra functions (mostly for upsampling_sse2.c) + +#if defined(WEBP_USE_SSE2) + +// Process 32 pixels and store the result (16b, 24b or 32b per pixel) in *dst. +void VP8YuvToRgba32_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst); +void VP8YuvToRgb32_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst); +void VP8YuvToBgra32_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst); +void VP8YuvToBgr32_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst); +void VP8YuvToArgb32_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst); +void VP8YuvToRgba444432_SSE2(const uint8_t* y, const uint8_t* u, + const uint8_t* v, uint8_t* dst); +void VP8YuvToRgb56532_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst); + +#endif // WEBP_USE_SSE2 + +//----------------------------------------------------------------------------- +// SSE41 extra functions (mostly for upsampling_sse41.c) + +#if defined(WEBP_USE_SSE41) + +// Process 32 pixels and store the result (16b, 24b or 32b per pixel) in *dst. +void VP8YuvToRgb32_SSE41(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst); +void VP8YuvToBgr32_SSE41(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst); + +#endif // WEBP_USE_SSE41 + +//------------------------------------------------------------------------------ +// RGB -> YUV conversion + +// Stub functions that can be called with various rounding values: +static WEBP_INLINE int VP8ClipUV(int uv, int rounding) { + uv = (uv + rounding + (128 << (YUV_FIX + 2))) >> (YUV_FIX + 2); + return ((uv & ~0xff) == 0) ? uv : (uv < 0) ? 0 : 255; +} + +static WEBP_INLINE int VP8RGBToY(int r, int g, int b, int rounding) { + const int luma = 16839 * r + 33059 * g + 6420 * b; + return (luma + rounding + (16 << YUV_FIX)) >> YUV_FIX; // no need to clip +} + +static WEBP_INLINE int VP8RGBToU(int r, int g, int b, int rounding) { + const int u = -9719 * r - 19081 * g + 28800 * b; + return VP8ClipUV(u, rounding); +} + +static WEBP_INLINE int VP8RGBToV(int r, int g, int b, int rounding) { + const int v = +28800 * r - 24116 * g - 4684 * b; + return VP8ClipUV(v, rounding); +} + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_DSP_YUV_H_ diff --git a/third-party/webp/libwebp/src/dsp/yuv_mips32.c b/third-party/webp/libwebp/src/dsp/yuv_mips32.c new file mode 100644 index 0000000000..9d0a887824 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/yuv_mips32.c @@ -0,0 +1,103 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MIPS version of YUV to RGB upsampling functions. +// +// Author(s): Djordje Pesut (djordje.pesut@imgtec.com) +// Jovan Zelincevic (jovan.zelincevic@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MIPS32) + +#include "src/dsp/yuv.h" + +//------------------------------------------------------------------------------ +// simple point-sampling + +#define ROW_FUNC(FUNC_NAME, XSTEP, R, G, B, A) \ +static void FUNC_NAME(const uint8_t* y, \ + const uint8_t* u, const uint8_t* v, \ + uint8_t* dst, int len) { \ + int i, r, g, b; \ + int temp0, temp1, temp2, temp3, temp4; \ + for (i = 0; i < (len >> 1); i++) { \ + temp1 = MultHi(v[0], 26149); \ + temp3 = MultHi(v[0], 13320); \ + temp2 = MultHi(u[0], 6419); \ + temp4 = MultHi(u[0], 33050); \ + temp0 = MultHi(y[0], 19077); \ + temp1 -= 14234; \ + temp3 -= 8708; \ + temp2 += temp3; \ + temp4 -= 17685; \ + r = VP8Clip8(temp0 + temp1); \ + g = VP8Clip8(temp0 - temp2); \ + b = VP8Clip8(temp0 + temp4); \ + temp0 = MultHi(y[1], 19077); \ + dst[R] = r; \ + dst[G] = g; \ + dst[B] = b; \ + if (A) dst[A] = 0xff; \ + r = VP8Clip8(temp0 + temp1); \ + g = VP8Clip8(temp0 - temp2); \ + b = VP8Clip8(temp0 + temp4); \ + dst[R + XSTEP] = r; \ + dst[G + XSTEP] = g; \ + dst[B + XSTEP] = b; \ + if (A) dst[A + XSTEP] = 0xff; \ + y += 2; \ + ++u; \ + ++v; \ + dst += 2 * XSTEP; \ + } \ + if (len & 1) { \ + temp1 = MultHi(v[0], 26149); \ + temp3 = MultHi(v[0], 13320); \ + temp2 = MultHi(u[0], 6419); \ + temp4 = MultHi(u[0], 33050); \ + temp0 = MultHi(y[0], 19077); \ + temp1 -= 14234; \ + temp3 -= 8708; \ + temp2 += temp3; \ + temp4 -= 17685; \ + r = VP8Clip8(temp0 + temp1); \ + g = VP8Clip8(temp0 - temp2); \ + b = VP8Clip8(temp0 + temp4); \ + dst[R] = r; \ + dst[G] = g; \ + dst[B] = b; \ + if (A) dst[A] = 0xff; \ + } \ +} + +ROW_FUNC(YuvToRgbRow_MIPS32, 3, 0, 1, 2, 0) +ROW_FUNC(YuvToRgbaRow_MIPS32, 4, 0, 1, 2, 3) +ROW_FUNC(YuvToBgrRow_MIPS32, 3, 2, 1, 0, 0) +ROW_FUNC(YuvToBgraRow_MIPS32, 4, 2, 1, 0, 3) + +#undef ROW_FUNC + +//------------------------------------------------------------------------------ +// Entry point + +extern void WebPInitSamplersMIPS32(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplersMIPS32(void) { + WebPSamplers[MODE_RGB] = YuvToRgbRow_MIPS32; + WebPSamplers[MODE_RGBA] = YuvToRgbaRow_MIPS32; + WebPSamplers[MODE_BGR] = YuvToBgrRow_MIPS32; + WebPSamplers[MODE_BGRA] = YuvToBgraRow_MIPS32; +} + +#else // !WEBP_USE_MIPS32 + +WEBP_DSP_INIT_STUB(WebPInitSamplersMIPS32) + +#endif // WEBP_USE_MIPS32 diff --git a/third-party/webp/libwebp/src/dsp/yuv_mips_dsp_r2.c b/third-party/webp/libwebp/src/dsp/yuv_mips_dsp_r2.c new file mode 100644 index 0000000000..cc8afcc756 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/yuv_mips_dsp_r2.c @@ -0,0 +1,134 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// MIPS DSPr2 version of YUV to RGB upsampling functions. +// +// Author(s): Branimir Vasic (branimir.vasic@imgtec.com) +// Djordje Pesut (djordje.pesut@imgtec.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_MIPS_DSP_R2) + +#include "src/dsp/yuv.h" + +//------------------------------------------------------------------------------ +// simple point-sampling + +#define ROW_FUNC_PART_1() \ + "lbu %[temp3], 0(%[v]) \n\t" \ + "lbu %[temp4], 0(%[u]) \n\t" \ + "lbu %[temp0], 0(%[y]) \n\t" \ + "mul %[temp1], %[t_con_1], %[temp3] \n\t" \ + "mul %[temp3], %[t_con_2], %[temp3] \n\t" \ + "mul %[temp2], %[t_con_3], %[temp4] \n\t" \ + "mul %[temp4], %[t_con_4], %[temp4] \n\t" \ + "mul %[temp0], %[t_con_5], %[temp0] \n\t" \ + "subu %[temp1], %[temp1], %[t_con_6] \n\t" \ + "subu %[temp3], %[temp3], %[t_con_7] \n\t" \ + "addu %[temp2], %[temp2], %[temp3] \n\t" \ + "subu %[temp4], %[temp4], %[t_con_8] \n\t" \ + +#define ROW_FUNC_PART_2(R, G, B, K) \ + "addu %[temp5], %[temp0], %[temp1] \n\t" \ + "subu %[temp6], %[temp0], %[temp2] \n\t" \ + "addu %[temp7], %[temp0], %[temp4] \n\t" \ +".if " #K " \n\t" \ + "lbu %[temp0], 1(%[y]) \n\t" \ +".endif \n\t" \ + "shll_s.w %[temp5], %[temp5], 17 \n\t" \ + "shll_s.w %[temp6], %[temp6], 17 \n\t" \ +".if " #K " \n\t" \ + "mul %[temp0], %[t_con_5], %[temp0] \n\t" \ +".endif \n\t" \ + "shll_s.w %[temp7], %[temp7], 17 \n\t" \ + "precrqu_s.qb.ph %[temp5], %[temp5], $zero \n\t" \ + "precrqu_s.qb.ph %[temp6], %[temp6], $zero \n\t" \ + "precrqu_s.qb.ph %[temp7], %[temp7], $zero \n\t" \ + "srl %[temp5], %[temp5], 24 \n\t" \ + "srl %[temp6], %[temp6], 24 \n\t" \ + "srl %[temp7], %[temp7], 24 \n\t" \ + "sb %[temp5], " #R "(%[dst]) \n\t" \ + "sb %[temp6], " #G "(%[dst]) \n\t" \ + "sb %[temp7], " #B "(%[dst]) \n\t" \ + +#define ASM_CLOBBER_LIST() \ + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), \ + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), \ + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7) \ + : [t_con_1]"r"(t_con_1), [t_con_2]"r"(t_con_2), [t_con_3]"r"(t_con_3), \ + [t_con_4]"r"(t_con_4), [t_con_5]"r"(t_con_5), [t_con_6]"r"(t_con_6), \ + [u]"r"(u), [v]"r"(v), [y]"r"(y), [dst]"r"(dst), \ + [t_con_7]"r"(t_con_7), [t_con_8]"r"(t_con_8) \ + : "memory", "hi", "lo" \ + +#define ROW_FUNC(FUNC_NAME, XSTEP, R, G, B, A) \ +static void FUNC_NAME(const uint8_t* y, \ + const uint8_t* u, const uint8_t* v, \ + uint8_t* dst, int len) { \ + int i; \ + uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; \ + const int t_con_1 = 26149; \ + const int t_con_2 = 13320; \ + const int t_con_3 = 6419; \ + const int t_con_4 = 33050; \ + const int t_con_5 = 19077; \ + const int t_con_6 = 14234; \ + const int t_con_7 = 8708; \ + const int t_con_8 = 17685; \ + for (i = 0; i < (len >> 1); i++) { \ + __asm__ volatile ( \ + ROW_FUNC_PART_1() \ + ROW_FUNC_PART_2(R, G, B, 1) \ + ROW_FUNC_PART_2(R + XSTEP, G + XSTEP, B + XSTEP, 0) \ + ASM_CLOBBER_LIST() \ + ); \ + if (A) dst[A] = dst[A + XSTEP] = 0xff; \ + y += 2; \ + ++u; \ + ++v; \ + dst += 2 * XSTEP; \ + } \ + if (len & 1) { \ + __asm__ volatile ( \ + ROW_FUNC_PART_1() \ + ROW_FUNC_PART_2(R, G, B, 0) \ + ASM_CLOBBER_LIST() \ + ); \ + if (A) dst[A] = 0xff; \ + } \ +} + +ROW_FUNC(YuvToRgbRow_MIPSdspR2, 3, 0, 1, 2, 0) +ROW_FUNC(YuvToRgbaRow_MIPSdspR2, 4, 0, 1, 2, 3) +ROW_FUNC(YuvToBgrRow_MIPSdspR2, 3, 2, 1, 0, 0) +ROW_FUNC(YuvToBgraRow_MIPSdspR2, 4, 2, 1, 0, 3) + +#undef ROW_FUNC +#undef ASM_CLOBBER_LIST +#undef ROW_FUNC_PART_2 +#undef ROW_FUNC_PART_1 + +//------------------------------------------------------------------------------ +// Entry point + +extern void WebPInitSamplersMIPSdspR2(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplersMIPSdspR2(void) { + WebPSamplers[MODE_RGB] = YuvToRgbRow_MIPSdspR2; + WebPSamplers[MODE_RGBA] = YuvToRgbaRow_MIPSdspR2; + WebPSamplers[MODE_BGR] = YuvToBgrRow_MIPSdspR2; + WebPSamplers[MODE_BGRA] = YuvToBgraRow_MIPSdspR2; +} + +#else // !WEBP_USE_MIPS_DSP_R2 + +WEBP_DSP_INIT_STUB(WebPInitSamplersMIPSdspR2) + +#endif // WEBP_USE_MIPS_DSP_R2 diff --git a/third-party/webp/libwebp/src/dsp/yuv_neon.c b/third-party/webp/libwebp/src/dsp/yuv_neon.c new file mode 100644 index 0000000000..ff77b00980 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/yuv_neon.c @@ -0,0 +1,180 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// YUV->RGB conversion functions +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/yuv.h" + +#if defined(WEBP_USE_NEON) + +#include +#include + +#include "src/dsp/neon.h" + +//----------------------------------------------------------------------------- + +static uint8x8_t ConvertRGBToY_NEON(const uint8x8_t R, + const uint8x8_t G, + const uint8x8_t B) { + const uint16x8_t r = vmovl_u8(R); + const uint16x8_t g = vmovl_u8(G); + const uint16x8_t b = vmovl_u8(B); + const uint16x4_t r_lo = vget_low_u16(r); + const uint16x4_t r_hi = vget_high_u16(r); + const uint16x4_t g_lo = vget_low_u16(g); + const uint16x4_t g_hi = vget_high_u16(g); + const uint16x4_t b_lo = vget_low_u16(b); + const uint16x4_t b_hi = vget_high_u16(b); + const uint32x4_t tmp0_lo = vmull_n_u16( r_lo, 16839u); + const uint32x4_t tmp0_hi = vmull_n_u16( r_hi, 16839u); + const uint32x4_t tmp1_lo = vmlal_n_u16(tmp0_lo, g_lo, 33059u); + const uint32x4_t tmp1_hi = vmlal_n_u16(tmp0_hi, g_hi, 33059u); + const uint32x4_t tmp2_lo = vmlal_n_u16(tmp1_lo, b_lo, 6420u); + const uint32x4_t tmp2_hi = vmlal_n_u16(tmp1_hi, b_hi, 6420u); + const uint16x8_t Y1 = vcombine_u16(vrshrn_n_u32(tmp2_lo, 16), + vrshrn_n_u32(tmp2_hi, 16)); + const uint16x8_t Y2 = vaddq_u16(Y1, vdupq_n_u16(16)); + return vqmovn_u16(Y2); +} + +static void ConvertRGB24ToY_NEON(const uint8_t* rgb, uint8_t* y, int width) { + int i; + for (i = 0; i + 8 <= width; i += 8, rgb += 3 * 8) { + const uint8x8x3_t RGB = vld3_u8(rgb); + const uint8x8_t Y = ConvertRGBToY_NEON(RGB.val[0], RGB.val[1], RGB.val[2]); + vst1_u8(y + i, Y); + } + for (; i < width; ++i, rgb += 3) { // left-over + y[i] = VP8RGBToY(rgb[0], rgb[1], rgb[2], YUV_HALF); + } +} + +static void ConvertBGR24ToY_NEON(const uint8_t* bgr, uint8_t* y, int width) { + int i; + for (i = 0; i + 8 <= width; i += 8, bgr += 3 * 8) { + const uint8x8x3_t BGR = vld3_u8(bgr); + const uint8x8_t Y = ConvertRGBToY_NEON(BGR.val[2], BGR.val[1], BGR.val[0]); + vst1_u8(y + i, Y); + } + for (; i < width; ++i, bgr += 3) { // left-over + y[i] = VP8RGBToY(bgr[2], bgr[1], bgr[0], YUV_HALF); + } +} + +static void ConvertARGBToY_NEON(const uint32_t* argb, uint8_t* y, int width) { + int i; + for (i = 0; i + 8 <= width; i += 8) { + const uint8x8x4_t RGB = vld4_u8((const uint8_t*)&argb[i]); + const uint8x8_t Y = ConvertRGBToY_NEON(RGB.val[2], RGB.val[1], RGB.val[0]); + vst1_u8(y + i, Y); + } + for (; i < width; ++i) { // left-over + const uint32_t p = argb[i]; + y[i] = VP8RGBToY((p >> 16) & 0xff, (p >> 8) & 0xff, (p >> 0) & 0xff, + YUV_HALF); + } +} + +//----------------------------------------------------------------------------- + +// computes: DST_s16 = [(C0 * r + C1 * g + C2 * b) >> 16] + CST +#define MULTIPLY_16b_PREAMBLE(r, g, b) \ + const int16x4_t r_lo = vreinterpret_s16_u16(vget_low_u16(r)); \ + const int16x4_t r_hi = vreinterpret_s16_u16(vget_high_u16(r)); \ + const int16x4_t g_lo = vreinterpret_s16_u16(vget_low_u16(g)); \ + const int16x4_t g_hi = vreinterpret_s16_u16(vget_high_u16(g)); \ + const int16x4_t b_lo = vreinterpret_s16_u16(vget_low_u16(b)); \ + const int16x4_t b_hi = vreinterpret_s16_u16(vget_high_u16(b)) + +#define MULTIPLY_16b(C0, C1, C2, CST, DST_s16) do { \ + const int32x4_t tmp0_lo = vmull_n_s16( r_lo, C0); \ + const int32x4_t tmp0_hi = vmull_n_s16( r_hi, C0); \ + const int32x4_t tmp1_lo = vmlal_n_s16(tmp0_lo, g_lo, C1); \ + const int32x4_t tmp1_hi = vmlal_n_s16(tmp0_hi, g_hi, C1); \ + const int32x4_t tmp2_lo = vmlal_n_s16(tmp1_lo, b_lo, C2); \ + const int32x4_t tmp2_hi = vmlal_n_s16(tmp1_hi, b_hi, C2); \ + const int16x8_t tmp3 = vcombine_s16(vshrn_n_s32(tmp2_lo, 16), \ + vshrn_n_s32(tmp2_hi, 16)); \ + DST_s16 = vaddq_s16(tmp3, vdupq_n_s16(CST)); \ +} while (0) + +// This needs to be a macro, since (128 << SHIFT) needs to be an immediate. +#define CONVERT_RGB_TO_UV(r, g, b, SHIFT, U_DST, V_DST) do { \ + MULTIPLY_16b_PREAMBLE(r, g, b); \ + MULTIPLY_16b(-9719, -19081, 28800, 128 << SHIFT, U_DST); \ + MULTIPLY_16b(28800, -24116, -4684, 128 << SHIFT, V_DST); \ +} while (0) + +static void ConvertRGBA32ToUV_NEON(const uint16_t* rgb, + uint8_t* u, uint8_t* v, int width) { + int i; + for (i = 0; i + 8 <= width; i += 8, rgb += 4 * 8) { + const uint16x8x4_t RGB = vld4q_u16((const uint16_t*)rgb); + int16x8_t U, V; + CONVERT_RGB_TO_UV(RGB.val[0], RGB.val[1], RGB.val[2], 2, U, V); + vst1_u8(u + i, vqrshrun_n_s16(U, 2)); + vst1_u8(v + i, vqrshrun_n_s16(V, 2)); + } + for (; i < width; i += 1, rgb += 4) { + const int r = rgb[0], g = rgb[1], b = rgb[2]; + u[i] = VP8RGBToU(r, g, b, YUV_HALF << 2); + v[i] = VP8RGBToV(r, g, b, YUV_HALF << 2); + } +} + +static void ConvertARGBToUV_NEON(const uint32_t* argb, uint8_t* u, uint8_t* v, + int src_width, int do_store) { + int i; + for (i = 0; i + 16 <= src_width; i += 16, u += 8, v += 8) { + const uint8x16x4_t RGB = vld4q_u8((const uint8_t*)&argb[i]); + const uint16x8_t R = vpaddlq_u8(RGB.val[2]); // pair-wise adds + const uint16x8_t G = vpaddlq_u8(RGB.val[1]); + const uint16x8_t B = vpaddlq_u8(RGB.val[0]); + int16x8_t U_tmp, V_tmp; + CONVERT_RGB_TO_UV(R, G, B, 1, U_tmp, V_tmp); + { + const uint8x8_t U = vqrshrun_n_s16(U_tmp, 1); + const uint8x8_t V = vqrshrun_n_s16(V_tmp, 1); + if (do_store) { + vst1_u8(u, U); + vst1_u8(v, V); + } else { + const uint8x8_t prev_u = vld1_u8(u); + const uint8x8_t prev_v = vld1_u8(v); + vst1_u8(u, vrhadd_u8(U, prev_u)); + vst1_u8(v, vrhadd_u8(V, prev_v)); + } + } + } + if (i < src_width) { // left-over + WebPConvertARGBToUV_C(argb + i, u, v, src_width - i, do_store); + } +} + + +//------------------------------------------------------------------------------ + +extern void WebPInitConvertARGBToYUVNEON(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitConvertARGBToYUVNEON(void) { + WebPConvertRGB24ToY = ConvertRGB24ToY_NEON; + WebPConvertBGR24ToY = ConvertBGR24ToY_NEON; + WebPConvertARGBToY = ConvertARGBToY_NEON; + WebPConvertARGBToUV = ConvertARGBToUV_NEON; + WebPConvertRGBA32ToUV = ConvertRGBA32ToUV_NEON; +} + +#else // !WEBP_USE_NEON + +WEBP_DSP_INIT_STUB(WebPInitConvertARGBToYUVNEON) + +#endif // WEBP_USE_NEON diff --git a/third-party/webp/libwebp/src/dsp/yuv_sse2.c b/third-party/webp/libwebp/src/dsp/yuv_sse2.c new file mode 100644 index 0000000000..01a48f9af2 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/yuv_sse2.c @@ -0,0 +1,758 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// YUV->RGB conversion functions +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/yuv.h" + +#if defined(WEBP_USE_SSE2) + +#include +#include + +#include "src/dsp/common_sse2.h" +#include "src/utils/utils.h" + +//----------------------------------------------------------------------------- +// Convert spans of 32 pixels to various RGB formats for the fancy upsampler. + +// These constants are 14b fixed-point version of ITU-R BT.601 constants. +// R = (19077 * y + 26149 * v - 14234) >> 6 +// G = (19077 * y - 6419 * u - 13320 * v + 8708) >> 6 +// B = (19077 * y + 33050 * u - 17685) >> 6 +static void ConvertYUV444ToRGB_SSE2(const __m128i* const Y0, + const __m128i* const U0, + const __m128i* const V0, + __m128i* const R, + __m128i* const G, + __m128i* const B) { + const __m128i k19077 = _mm_set1_epi16(19077); + const __m128i k26149 = _mm_set1_epi16(26149); + const __m128i k14234 = _mm_set1_epi16(14234); + // 33050 doesn't fit in a signed short: only use this with unsigned arithmetic + const __m128i k33050 = _mm_set1_epi16((short)33050); + const __m128i k17685 = _mm_set1_epi16(17685); + const __m128i k6419 = _mm_set1_epi16(6419); + const __m128i k13320 = _mm_set1_epi16(13320); + const __m128i k8708 = _mm_set1_epi16(8708); + + const __m128i Y1 = _mm_mulhi_epu16(*Y0, k19077); + + const __m128i R0 = _mm_mulhi_epu16(*V0, k26149); + const __m128i R1 = _mm_sub_epi16(Y1, k14234); + const __m128i R2 = _mm_add_epi16(R1, R0); + + const __m128i G0 = _mm_mulhi_epu16(*U0, k6419); + const __m128i G1 = _mm_mulhi_epu16(*V0, k13320); + const __m128i G2 = _mm_add_epi16(Y1, k8708); + const __m128i G3 = _mm_add_epi16(G0, G1); + const __m128i G4 = _mm_sub_epi16(G2, G3); + + // be careful with the saturated *unsigned* arithmetic here! + const __m128i B0 = _mm_mulhi_epu16(*U0, k33050); + const __m128i B1 = _mm_adds_epu16(B0, Y1); + const __m128i B2 = _mm_subs_epu16(B1, k17685); + + // use logical shift for B2, which can be larger than 32767 + *R = _mm_srai_epi16(R2, 6); // range: [-14234, 30815] + *G = _mm_srai_epi16(G4, 6); // range: [-10953, 27710] + *B = _mm_srli_epi16(B2, 6); // range: [0, 34238] +} + +// Load the bytes into the *upper* part of 16b words. That's "<< 8", basically. +static WEBP_INLINE __m128i Load_HI_16_SSE2(const uint8_t* src) { + const __m128i zero = _mm_setzero_si128(); + return _mm_unpacklo_epi8(zero, _mm_loadl_epi64((const __m128i*)src)); +} + +// Load and replicate the U/V samples +static WEBP_INLINE __m128i Load_UV_HI_8_SSE2(const uint8_t* src) { + const __m128i zero = _mm_setzero_si128(); + const __m128i tmp0 = _mm_cvtsi32_si128(WebPMemToInt32(src)); + const __m128i tmp1 = _mm_unpacklo_epi8(zero, tmp0); + return _mm_unpacklo_epi16(tmp1, tmp1); // replicate samples +} + +// Convert 32 samples of YUV444 to R/G/B +static void YUV444ToRGB_SSE2(const uint8_t* const y, + const uint8_t* const u, + const uint8_t* const v, + __m128i* const R, __m128i* const G, + __m128i* const B) { + const __m128i Y0 = Load_HI_16_SSE2(y), U0 = Load_HI_16_SSE2(u), + V0 = Load_HI_16_SSE2(v); + ConvertYUV444ToRGB_SSE2(&Y0, &U0, &V0, R, G, B); +} + +// Convert 32 samples of YUV420 to R/G/B +static void YUV420ToRGB_SSE2(const uint8_t* const y, + const uint8_t* const u, + const uint8_t* const v, + __m128i* const R, __m128i* const G, + __m128i* const B) { + const __m128i Y0 = Load_HI_16_SSE2(y), U0 = Load_UV_HI_8_SSE2(u), + V0 = Load_UV_HI_8_SSE2(v); + ConvertYUV444ToRGB_SSE2(&Y0, &U0, &V0, R, G, B); +} + +// Pack R/G/B/A results into 32b output. +static WEBP_INLINE void PackAndStore4_SSE2(const __m128i* const R, + const __m128i* const G, + const __m128i* const B, + const __m128i* const A, + uint8_t* const dst) { + const __m128i rb = _mm_packus_epi16(*R, *B); + const __m128i ga = _mm_packus_epi16(*G, *A); + const __m128i rg = _mm_unpacklo_epi8(rb, ga); + const __m128i ba = _mm_unpackhi_epi8(rb, ga); + const __m128i RGBA_lo = _mm_unpacklo_epi16(rg, ba); + const __m128i RGBA_hi = _mm_unpackhi_epi16(rg, ba); + _mm_storeu_si128((__m128i*)(dst + 0), RGBA_lo); + _mm_storeu_si128((__m128i*)(dst + 16), RGBA_hi); +} + +// Pack R/G/B/A results into 16b output. +static WEBP_INLINE void PackAndStore4444_SSE2(const __m128i* const R, + const __m128i* const G, + const __m128i* const B, + const __m128i* const A, + uint8_t* const dst) { +#if (WEBP_SWAP_16BIT_CSP == 0) + const __m128i rg0 = _mm_packus_epi16(*R, *G); + const __m128i ba0 = _mm_packus_epi16(*B, *A); +#else + const __m128i rg0 = _mm_packus_epi16(*B, *A); + const __m128i ba0 = _mm_packus_epi16(*R, *G); +#endif + const __m128i mask_0xf0 = _mm_set1_epi8((char)0xf0); + const __m128i rb1 = _mm_unpacklo_epi8(rg0, ba0); // rbrbrbrbrb... + const __m128i ga1 = _mm_unpackhi_epi8(rg0, ba0); // gagagagaga... + const __m128i rb2 = _mm_and_si128(rb1, mask_0xf0); + const __m128i ga2 = _mm_srli_epi16(_mm_and_si128(ga1, mask_0xf0), 4); + const __m128i rgba4444 = _mm_or_si128(rb2, ga2); + _mm_storeu_si128((__m128i*)dst, rgba4444); +} + +// Pack R/G/B results into 16b output. +static WEBP_INLINE void PackAndStore565_SSE2(const __m128i* const R, + const __m128i* const G, + const __m128i* const B, + uint8_t* const dst) { + const __m128i r0 = _mm_packus_epi16(*R, *R); + const __m128i g0 = _mm_packus_epi16(*G, *G); + const __m128i b0 = _mm_packus_epi16(*B, *B); + const __m128i r1 = _mm_and_si128(r0, _mm_set1_epi8((char)0xf8)); + const __m128i b1 = _mm_and_si128(_mm_srli_epi16(b0, 3), _mm_set1_epi8(0x1f)); + const __m128i g1 = + _mm_srli_epi16(_mm_and_si128(g0, _mm_set1_epi8((char)0xe0)), 5); + const __m128i g2 = _mm_slli_epi16(_mm_and_si128(g0, _mm_set1_epi8(0x1c)), 3); + const __m128i rg = _mm_or_si128(r1, g1); + const __m128i gb = _mm_or_si128(g2, b1); +#if (WEBP_SWAP_16BIT_CSP == 0) + const __m128i rgb565 = _mm_unpacklo_epi8(rg, gb); +#else + const __m128i rgb565 = _mm_unpacklo_epi8(gb, rg); +#endif + _mm_storeu_si128((__m128i*)dst, rgb565); +} + +// Pack the planar buffers +// rrrr... rrrr... gggg... gggg... bbbb... bbbb.... +// triplet by triplet in the output buffer rgb as rgbrgbrgbrgb ... +static WEBP_INLINE void PlanarTo24b_SSE2(__m128i* const in0, __m128i* const in1, + __m128i* const in2, __m128i* const in3, + __m128i* const in4, __m128i* const in5, + uint8_t* const rgb) { + // The input is 6 registers of sixteen 8b but for the sake of explanation, + // let's take 6 registers of four 8b values. + // To pack, we will keep taking one every two 8b integer and move it + // around as follows: + // Input: + // r0r1r2r3 | r4r5r6r7 | g0g1g2g3 | g4g5g6g7 | b0b1b2b3 | b4b5b6b7 + // Split the 6 registers in two sets of 3 registers: the first set as the even + // 8b bytes, the second the odd ones: + // r0r2r4r6 | g0g2g4g6 | b0b2b4b6 | r1r3r5r7 | g1g3g5g7 | b1b3b5b7 + // Repeat the same permutations twice more: + // r0r4g0g4 | b0b4r1r5 | g1g5b1b5 | r2r6g2g6 | b2b6r3r7 | g3g7b3b7 + // r0g0b0r1 | g1b1r2g2 | b2r3g3b3 | r4g4b4r5 | g5b5r6g6 | b6r7g7b7 + VP8PlanarTo24b_SSE2(in0, in1, in2, in3, in4, in5); + + _mm_storeu_si128((__m128i*)(rgb + 0), *in0); + _mm_storeu_si128((__m128i*)(rgb + 16), *in1); + _mm_storeu_si128((__m128i*)(rgb + 32), *in2); + _mm_storeu_si128((__m128i*)(rgb + 48), *in3); + _mm_storeu_si128((__m128i*)(rgb + 64), *in4); + _mm_storeu_si128((__m128i*)(rgb + 80), *in5); +} + +void VP8YuvToRgba32_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst) { + const __m128i kAlpha = _mm_set1_epi16(255); + int n; + for (n = 0; n < 32; n += 8, dst += 32) { + __m128i R, G, B; + YUV444ToRGB_SSE2(y + n, u + n, v + n, &R, &G, &B); + PackAndStore4_SSE2(&R, &G, &B, &kAlpha, dst); + } +} + +void VP8YuvToBgra32_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst) { + const __m128i kAlpha = _mm_set1_epi16(255); + int n; + for (n = 0; n < 32; n += 8, dst += 32) { + __m128i R, G, B; + YUV444ToRGB_SSE2(y + n, u + n, v + n, &R, &G, &B); + PackAndStore4_SSE2(&B, &G, &R, &kAlpha, dst); + } +} + +void VP8YuvToArgb32_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst) { + const __m128i kAlpha = _mm_set1_epi16(255); + int n; + for (n = 0; n < 32; n += 8, dst += 32) { + __m128i R, G, B; + YUV444ToRGB_SSE2(y + n, u + n, v + n, &R, &G, &B); + PackAndStore4_SSE2(&kAlpha, &R, &G, &B, dst); + } +} + +void VP8YuvToRgba444432_SSE2(const uint8_t* y, const uint8_t* u, + const uint8_t* v, uint8_t* dst) { + const __m128i kAlpha = _mm_set1_epi16(255); + int n; + for (n = 0; n < 32; n += 8, dst += 16) { + __m128i R, G, B; + YUV444ToRGB_SSE2(y + n, u + n, v + n, &R, &G, &B); + PackAndStore4444_SSE2(&R, &G, &B, &kAlpha, dst); + } +} + +void VP8YuvToRgb56532_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst) { + int n; + for (n = 0; n < 32; n += 8, dst += 16) { + __m128i R, G, B; + YUV444ToRGB_SSE2(y + n, u + n, v + n, &R, &G, &B); + PackAndStore565_SSE2(&R, &G, &B, dst); + } +} + +void VP8YuvToRgb32_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst) { + __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3; + __m128i rgb0, rgb1, rgb2, rgb3, rgb4, rgb5; + + YUV444ToRGB_SSE2(y + 0, u + 0, v + 0, &R0, &G0, &B0); + YUV444ToRGB_SSE2(y + 8, u + 8, v + 8, &R1, &G1, &B1); + YUV444ToRGB_SSE2(y + 16, u + 16, v + 16, &R2, &G2, &B2); + YUV444ToRGB_SSE2(y + 24, u + 24, v + 24, &R3, &G3, &B3); + + // Cast to 8b and store as RRRRGGGGBBBB. + rgb0 = _mm_packus_epi16(R0, R1); + rgb1 = _mm_packus_epi16(R2, R3); + rgb2 = _mm_packus_epi16(G0, G1); + rgb3 = _mm_packus_epi16(G2, G3); + rgb4 = _mm_packus_epi16(B0, B1); + rgb5 = _mm_packus_epi16(B2, B3); + + // Pack as RGBRGBRGBRGB. + PlanarTo24b_SSE2(&rgb0, &rgb1, &rgb2, &rgb3, &rgb4, &rgb5, dst); +} + +void VP8YuvToBgr32_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst) { + __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3; + __m128i bgr0, bgr1, bgr2, bgr3, bgr4, bgr5; + + YUV444ToRGB_SSE2(y + 0, u + 0, v + 0, &R0, &G0, &B0); + YUV444ToRGB_SSE2(y + 8, u + 8, v + 8, &R1, &G1, &B1); + YUV444ToRGB_SSE2(y + 16, u + 16, v + 16, &R2, &G2, &B2); + YUV444ToRGB_SSE2(y + 24, u + 24, v + 24, &R3, &G3, &B3); + + // Cast to 8b and store as BBBBGGGGRRRR. + bgr0 = _mm_packus_epi16(B0, B1); + bgr1 = _mm_packus_epi16(B2, B3); + bgr2 = _mm_packus_epi16(G0, G1); + bgr3 = _mm_packus_epi16(G2, G3); + bgr4 = _mm_packus_epi16(R0, R1); + bgr5= _mm_packus_epi16(R2, R3); + + // Pack as BGRBGRBGRBGR. + PlanarTo24b_SSE2(&bgr0, &bgr1, &bgr2, &bgr3, &bgr4, &bgr5, dst); +} + +//----------------------------------------------------------------------------- +// Arbitrary-length row conversion functions + +static void YuvToRgbaRow_SSE2(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len) { + const __m128i kAlpha = _mm_set1_epi16(255); + int n; + for (n = 0; n + 8 <= len; n += 8, dst += 32) { + __m128i R, G, B; + YUV420ToRGB_SSE2(y, u, v, &R, &G, &B); + PackAndStore4_SSE2(&R, &G, &B, &kAlpha, dst); + y += 8; + u += 4; + v += 4; + } + for (; n < len; ++n) { // Finish off + VP8YuvToRgba(y[0], u[0], v[0], dst); + dst += 4; + y += 1; + u += (n & 1); + v += (n & 1); + } +} + +static void YuvToBgraRow_SSE2(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len) { + const __m128i kAlpha = _mm_set1_epi16(255); + int n; + for (n = 0; n + 8 <= len; n += 8, dst += 32) { + __m128i R, G, B; + YUV420ToRGB_SSE2(y, u, v, &R, &G, &B); + PackAndStore4_SSE2(&B, &G, &R, &kAlpha, dst); + y += 8; + u += 4; + v += 4; + } + for (; n < len; ++n) { // Finish off + VP8YuvToBgra(y[0], u[0], v[0], dst); + dst += 4; + y += 1; + u += (n & 1); + v += (n & 1); + } +} + +static void YuvToArgbRow_SSE2(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len) { + const __m128i kAlpha = _mm_set1_epi16(255); + int n; + for (n = 0; n + 8 <= len; n += 8, dst += 32) { + __m128i R, G, B; + YUV420ToRGB_SSE2(y, u, v, &R, &G, &B); + PackAndStore4_SSE2(&kAlpha, &R, &G, &B, dst); + y += 8; + u += 4; + v += 4; + } + for (; n < len; ++n) { // Finish off + VP8YuvToArgb(y[0], u[0], v[0], dst); + dst += 4; + y += 1; + u += (n & 1); + v += (n & 1); + } +} + +static void YuvToRgbRow_SSE2(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len) { + int n; + for (n = 0; n + 32 <= len; n += 32, dst += 32 * 3) { + __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3; + __m128i rgb0, rgb1, rgb2, rgb3, rgb4, rgb5; + + YUV420ToRGB_SSE2(y + 0, u + 0, v + 0, &R0, &G0, &B0); + YUV420ToRGB_SSE2(y + 8, u + 4, v + 4, &R1, &G1, &B1); + YUV420ToRGB_SSE2(y + 16, u + 8, v + 8, &R2, &G2, &B2); + YUV420ToRGB_SSE2(y + 24, u + 12, v + 12, &R3, &G3, &B3); + + // Cast to 8b and store as RRRRGGGGBBBB. + rgb0 = _mm_packus_epi16(R0, R1); + rgb1 = _mm_packus_epi16(R2, R3); + rgb2 = _mm_packus_epi16(G0, G1); + rgb3 = _mm_packus_epi16(G2, G3); + rgb4 = _mm_packus_epi16(B0, B1); + rgb5 = _mm_packus_epi16(B2, B3); + + // Pack as RGBRGBRGBRGB. + PlanarTo24b_SSE2(&rgb0, &rgb1, &rgb2, &rgb3, &rgb4, &rgb5, dst); + + y += 32; + u += 16; + v += 16; + } + for (; n < len; ++n) { // Finish off + VP8YuvToRgb(y[0], u[0], v[0], dst); + dst += 3; + y += 1; + u += (n & 1); + v += (n & 1); + } +} + +static void YuvToBgrRow_SSE2(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len) { + int n; + for (n = 0; n + 32 <= len; n += 32, dst += 32 * 3) { + __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3; + __m128i bgr0, bgr1, bgr2, bgr3, bgr4, bgr5; + + YUV420ToRGB_SSE2(y + 0, u + 0, v + 0, &R0, &G0, &B0); + YUV420ToRGB_SSE2(y + 8, u + 4, v + 4, &R1, &G1, &B1); + YUV420ToRGB_SSE2(y + 16, u + 8, v + 8, &R2, &G2, &B2); + YUV420ToRGB_SSE2(y + 24, u + 12, v + 12, &R3, &G3, &B3); + + // Cast to 8b and store as BBBBGGGGRRRR. + bgr0 = _mm_packus_epi16(B0, B1); + bgr1 = _mm_packus_epi16(B2, B3); + bgr2 = _mm_packus_epi16(G0, G1); + bgr3 = _mm_packus_epi16(G2, G3); + bgr4 = _mm_packus_epi16(R0, R1); + bgr5 = _mm_packus_epi16(R2, R3); + + // Pack as BGRBGRBGRBGR. + PlanarTo24b_SSE2(&bgr0, &bgr1, &bgr2, &bgr3, &bgr4, &bgr5, dst); + + y += 32; + u += 16; + v += 16; + } + for (; n < len; ++n) { // Finish off + VP8YuvToBgr(y[0], u[0], v[0], dst); + dst += 3; + y += 1; + u += (n & 1); + v += (n & 1); + } +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void WebPInitSamplersSSE2(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplersSSE2(void) { + WebPSamplers[MODE_RGB] = YuvToRgbRow_SSE2; + WebPSamplers[MODE_RGBA] = YuvToRgbaRow_SSE2; + WebPSamplers[MODE_BGR] = YuvToBgrRow_SSE2; + WebPSamplers[MODE_BGRA] = YuvToBgraRow_SSE2; + WebPSamplers[MODE_ARGB] = YuvToArgbRow_SSE2; +} + +//------------------------------------------------------------------------------ +// RGB24/32 -> YUV converters + +// Load eight 16b-words from *src. +#define LOAD_16(src) _mm_loadu_si128((const __m128i*)(src)) +// Store either 16b-words into *dst +#define STORE_16(V, dst) _mm_storeu_si128((__m128i*)(dst), (V)) + +// Function that inserts a value of the second half of the in buffer in between +// every two char of the first half. +static WEBP_INLINE void RGB24PackedToPlanarHelper_SSE2( + const __m128i* const in /*in[6]*/, __m128i* const out /*out[6]*/) { + out[0] = _mm_unpacklo_epi8(in[0], in[3]); + out[1] = _mm_unpackhi_epi8(in[0], in[3]); + out[2] = _mm_unpacklo_epi8(in[1], in[4]); + out[3] = _mm_unpackhi_epi8(in[1], in[4]); + out[4] = _mm_unpacklo_epi8(in[2], in[5]); + out[5] = _mm_unpackhi_epi8(in[2], in[5]); +} + +// Unpack the 8b input rgbrgbrgbrgb ... as contiguous registers: +// rrrr... rrrr... gggg... gggg... bbbb... bbbb.... +// Similar to PlanarTo24bHelper(), but in reverse order. +static WEBP_INLINE void RGB24PackedToPlanar_SSE2( + const uint8_t* const rgb, __m128i* const out /*out[6]*/) { + __m128i tmp[6]; + tmp[0] = _mm_loadu_si128((const __m128i*)(rgb + 0)); + tmp[1] = _mm_loadu_si128((const __m128i*)(rgb + 16)); + tmp[2] = _mm_loadu_si128((const __m128i*)(rgb + 32)); + tmp[3] = _mm_loadu_si128((const __m128i*)(rgb + 48)); + tmp[4] = _mm_loadu_si128((const __m128i*)(rgb + 64)); + tmp[5] = _mm_loadu_si128((const __m128i*)(rgb + 80)); + + RGB24PackedToPlanarHelper_SSE2(tmp, out); + RGB24PackedToPlanarHelper_SSE2(out, tmp); + RGB24PackedToPlanarHelper_SSE2(tmp, out); + RGB24PackedToPlanarHelper_SSE2(out, tmp); + RGB24PackedToPlanarHelper_SSE2(tmp, out); +} + +// Convert 8 packed ARGB to r[], g[], b[] +static WEBP_INLINE void RGB32PackedToPlanar_SSE2(const uint32_t* const argb, + __m128i* const rgb /*in[6]*/) { + const __m128i zero = _mm_setzero_si128(); + __m128i a0 = LOAD_16(argb + 0); + __m128i a1 = LOAD_16(argb + 4); + __m128i a2 = LOAD_16(argb + 8); + __m128i a3 = LOAD_16(argb + 12); + VP8L32bToPlanar_SSE2(&a0, &a1, &a2, &a3); + rgb[0] = _mm_unpacklo_epi8(a1, zero); + rgb[1] = _mm_unpackhi_epi8(a1, zero); + rgb[2] = _mm_unpacklo_epi8(a2, zero); + rgb[3] = _mm_unpackhi_epi8(a2, zero); + rgb[4] = _mm_unpacklo_epi8(a3, zero); + rgb[5] = _mm_unpackhi_epi8(a3, zero); +} + +// This macro computes (RG * MULT_RG + GB * MULT_GB + ROUNDER) >> DESCALE_FIX +// It's a macro and not a function because we need to use immediate values with +// srai_epi32, e.g. +#define TRANSFORM(RG_LO, RG_HI, GB_LO, GB_HI, MULT_RG, MULT_GB, \ + ROUNDER, DESCALE_FIX, OUT) do { \ + const __m128i V0_lo = _mm_madd_epi16(RG_LO, MULT_RG); \ + const __m128i V0_hi = _mm_madd_epi16(RG_HI, MULT_RG); \ + const __m128i V1_lo = _mm_madd_epi16(GB_LO, MULT_GB); \ + const __m128i V1_hi = _mm_madd_epi16(GB_HI, MULT_GB); \ + const __m128i V2_lo = _mm_add_epi32(V0_lo, V1_lo); \ + const __m128i V2_hi = _mm_add_epi32(V0_hi, V1_hi); \ + const __m128i V3_lo = _mm_add_epi32(V2_lo, ROUNDER); \ + const __m128i V3_hi = _mm_add_epi32(V2_hi, ROUNDER); \ + const __m128i V5_lo = _mm_srai_epi32(V3_lo, DESCALE_FIX); \ + const __m128i V5_hi = _mm_srai_epi32(V3_hi, DESCALE_FIX); \ + (OUT) = _mm_packs_epi32(V5_lo, V5_hi); \ +} while (0) + +#define MK_CST_16(A, B) _mm_set_epi16((B), (A), (B), (A), (B), (A), (B), (A)) +static WEBP_INLINE void ConvertRGBToY_SSE2(const __m128i* const R, + const __m128i* const G, + const __m128i* const B, + __m128i* const Y) { + const __m128i kRG_y = MK_CST_16(16839, 33059 - 16384); + const __m128i kGB_y = MK_CST_16(16384, 6420); + const __m128i kHALF_Y = _mm_set1_epi32((16 << YUV_FIX) + YUV_HALF); + + const __m128i RG_lo = _mm_unpacklo_epi16(*R, *G); + const __m128i RG_hi = _mm_unpackhi_epi16(*R, *G); + const __m128i GB_lo = _mm_unpacklo_epi16(*G, *B); + const __m128i GB_hi = _mm_unpackhi_epi16(*G, *B); + TRANSFORM(RG_lo, RG_hi, GB_lo, GB_hi, kRG_y, kGB_y, kHALF_Y, YUV_FIX, *Y); +} + +static WEBP_INLINE void ConvertRGBToUV_SSE2(const __m128i* const R, + const __m128i* const G, + const __m128i* const B, + __m128i* const U, + __m128i* const V) { + const __m128i kRG_u = MK_CST_16(-9719, -19081); + const __m128i kGB_u = MK_CST_16(0, 28800); + const __m128i kRG_v = MK_CST_16(28800, 0); + const __m128i kGB_v = MK_CST_16(-24116, -4684); + const __m128i kHALF_UV = _mm_set1_epi32(((128 << YUV_FIX) + YUV_HALF) << 2); + + const __m128i RG_lo = _mm_unpacklo_epi16(*R, *G); + const __m128i RG_hi = _mm_unpackhi_epi16(*R, *G); + const __m128i GB_lo = _mm_unpacklo_epi16(*G, *B); + const __m128i GB_hi = _mm_unpackhi_epi16(*G, *B); + TRANSFORM(RG_lo, RG_hi, GB_lo, GB_hi, kRG_u, kGB_u, + kHALF_UV, YUV_FIX + 2, *U); + TRANSFORM(RG_lo, RG_hi, GB_lo, GB_hi, kRG_v, kGB_v, + kHALF_UV, YUV_FIX + 2, *V); +} + +#undef MK_CST_16 +#undef TRANSFORM + +static void ConvertRGB24ToY_SSE2(const uint8_t* rgb, uint8_t* y, int width) { + const int max_width = width & ~31; + int i; + for (i = 0; i < max_width; rgb += 3 * 16 * 2) { + __m128i rgb_plane[6]; + int j; + + RGB24PackedToPlanar_SSE2(rgb, rgb_plane); + + for (j = 0; j < 2; ++j, i += 16) { + const __m128i zero = _mm_setzero_si128(); + __m128i r, g, b, Y0, Y1; + + // Convert to 16-bit Y. + r = _mm_unpacklo_epi8(rgb_plane[0 + j], zero); + g = _mm_unpacklo_epi8(rgb_plane[2 + j], zero); + b = _mm_unpacklo_epi8(rgb_plane[4 + j], zero); + ConvertRGBToY_SSE2(&r, &g, &b, &Y0); + + // Convert to 16-bit Y. + r = _mm_unpackhi_epi8(rgb_plane[0 + j], zero); + g = _mm_unpackhi_epi8(rgb_plane[2 + j], zero); + b = _mm_unpackhi_epi8(rgb_plane[4 + j], zero); + ConvertRGBToY_SSE2(&r, &g, &b, &Y1); + + // Cast to 8-bit and store. + STORE_16(_mm_packus_epi16(Y0, Y1), y + i); + } + } + for (; i < width; ++i, rgb += 3) { // left-over + y[i] = VP8RGBToY(rgb[0], rgb[1], rgb[2], YUV_HALF); + } +} + +static void ConvertBGR24ToY_SSE2(const uint8_t* bgr, uint8_t* y, int width) { + const int max_width = width & ~31; + int i; + for (i = 0; i < max_width; bgr += 3 * 16 * 2) { + __m128i bgr_plane[6]; + int j; + + RGB24PackedToPlanar_SSE2(bgr, bgr_plane); + + for (j = 0; j < 2; ++j, i += 16) { + const __m128i zero = _mm_setzero_si128(); + __m128i r, g, b, Y0, Y1; + + // Convert to 16-bit Y. + b = _mm_unpacklo_epi8(bgr_plane[0 + j], zero); + g = _mm_unpacklo_epi8(bgr_plane[2 + j], zero); + r = _mm_unpacklo_epi8(bgr_plane[4 + j], zero); + ConvertRGBToY_SSE2(&r, &g, &b, &Y0); + + // Convert to 16-bit Y. + b = _mm_unpackhi_epi8(bgr_plane[0 + j], zero); + g = _mm_unpackhi_epi8(bgr_plane[2 + j], zero); + r = _mm_unpackhi_epi8(bgr_plane[4 + j], zero); + ConvertRGBToY_SSE2(&r, &g, &b, &Y1); + + // Cast to 8-bit and store. + STORE_16(_mm_packus_epi16(Y0, Y1), y + i); + } + } + for (; i < width; ++i, bgr += 3) { // left-over + y[i] = VP8RGBToY(bgr[2], bgr[1], bgr[0], YUV_HALF); + } +} + +static void ConvertARGBToY_SSE2(const uint32_t* argb, uint8_t* y, int width) { + const int max_width = width & ~15; + int i; + for (i = 0; i < max_width; i += 16) { + __m128i Y0, Y1, rgb[6]; + RGB32PackedToPlanar_SSE2(&argb[i], rgb); + ConvertRGBToY_SSE2(&rgb[0], &rgb[2], &rgb[4], &Y0); + ConvertRGBToY_SSE2(&rgb[1], &rgb[3], &rgb[5], &Y1); + STORE_16(_mm_packus_epi16(Y0, Y1), y + i); + } + for (; i < width; ++i) { // left-over + const uint32_t p = argb[i]; + y[i] = VP8RGBToY((p >> 16) & 0xff, (p >> 8) & 0xff, (p >> 0) & 0xff, + YUV_HALF); + } +} + +// Horizontal add (doubled) of two 16b values, result is 16b. +// in: A | B | C | D | ... -> out: 2*(A+B) | 2*(C+D) | ... +static void HorizontalAddPack_SSE2(const __m128i* const A, + const __m128i* const B, + __m128i* const out) { + const __m128i k2 = _mm_set1_epi16(2); + const __m128i C = _mm_madd_epi16(*A, k2); + const __m128i D = _mm_madd_epi16(*B, k2); + *out = _mm_packs_epi32(C, D); +} + +static void ConvertARGBToUV_SSE2(const uint32_t* argb, + uint8_t* u, uint8_t* v, + int src_width, int do_store) { + const int max_width = src_width & ~31; + int i; + for (i = 0; i < max_width; i += 32, u += 16, v += 16) { + __m128i rgb[6], U0, V0, U1, V1; + RGB32PackedToPlanar_SSE2(&argb[i], rgb); + HorizontalAddPack_SSE2(&rgb[0], &rgb[1], &rgb[0]); + HorizontalAddPack_SSE2(&rgb[2], &rgb[3], &rgb[2]); + HorizontalAddPack_SSE2(&rgb[4], &rgb[5], &rgb[4]); + ConvertRGBToUV_SSE2(&rgb[0], &rgb[2], &rgb[4], &U0, &V0); + + RGB32PackedToPlanar_SSE2(&argb[i + 16], rgb); + HorizontalAddPack_SSE2(&rgb[0], &rgb[1], &rgb[0]); + HorizontalAddPack_SSE2(&rgb[2], &rgb[3], &rgb[2]); + HorizontalAddPack_SSE2(&rgb[4], &rgb[5], &rgb[4]); + ConvertRGBToUV_SSE2(&rgb[0], &rgb[2], &rgb[4], &U1, &V1); + + U0 = _mm_packus_epi16(U0, U1); + V0 = _mm_packus_epi16(V0, V1); + if (!do_store) { + const __m128i prev_u = LOAD_16(u); + const __m128i prev_v = LOAD_16(v); + U0 = _mm_avg_epu8(U0, prev_u); + V0 = _mm_avg_epu8(V0, prev_v); + } + STORE_16(U0, u); + STORE_16(V0, v); + } + if (i < src_width) { // left-over + WebPConvertARGBToUV_C(argb + i, u, v, src_width - i, do_store); + } +} + +// Convert 16 packed ARGB 16b-values to r[], g[], b[] +static WEBP_INLINE void RGBA32PackedToPlanar_16b_SSE2( + const uint16_t* const rgbx, + __m128i* const r, __m128i* const g, __m128i* const b) { + const __m128i in0 = LOAD_16(rgbx + 0); // r0 | g0 | b0 |x| r1 | g1 | b1 |x + const __m128i in1 = LOAD_16(rgbx + 8); // r2 | g2 | b2 |x| r3 | g3 | b3 |x + const __m128i in2 = LOAD_16(rgbx + 16); // r4 | ... + const __m128i in3 = LOAD_16(rgbx + 24); // r6 | ... + // column-wise transpose + const __m128i A0 = _mm_unpacklo_epi16(in0, in1); + const __m128i A1 = _mm_unpackhi_epi16(in0, in1); + const __m128i A2 = _mm_unpacklo_epi16(in2, in3); + const __m128i A3 = _mm_unpackhi_epi16(in2, in3); + const __m128i B0 = _mm_unpacklo_epi16(A0, A1); // r0 r1 r2 r3 | g0 g1 .. + const __m128i B1 = _mm_unpackhi_epi16(A0, A1); // b0 b1 b2 b3 | x x x x + const __m128i B2 = _mm_unpacklo_epi16(A2, A3); // r4 r5 r6 r7 | g4 g5 .. + const __m128i B3 = _mm_unpackhi_epi16(A2, A3); // b4 b5 b6 b7 | x x x x + *r = _mm_unpacklo_epi64(B0, B2); + *g = _mm_unpackhi_epi64(B0, B2); + *b = _mm_unpacklo_epi64(B1, B3); +} + +static void ConvertRGBA32ToUV_SSE2(const uint16_t* rgb, + uint8_t* u, uint8_t* v, int width) { + const int max_width = width & ~15; + const uint16_t* const last_rgb = rgb + 4 * max_width; + while (rgb < last_rgb) { + __m128i r, g, b, U0, V0, U1, V1; + RGBA32PackedToPlanar_16b_SSE2(rgb + 0, &r, &g, &b); + ConvertRGBToUV_SSE2(&r, &g, &b, &U0, &V0); + RGBA32PackedToPlanar_16b_SSE2(rgb + 32, &r, &g, &b); + ConvertRGBToUV_SSE2(&r, &g, &b, &U1, &V1); + STORE_16(_mm_packus_epi16(U0, U1), u); + STORE_16(_mm_packus_epi16(V0, V1), v); + u += 16; + v += 16; + rgb += 2 * 32; + } + if (max_width < width) { // left-over + WebPConvertRGBA32ToUV_C(rgb, u, v, width - max_width); + } +} + +//------------------------------------------------------------------------------ + +extern void WebPInitConvertARGBToYUVSSE2(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitConvertARGBToYUVSSE2(void) { + WebPConvertARGBToY = ConvertARGBToY_SSE2; + WebPConvertARGBToUV = ConvertARGBToUV_SSE2; + + WebPConvertRGB24ToY = ConvertRGB24ToY_SSE2; + WebPConvertBGR24ToY = ConvertBGR24ToY_SSE2; + + WebPConvertRGBA32ToUV = ConvertRGBA32ToUV_SSE2; +} + +#else // !WEBP_USE_SSE2 + +WEBP_DSP_INIT_STUB(WebPInitSamplersSSE2) +WEBP_DSP_INIT_STUB(WebPInitConvertARGBToYUVSSE2) + +#endif // WEBP_USE_SSE2 diff --git a/third-party/webp/libwebp/src/dsp/yuv_sse41.c b/third-party/webp/libwebp/src/dsp/yuv_sse41.c new file mode 100644 index 0000000000..f79b802e47 --- /dev/null +++ b/third-party/webp/libwebp/src/dsp/yuv_sse41.c @@ -0,0 +1,615 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// YUV->RGB conversion functions +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/yuv.h" + +#if defined(WEBP_USE_SSE41) + +#include +#include + +#include "src/dsp/common_sse41.h" +#include "src/utils/utils.h" + +//----------------------------------------------------------------------------- +// Convert spans of 32 pixels to various RGB formats for the fancy upsampler. + +// These constants are 14b fixed-point version of ITU-R BT.601 constants. +// R = (19077 * y + 26149 * v - 14234) >> 6 +// G = (19077 * y - 6419 * u - 13320 * v + 8708) >> 6 +// B = (19077 * y + 33050 * u - 17685) >> 6 +static void ConvertYUV444ToRGB_SSE41(const __m128i* const Y0, + const __m128i* const U0, + const __m128i* const V0, + __m128i* const R, + __m128i* const G, + __m128i* const B) { + const __m128i k19077 = _mm_set1_epi16(19077); + const __m128i k26149 = _mm_set1_epi16(26149); + const __m128i k14234 = _mm_set1_epi16(14234); + // 33050 doesn't fit in a signed short: only use this with unsigned arithmetic + const __m128i k33050 = _mm_set1_epi16((short)33050); + const __m128i k17685 = _mm_set1_epi16(17685); + const __m128i k6419 = _mm_set1_epi16(6419); + const __m128i k13320 = _mm_set1_epi16(13320); + const __m128i k8708 = _mm_set1_epi16(8708); + + const __m128i Y1 = _mm_mulhi_epu16(*Y0, k19077); + + const __m128i R0 = _mm_mulhi_epu16(*V0, k26149); + const __m128i R1 = _mm_sub_epi16(Y1, k14234); + const __m128i R2 = _mm_add_epi16(R1, R0); + + const __m128i G0 = _mm_mulhi_epu16(*U0, k6419); + const __m128i G1 = _mm_mulhi_epu16(*V0, k13320); + const __m128i G2 = _mm_add_epi16(Y1, k8708); + const __m128i G3 = _mm_add_epi16(G0, G1); + const __m128i G4 = _mm_sub_epi16(G2, G3); + + // be careful with the saturated *unsigned* arithmetic here! + const __m128i B0 = _mm_mulhi_epu16(*U0, k33050); + const __m128i B1 = _mm_adds_epu16(B0, Y1); + const __m128i B2 = _mm_subs_epu16(B1, k17685); + + // use logical shift for B2, which can be larger than 32767 + *R = _mm_srai_epi16(R2, 6); // range: [-14234, 30815] + *G = _mm_srai_epi16(G4, 6); // range: [-10953, 27710] + *B = _mm_srli_epi16(B2, 6); // range: [0, 34238] +} + +// Load the bytes into the *upper* part of 16b words. That's "<< 8", basically. +static WEBP_INLINE __m128i Load_HI_16_SSE41(const uint8_t* src) { + const __m128i zero = _mm_setzero_si128(); + return _mm_unpacklo_epi8(zero, _mm_loadl_epi64((const __m128i*)src)); +} + +// Load and replicate the U/V samples +static WEBP_INLINE __m128i Load_UV_HI_8_SSE41(const uint8_t* src) { + const __m128i zero = _mm_setzero_si128(); + const __m128i tmp0 = _mm_cvtsi32_si128(WebPMemToInt32(src)); + const __m128i tmp1 = _mm_unpacklo_epi8(zero, tmp0); + return _mm_unpacklo_epi16(tmp1, tmp1); // replicate samples +} + +// Convert 32 samples of YUV444 to R/G/B +static void YUV444ToRGB_SSE41(const uint8_t* const y, + const uint8_t* const u, + const uint8_t* const v, + __m128i* const R, __m128i* const G, + __m128i* const B) { + const __m128i Y0 = Load_HI_16_SSE41(y), U0 = Load_HI_16_SSE41(u), + V0 = Load_HI_16_SSE41(v); + ConvertYUV444ToRGB_SSE41(&Y0, &U0, &V0, R, G, B); +} + +// Convert 32 samples of YUV420 to R/G/B +static void YUV420ToRGB_SSE41(const uint8_t* const y, + const uint8_t* const u, + const uint8_t* const v, + __m128i* const R, __m128i* const G, + __m128i* const B) { + const __m128i Y0 = Load_HI_16_SSE41(y), U0 = Load_UV_HI_8_SSE41(u), + V0 = Load_UV_HI_8_SSE41(v); + ConvertYUV444ToRGB_SSE41(&Y0, &U0, &V0, R, G, B); +} + +// Pack the planar buffers +// rrrr... rrrr... gggg... gggg... bbbb... bbbb.... +// triplet by triplet in the output buffer rgb as rgbrgbrgbrgb ... +static WEBP_INLINE void PlanarTo24b_SSE41( + __m128i* const in0, __m128i* const in1, __m128i* const in2, + __m128i* const in3, __m128i* const in4, __m128i* const in5, + uint8_t* const rgb) { + // The input is 6 registers of sixteen 8b but for the sake of explanation, + // let's take 6 registers of four 8b values. + // To pack, we will keep taking one every two 8b integer and move it + // around as follows: + // Input: + // r0r1r2r3 | r4r5r6r7 | g0g1g2g3 | g4g5g6g7 | b0b1b2b3 | b4b5b6b7 + // Split the 6 registers in two sets of 3 registers: the first set as the even + // 8b bytes, the second the odd ones: + // r0r2r4r6 | g0g2g4g6 | b0b2b4b6 | r1r3r5r7 | g1g3g5g7 | b1b3b5b7 + // Repeat the same permutations twice more: + // r0r4g0g4 | b0b4r1r5 | g1g5b1b5 | r2r6g2g6 | b2b6r3r7 | g3g7b3b7 + // r0g0b0r1 | g1b1r2g2 | b2r3g3b3 | r4g4b4r5 | g5b5r6g6 | b6r7g7b7 + VP8PlanarTo24b_SSE41(in0, in1, in2, in3, in4, in5); + + _mm_storeu_si128((__m128i*)(rgb + 0), *in0); + _mm_storeu_si128((__m128i*)(rgb + 16), *in1); + _mm_storeu_si128((__m128i*)(rgb + 32), *in2); + _mm_storeu_si128((__m128i*)(rgb + 48), *in3); + _mm_storeu_si128((__m128i*)(rgb + 64), *in4); + _mm_storeu_si128((__m128i*)(rgb + 80), *in5); +} + +void VP8YuvToRgb32_SSE41(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst) { + __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3; + __m128i rgb0, rgb1, rgb2, rgb3, rgb4, rgb5; + + YUV444ToRGB_SSE41(y + 0, u + 0, v + 0, &R0, &G0, &B0); + YUV444ToRGB_SSE41(y + 8, u + 8, v + 8, &R1, &G1, &B1); + YUV444ToRGB_SSE41(y + 16, u + 16, v + 16, &R2, &G2, &B2); + YUV444ToRGB_SSE41(y + 24, u + 24, v + 24, &R3, &G3, &B3); + + // Cast to 8b and store as RRRRGGGGBBBB. + rgb0 = _mm_packus_epi16(R0, R1); + rgb1 = _mm_packus_epi16(R2, R3); + rgb2 = _mm_packus_epi16(G0, G1); + rgb3 = _mm_packus_epi16(G2, G3); + rgb4 = _mm_packus_epi16(B0, B1); + rgb5 = _mm_packus_epi16(B2, B3); + + // Pack as RGBRGBRGBRGB. + PlanarTo24b_SSE41(&rgb0, &rgb1, &rgb2, &rgb3, &rgb4, &rgb5, dst); +} + +void VP8YuvToBgr32_SSE41(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst) { + __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3; + __m128i bgr0, bgr1, bgr2, bgr3, bgr4, bgr5; + + YUV444ToRGB_SSE41(y + 0, u + 0, v + 0, &R0, &G0, &B0); + YUV444ToRGB_SSE41(y + 8, u + 8, v + 8, &R1, &G1, &B1); + YUV444ToRGB_SSE41(y + 16, u + 16, v + 16, &R2, &G2, &B2); + YUV444ToRGB_SSE41(y + 24, u + 24, v + 24, &R3, &G3, &B3); + + // Cast to 8b and store as BBBBGGGGRRRR. + bgr0 = _mm_packus_epi16(B0, B1); + bgr1 = _mm_packus_epi16(B2, B3); + bgr2 = _mm_packus_epi16(G0, G1); + bgr3 = _mm_packus_epi16(G2, G3); + bgr4 = _mm_packus_epi16(R0, R1); + bgr5= _mm_packus_epi16(R2, R3); + + // Pack as BGRBGRBGRBGR. + PlanarTo24b_SSE41(&bgr0, &bgr1, &bgr2, &bgr3, &bgr4, &bgr5, dst); +} + +//----------------------------------------------------------------------------- +// Arbitrary-length row conversion functions + +static void YuvToRgbRow_SSE41(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len) { + int n; + for (n = 0; n + 32 <= len; n += 32, dst += 32 * 3) { + __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3; + __m128i rgb0, rgb1, rgb2, rgb3, rgb4, rgb5; + + YUV420ToRGB_SSE41(y + 0, u + 0, v + 0, &R0, &G0, &B0); + YUV420ToRGB_SSE41(y + 8, u + 4, v + 4, &R1, &G1, &B1); + YUV420ToRGB_SSE41(y + 16, u + 8, v + 8, &R2, &G2, &B2); + YUV420ToRGB_SSE41(y + 24, u + 12, v + 12, &R3, &G3, &B3); + + // Cast to 8b and store as RRRRGGGGBBBB. + rgb0 = _mm_packus_epi16(R0, R1); + rgb1 = _mm_packus_epi16(R2, R3); + rgb2 = _mm_packus_epi16(G0, G1); + rgb3 = _mm_packus_epi16(G2, G3); + rgb4 = _mm_packus_epi16(B0, B1); + rgb5 = _mm_packus_epi16(B2, B3); + + // Pack as RGBRGBRGBRGB. + PlanarTo24b_SSE41(&rgb0, &rgb1, &rgb2, &rgb3, &rgb4, &rgb5, dst); + + y += 32; + u += 16; + v += 16; + } + for (; n < len; ++n) { // Finish off + VP8YuvToRgb(y[0], u[0], v[0], dst); + dst += 3; + y += 1; + u += (n & 1); + v += (n & 1); + } +} + +static void YuvToBgrRow_SSE41(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len) { + int n; + for (n = 0; n + 32 <= len; n += 32, dst += 32 * 3) { + __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3; + __m128i bgr0, bgr1, bgr2, bgr3, bgr4, bgr5; + + YUV420ToRGB_SSE41(y + 0, u + 0, v + 0, &R0, &G0, &B0); + YUV420ToRGB_SSE41(y + 8, u + 4, v + 4, &R1, &G1, &B1); + YUV420ToRGB_SSE41(y + 16, u + 8, v + 8, &R2, &G2, &B2); + YUV420ToRGB_SSE41(y + 24, u + 12, v + 12, &R3, &G3, &B3); + + // Cast to 8b and store as BBBBGGGGRRRR. + bgr0 = _mm_packus_epi16(B0, B1); + bgr1 = _mm_packus_epi16(B2, B3); + bgr2 = _mm_packus_epi16(G0, G1); + bgr3 = _mm_packus_epi16(G2, G3); + bgr4 = _mm_packus_epi16(R0, R1); + bgr5 = _mm_packus_epi16(R2, R3); + + // Pack as BGRBGRBGRBGR. + PlanarTo24b_SSE41(&bgr0, &bgr1, &bgr2, &bgr3, &bgr4, &bgr5, dst); + + y += 32; + u += 16; + v += 16; + } + for (; n < len; ++n) { // Finish off + VP8YuvToBgr(y[0], u[0], v[0], dst); + dst += 3; + y += 1; + u += (n & 1); + v += (n & 1); + } +} + +//------------------------------------------------------------------------------ +// Entry point + +extern void WebPInitSamplersSSE41(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplersSSE41(void) { + WebPSamplers[MODE_RGB] = YuvToRgbRow_SSE41; + WebPSamplers[MODE_BGR] = YuvToBgrRow_SSE41; +} + +//------------------------------------------------------------------------------ +// RGB24/32 -> YUV converters + +// Load eight 16b-words from *src. +#define LOAD_16(src) _mm_loadu_si128((const __m128i*)(src)) +// Store either 16b-words into *dst +#define STORE_16(V, dst) _mm_storeu_si128((__m128i*)(dst), (V)) + +#define WEBP_SSE41_SHUFF(OUT) do { \ + const __m128i tmp0 = _mm_shuffle_epi8(A0, shuff0); \ + const __m128i tmp1 = _mm_shuffle_epi8(A1, shuff1); \ + const __m128i tmp2 = _mm_shuffle_epi8(A2, shuff2); \ + const __m128i tmp3 = _mm_shuffle_epi8(A3, shuff0); \ + const __m128i tmp4 = _mm_shuffle_epi8(A4, shuff1); \ + const __m128i tmp5 = _mm_shuffle_epi8(A5, shuff2); \ + \ + /* OR everything to get one channel */ \ + const __m128i tmp6 = _mm_or_si128(tmp0, tmp1); \ + const __m128i tmp7 = _mm_or_si128(tmp3, tmp4); \ + out[OUT + 0] = _mm_or_si128(tmp6, tmp2); \ + out[OUT + 1] = _mm_or_si128(tmp7, tmp5); \ +} while (0); + +// Unpack the 8b input rgbrgbrgbrgb ... as contiguous registers: +// rrrr... rrrr... gggg... gggg... bbbb... bbbb.... +// Similar to PlanarTo24bHelper(), but in reverse order. +static WEBP_INLINE void RGB24PackedToPlanar_SSE41( + const uint8_t* const rgb, __m128i* const out /*out[6]*/) { + const __m128i A0 = _mm_loadu_si128((const __m128i*)(rgb + 0)); + const __m128i A1 = _mm_loadu_si128((const __m128i*)(rgb + 16)); + const __m128i A2 = _mm_loadu_si128((const __m128i*)(rgb + 32)); + const __m128i A3 = _mm_loadu_si128((const __m128i*)(rgb + 48)); + const __m128i A4 = _mm_loadu_si128((const __m128i*)(rgb + 64)); + const __m128i A5 = _mm_loadu_si128((const __m128i*)(rgb + 80)); + + // Compute RR. + { + const __m128i shuff0 = _mm_set_epi8( + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, 12, 9, 6, 3, 0); + const __m128i shuff1 = _mm_set_epi8( + -1, -1, -1, -1, -1, 14, 11, 8, 5, 2, -1, -1, -1, -1, -1, -1); + const __m128i shuff2 = _mm_set_epi8( + 13, 10, 7, 4, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); + WEBP_SSE41_SHUFF(0) + } + // Compute GG. + { + const __m128i shuff0 = _mm_set_epi8( + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13, 10, 7, 4, 1); + const __m128i shuff1 = _mm_set_epi8( + -1, -1, -1, -1, -1, 15, 12, 9, 6, 3, 0, -1, -1, -1, -1, -1); + const __m128i shuff2 = _mm_set_epi8( + 14, 11, 8, 5, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); + WEBP_SSE41_SHUFF(2) + } + // Compute BB. + { + const __m128i shuff0 = _mm_set_epi8( + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14, 11, 8, 5, 2); + const __m128i shuff1 = _mm_set_epi8( + -1, -1, -1, -1, -1, -1, 13, 10, 7, 4, 1, -1, -1, -1, -1, -1); + const __m128i shuff2 = _mm_set_epi8( + 15, 12, 9, 6, 3, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); + WEBP_SSE41_SHUFF(4) + } +} + +#undef WEBP_SSE41_SHUFF + +// Convert 8 packed ARGB to r[], g[], b[] +static WEBP_INLINE void RGB32PackedToPlanar_SSE41( + const uint32_t* const argb, __m128i* const rgb /*in[6]*/) { + const __m128i zero = _mm_setzero_si128(); + __m128i a0 = LOAD_16(argb + 0); + __m128i a1 = LOAD_16(argb + 4); + __m128i a2 = LOAD_16(argb + 8); + __m128i a3 = LOAD_16(argb + 12); + VP8L32bToPlanar_SSE41(&a0, &a1, &a2, &a3); + rgb[0] = _mm_unpacklo_epi8(a1, zero); + rgb[1] = _mm_unpackhi_epi8(a1, zero); + rgb[2] = _mm_unpacklo_epi8(a2, zero); + rgb[3] = _mm_unpackhi_epi8(a2, zero); + rgb[4] = _mm_unpacklo_epi8(a3, zero); + rgb[5] = _mm_unpackhi_epi8(a3, zero); +} + +// This macro computes (RG * MULT_RG + GB * MULT_GB + ROUNDER) >> DESCALE_FIX +// It's a macro and not a function because we need to use immediate values with +// srai_epi32, e.g. +#define TRANSFORM(RG_LO, RG_HI, GB_LO, GB_HI, MULT_RG, MULT_GB, \ + ROUNDER, DESCALE_FIX, OUT) do { \ + const __m128i V0_lo = _mm_madd_epi16(RG_LO, MULT_RG); \ + const __m128i V0_hi = _mm_madd_epi16(RG_HI, MULT_RG); \ + const __m128i V1_lo = _mm_madd_epi16(GB_LO, MULT_GB); \ + const __m128i V1_hi = _mm_madd_epi16(GB_HI, MULT_GB); \ + const __m128i V2_lo = _mm_add_epi32(V0_lo, V1_lo); \ + const __m128i V2_hi = _mm_add_epi32(V0_hi, V1_hi); \ + const __m128i V3_lo = _mm_add_epi32(V2_lo, ROUNDER); \ + const __m128i V3_hi = _mm_add_epi32(V2_hi, ROUNDER); \ + const __m128i V5_lo = _mm_srai_epi32(V3_lo, DESCALE_FIX); \ + const __m128i V5_hi = _mm_srai_epi32(V3_hi, DESCALE_FIX); \ + (OUT) = _mm_packs_epi32(V5_lo, V5_hi); \ +} while (0) + +#define MK_CST_16(A, B) _mm_set_epi16((B), (A), (B), (A), (B), (A), (B), (A)) +static WEBP_INLINE void ConvertRGBToY_SSE41(const __m128i* const R, + const __m128i* const G, + const __m128i* const B, + __m128i* const Y) { + const __m128i kRG_y = MK_CST_16(16839, 33059 - 16384); + const __m128i kGB_y = MK_CST_16(16384, 6420); + const __m128i kHALF_Y = _mm_set1_epi32((16 << YUV_FIX) + YUV_HALF); + + const __m128i RG_lo = _mm_unpacklo_epi16(*R, *G); + const __m128i RG_hi = _mm_unpackhi_epi16(*R, *G); + const __m128i GB_lo = _mm_unpacklo_epi16(*G, *B); + const __m128i GB_hi = _mm_unpackhi_epi16(*G, *B); + TRANSFORM(RG_lo, RG_hi, GB_lo, GB_hi, kRG_y, kGB_y, kHALF_Y, YUV_FIX, *Y); +} + +static WEBP_INLINE void ConvertRGBToUV_SSE41(const __m128i* const R, + const __m128i* const G, + const __m128i* const B, + __m128i* const U, + __m128i* const V) { + const __m128i kRG_u = MK_CST_16(-9719, -19081); + const __m128i kGB_u = MK_CST_16(0, 28800); + const __m128i kRG_v = MK_CST_16(28800, 0); + const __m128i kGB_v = MK_CST_16(-24116, -4684); + const __m128i kHALF_UV = _mm_set1_epi32(((128 << YUV_FIX) + YUV_HALF) << 2); + + const __m128i RG_lo = _mm_unpacklo_epi16(*R, *G); + const __m128i RG_hi = _mm_unpackhi_epi16(*R, *G); + const __m128i GB_lo = _mm_unpacklo_epi16(*G, *B); + const __m128i GB_hi = _mm_unpackhi_epi16(*G, *B); + TRANSFORM(RG_lo, RG_hi, GB_lo, GB_hi, kRG_u, kGB_u, + kHALF_UV, YUV_FIX + 2, *U); + TRANSFORM(RG_lo, RG_hi, GB_lo, GB_hi, kRG_v, kGB_v, + kHALF_UV, YUV_FIX + 2, *V); +} + +#undef MK_CST_16 +#undef TRANSFORM + +static void ConvertRGB24ToY_SSE41(const uint8_t* rgb, uint8_t* y, int width) { + const int max_width = width & ~31; + int i; + for (i = 0; i < max_width; rgb += 3 * 16 * 2) { + __m128i rgb_plane[6]; + int j; + + RGB24PackedToPlanar_SSE41(rgb, rgb_plane); + + for (j = 0; j < 2; ++j, i += 16) { + const __m128i zero = _mm_setzero_si128(); + __m128i r, g, b, Y0, Y1; + + // Convert to 16-bit Y. + r = _mm_unpacklo_epi8(rgb_plane[0 + j], zero); + g = _mm_unpacklo_epi8(rgb_plane[2 + j], zero); + b = _mm_unpacklo_epi8(rgb_plane[4 + j], zero); + ConvertRGBToY_SSE41(&r, &g, &b, &Y0); + + // Convert to 16-bit Y. + r = _mm_unpackhi_epi8(rgb_plane[0 + j], zero); + g = _mm_unpackhi_epi8(rgb_plane[2 + j], zero); + b = _mm_unpackhi_epi8(rgb_plane[4 + j], zero); + ConvertRGBToY_SSE41(&r, &g, &b, &Y1); + + // Cast to 8-bit and store. + STORE_16(_mm_packus_epi16(Y0, Y1), y + i); + } + } + for (; i < width; ++i, rgb += 3) { // left-over + y[i] = VP8RGBToY(rgb[0], rgb[1], rgb[2], YUV_HALF); + } +} + +static void ConvertBGR24ToY_SSE41(const uint8_t* bgr, uint8_t* y, int width) { + const int max_width = width & ~31; + int i; + for (i = 0; i < max_width; bgr += 3 * 16 * 2) { + __m128i bgr_plane[6]; + int j; + + RGB24PackedToPlanar_SSE41(bgr, bgr_plane); + + for (j = 0; j < 2; ++j, i += 16) { + const __m128i zero = _mm_setzero_si128(); + __m128i r, g, b, Y0, Y1; + + // Convert to 16-bit Y. + b = _mm_unpacklo_epi8(bgr_plane[0 + j], zero); + g = _mm_unpacklo_epi8(bgr_plane[2 + j], zero); + r = _mm_unpacklo_epi8(bgr_plane[4 + j], zero); + ConvertRGBToY_SSE41(&r, &g, &b, &Y0); + + // Convert to 16-bit Y. + b = _mm_unpackhi_epi8(bgr_plane[0 + j], zero); + g = _mm_unpackhi_epi8(bgr_plane[2 + j], zero); + r = _mm_unpackhi_epi8(bgr_plane[4 + j], zero); + ConvertRGBToY_SSE41(&r, &g, &b, &Y1); + + // Cast to 8-bit and store. + STORE_16(_mm_packus_epi16(Y0, Y1), y + i); + } + } + for (; i < width; ++i, bgr += 3) { // left-over + y[i] = VP8RGBToY(bgr[2], bgr[1], bgr[0], YUV_HALF); + } +} + +static void ConvertARGBToY_SSE41(const uint32_t* argb, uint8_t* y, int width) { + const int max_width = width & ~15; + int i; + for (i = 0; i < max_width; i += 16) { + __m128i Y0, Y1, rgb[6]; + RGB32PackedToPlanar_SSE41(&argb[i], rgb); + ConvertRGBToY_SSE41(&rgb[0], &rgb[2], &rgb[4], &Y0); + ConvertRGBToY_SSE41(&rgb[1], &rgb[3], &rgb[5], &Y1); + STORE_16(_mm_packus_epi16(Y0, Y1), y + i); + } + for (; i < width; ++i) { // left-over + const uint32_t p = argb[i]; + y[i] = VP8RGBToY((p >> 16) & 0xff, (p >> 8) & 0xff, (p >> 0) & 0xff, + YUV_HALF); + } +} + +// Horizontal add (doubled) of two 16b values, result is 16b. +// in: A | B | C | D | ... -> out: 2*(A+B) | 2*(C+D) | ... +static void HorizontalAddPack_SSE41(const __m128i* const A, + const __m128i* const B, + __m128i* const out) { + const __m128i k2 = _mm_set1_epi16(2); + const __m128i C = _mm_madd_epi16(*A, k2); + const __m128i D = _mm_madd_epi16(*B, k2); + *out = _mm_packs_epi32(C, D); +} + +static void ConvertARGBToUV_SSE41(const uint32_t* argb, + uint8_t* u, uint8_t* v, + int src_width, int do_store) { + const int max_width = src_width & ~31; + int i; + for (i = 0; i < max_width; i += 32, u += 16, v += 16) { + __m128i rgb[6], U0, V0, U1, V1; + RGB32PackedToPlanar_SSE41(&argb[i], rgb); + HorizontalAddPack_SSE41(&rgb[0], &rgb[1], &rgb[0]); + HorizontalAddPack_SSE41(&rgb[2], &rgb[3], &rgb[2]); + HorizontalAddPack_SSE41(&rgb[4], &rgb[5], &rgb[4]); + ConvertRGBToUV_SSE41(&rgb[0], &rgb[2], &rgb[4], &U0, &V0); + + RGB32PackedToPlanar_SSE41(&argb[i + 16], rgb); + HorizontalAddPack_SSE41(&rgb[0], &rgb[1], &rgb[0]); + HorizontalAddPack_SSE41(&rgb[2], &rgb[3], &rgb[2]); + HorizontalAddPack_SSE41(&rgb[4], &rgb[5], &rgb[4]); + ConvertRGBToUV_SSE41(&rgb[0], &rgb[2], &rgb[4], &U1, &V1); + + U0 = _mm_packus_epi16(U0, U1); + V0 = _mm_packus_epi16(V0, V1); + if (!do_store) { + const __m128i prev_u = LOAD_16(u); + const __m128i prev_v = LOAD_16(v); + U0 = _mm_avg_epu8(U0, prev_u); + V0 = _mm_avg_epu8(V0, prev_v); + } + STORE_16(U0, u); + STORE_16(V0, v); + } + if (i < src_width) { // left-over + WebPConvertARGBToUV_C(argb + i, u, v, src_width - i, do_store); + } +} + +// Convert 16 packed ARGB 16b-values to r[], g[], b[] +static WEBP_INLINE void RGBA32PackedToPlanar_16b_SSE41( + const uint16_t* const rgbx, + __m128i* const r, __m128i* const g, __m128i* const b) { + const __m128i in0 = LOAD_16(rgbx + 0); // r0 | g0 | b0 |x| r1 | g1 | b1 |x + const __m128i in1 = LOAD_16(rgbx + 8); // r2 | g2 | b2 |x| r3 | g3 | b3 |x + const __m128i in2 = LOAD_16(rgbx + 16); // r4 | ... + const __m128i in3 = LOAD_16(rgbx + 24); // r6 | ... + // aarrggbb as 16-bit. + const __m128i shuff0 = + _mm_set_epi8(-1, -1, -1, -1, 13, 12, 5, 4, 11, 10, 3, 2, 9, 8, 1, 0); + const __m128i shuff1 = + _mm_set_epi8(13, 12, 5, 4, -1, -1, -1, -1, 11, 10, 3, 2, 9, 8, 1, 0); + const __m128i A0 = _mm_shuffle_epi8(in0, shuff0); + const __m128i A1 = _mm_shuffle_epi8(in1, shuff1); + const __m128i A2 = _mm_shuffle_epi8(in2, shuff0); + const __m128i A3 = _mm_shuffle_epi8(in3, shuff1); + // R0R1G0G1 + // B0B1**** + // R2R3G2G3 + // B2B3**** + // (OR is used to free port 5 for the unpack) + const __m128i B0 = _mm_unpacklo_epi32(A0, A1); + const __m128i B1 = _mm_or_si128(A0, A1); + const __m128i B2 = _mm_unpacklo_epi32(A2, A3); + const __m128i B3 = _mm_or_si128(A2, A3); + // Gather the channels. + *r = _mm_unpacklo_epi64(B0, B2); + *g = _mm_unpackhi_epi64(B0, B2); + *b = _mm_unpackhi_epi64(B1, B3); +} + +static void ConvertRGBA32ToUV_SSE41(const uint16_t* rgb, + uint8_t* u, uint8_t* v, int width) { + const int max_width = width & ~15; + const uint16_t* const last_rgb = rgb + 4 * max_width; + while (rgb < last_rgb) { + __m128i r, g, b, U0, V0, U1, V1; + RGBA32PackedToPlanar_16b_SSE41(rgb + 0, &r, &g, &b); + ConvertRGBToUV_SSE41(&r, &g, &b, &U0, &V0); + RGBA32PackedToPlanar_16b_SSE41(rgb + 32, &r, &g, &b); + ConvertRGBToUV_SSE41(&r, &g, &b, &U1, &V1); + STORE_16(_mm_packus_epi16(U0, U1), u); + STORE_16(_mm_packus_epi16(V0, V1), v); + u += 16; + v += 16; + rgb += 2 * 32; + } + if (max_width < width) { // left-over + WebPConvertRGBA32ToUV_C(rgb, u, v, width - max_width); + } +} + +//------------------------------------------------------------------------------ + +extern void WebPInitConvertARGBToYUVSSE41(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitConvertARGBToYUVSSE41(void) { + WebPConvertARGBToY = ConvertARGBToY_SSE41; + WebPConvertARGBToUV = ConvertARGBToUV_SSE41; + + WebPConvertRGB24ToY = ConvertRGB24ToY_SSE41; + WebPConvertBGR24ToY = ConvertBGR24ToY_SSE41; + + WebPConvertRGBA32ToUV = ConvertRGBA32ToUV_SSE41; +} + +//------------------------------------------------------------------------------ + +#else // !WEBP_USE_SSE41 + +WEBP_DSP_INIT_STUB(WebPInitSamplersSSE41) +WEBP_DSP_INIT_STUB(WebPInitConvertARGBToYUVSSE41) + +#endif // WEBP_USE_SSE41 diff --git a/third-party/webp/libwebp/src/enc/Makefile.am b/third-party/webp/libwebp/src/enc/Makefile.am new file mode 100644 index 0000000000..2fec804cb7 --- /dev/null +++ b/third-party/webp/libwebp/src/enc/Makefile.am @@ -0,0 +1,43 @@ +AM_CPPFLAGS += -I$(top_builddir) -I$(top_srcdir) +noinst_LTLIBRARIES = libwebpencode.la + +libwebpencode_la_SOURCES = +libwebpencode_la_SOURCES += alpha_enc.c +libwebpencode_la_SOURCES += analysis_enc.c +libwebpencode_la_SOURCES += backward_references_cost_enc.c +libwebpencode_la_SOURCES += backward_references_enc.c +libwebpencode_la_SOURCES += backward_references_enc.h +libwebpencode_la_SOURCES += config_enc.c +libwebpencode_la_SOURCES += cost_enc.c +libwebpencode_la_SOURCES += cost_enc.h +libwebpencode_la_SOURCES += filter_enc.c +libwebpencode_la_SOURCES += frame_enc.c +libwebpencode_la_SOURCES += histogram_enc.c +libwebpencode_la_SOURCES += histogram_enc.h +libwebpencode_la_SOURCES += iterator_enc.c +libwebpencode_la_SOURCES += near_lossless_enc.c +libwebpencode_la_SOURCES += picture_enc.c +libwebpencode_la_SOURCES += picture_csp_enc.c +libwebpencode_la_SOURCES += picture_psnr_enc.c +libwebpencode_la_SOURCES += picture_rescale_enc.c +libwebpencode_la_SOURCES += picture_tools_enc.c +libwebpencode_la_SOURCES += predictor_enc.c +libwebpencode_la_SOURCES += quant_enc.c +libwebpencode_la_SOURCES += syntax_enc.c +libwebpencode_la_SOURCES += token_enc.c +libwebpencode_la_SOURCES += tree_enc.c +libwebpencode_la_SOURCES += vp8i_enc.h +libwebpencode_la_SOURCES += vp8l_enc.c +libwebpencode_la_SOURCES += vp8li_enc.h +libwebpencode_la_SOURCES += webp_enc.c + +libwebpencodeinclude_HEADERS = +libwebpencodeinclude_HEADERS += ../webp/encode.h +libwebpencodeinclude_HEADERS += ../webp/types.h +noinst_HEADERS = +noinst_HEADERS += ../webp/format_constants.h + +libwebpencode_la_LIBADD = ../../sharpyuv/libsharpyuv.la +libwebpencode_la_LDFLAGS = -lm +libwebpencode_la_CPPFLAGS = $(AM_CPPFLAGS) +libwebpencodeincludedir = $(includedir)/webp diff --git a/third-party/webp/libwebp/src/enc/alpha_enc.c b/third-party/webp/libwebp/src/enc/alpha_enc.c new file mode 100644 index 0000000000..4a599f88a9 --- /dev/null +++ b/third-party/webp/libwebp/src/enc/alpha_enc.c @@ -0,0 +1,453 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Alpha-plane compression. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include +#include + +#include "src/enc/vp8i_enc.h" +#include "src/dsp/dsp.h" +#include "src/utils/filters_utils.h" +#include "src/utils/quant_levels_utils.h" +#include "src/utils/utils.h" +#include "src/webp/format_constants.h" + +// ----------------------------------------------------------------------------- +// Encodes the given alpha data via specified compression method 'method'. +// The pre-processing (quantization) is performed if 'quality' is less than 100. +// For such cases, the encoding is lossy. The valid range is [0, 100] for +// 'quality' and [0, 1] for 'method': +// 'method = 0' - No compression; +// 'method = 1' - Use lossless coder on the alpha plane only +// 'filter' values [0, 4] correspond to prediction modes none, horizontal, +// vertical & gradient filters. The prediction mode 4 will try all the +// prediction modes 0 to 3 and pick the best one. +// 'effort_level': specifies how much effort must be spent to try and reduce +// the compressed output size. In range 0 (quick) to 6 (slow). +// +// 'output' corresponds to the buffer containing compressed alpha data. +// This buffer is allocated by this method and caller should call +// WebPSafeFree(*output) when done. +// 'output_size' corresponds to size of this compressed alpha buffer. +// +// Returns 1 on successfully encoding the alpha and +// 0 if either: +// invalid quality or method, or +// memory allocation for the compressed data fails. + +#include "src/enc/vp8li_enc.h" + +static int EncodeLossless(const uint8_t* const data, int width, int height, + int effort_level, // in [0..6] range + int use_quality_100, VP8LBitWriter* const bw, + WebPAuxStats* const stats) { + int ok = 0; + WebPConfig config; + WebPPicture picture; + + if (!WebPPictureInit(&picture)) return 0; + picture.width = width; + picture.height = height; + picture.use_argb = 1; + picture.stats = stats; + if (!WebPPictureAlloc(&picture)) return 0; + + // Transfer the alpha values to the green channel. + WebPDispatchAlphaToGreen(data, width, picture.width, picture.height, + picture.argb, picture.argb_stride); + + WebPConfigInit(&config); + config.lossless = 1; + // Enable exact, or it would alter RGB values of transparent alpha, which is + // normally OK but not here since we are not encoding the input image but an + // internal encoding-related image containing necessary exact information in + // RGB channels. + config.exact = 1; + config.method = effort_level; // impact is very small + // Set a low default quality for encoding alpha. Ensure that Alpha quality at + // lower methods (3 and below) is less than the threshold for triggering + // costly 'BackwardReferencesTraceBackwards'. + // If the alpha quality is set to 100 and the method to 6, allow for a high + // lossless quality to trigger the cruncher. + config.quality = + (use_quality_100 && effort_level == 6) ? 100 : 8.f * effort_level; + assert(config.quality >= 0 && config.quality <= 100.f); + + // TODO(urvang): Temporary fix to avoid generating images that trigger + // a decoder bug related to alpha with color cache. + // See: https://code.google.com/p/webp/issues/detail?id=239 + // Need to re-enable this later. + ok = VP8LEncodeStream(&config, &picture, bw, /*use_cache=*/0); + WebPPictureFree(&picture); + ok = ok && !bw->error_; + if (!ok) { + VP8LBitWriterWipeOut(bw); + return 0; + } + return 1; +} + +// ----------------------------------------------------------------------------- + +// Small struct to hold the result of a filter mode compression attempt. +typedef struct { + size_t score; + VP8BitWriter bw; + WebPAuxStats stats; +} FilterTrial; + +// This function always returns an initialized 'bw' object, even upon error. +static int EncodeAlphaInternal(const uint8_t* const data, int width, int height, + int method, int filter, int reduce_levels, + int effort_level, // in [0..6] range + uint8_t* const tmp_alpha, + FilterTrial* result) { + int ok = 0; + const uint8_t* alpha_src; + WebPFilterFunc filter_func; + uint8_t header; + const size_t data_size = width * height; + const uint8_t* output = NULL; + size_t output_size = 0; + VP8LBitWriter tmp_bw; + + assert((uint64_t)data_size == (uint64_t)width * height); // as per spec + assert(filter >= 0 && filter < WEBP_FILTER_LAST); + assert(method >= ALPHA_NO_COMPRESSION); + assert(method <= ALPHA_LOSSLESS_COMPRESSION); + assert(sizeof(header) == ALPHA_HEADER_LEN); + + filter_func = WebPFilters[filter]; + if (filter_func != NULL) { + filter_func(data, width, height, width, tmp_alpha); + alpha_src = tmp_alpha; + } else { + alpha_src = data; + } + + if (method != ALPHA_NO_COMPRESSION) { + ok = VP8LBitWriterInit(&tmp_bw, data_size >> 3); + ok = ok && EncodeLossless(alpha_src, width, height, effort_level, + !reduce_levels, &tmp_bw, &result->stats); + if (ok) { + output = VP8LBitWriterFinish(&tmp_bw); + if (tmp_bw.error_) { + VP8LBitWriterWipeOut(&tmp_bw); + memset(&result->bw, 0, sizeof(result->bw)); + return 0; + } + output_size = VP8LBitWriterNumBytes(&tmp_bw); + if (output_size > data_size) { + // compressed size is larger than source! Revert to uncompressed mode. + method = ALPHA_NO_COMPRESSION; + VP8LBitWriterWipeOut(&tmp_bw); + } + } else { + VP8LBitWriterWipeOut(&tmp_bw); + memset(&result->bw, 0, sizeof(result->bw)); + return 0; + } + } + + if (method == ALPHA_NO_COMPRESSION) { + output = alpha_src; + output_size = data_size; + ok = 1; + } + + // Emit final result. + header = method | (filter << 2); + if (reduce_levels) header |= ALPHA_PREPROCESSED_LEVELS << 4; + + if (!VP8BitWriterInit(&result->bw, ALPHA_HEADER_LEN + output_size)) ok = 0; + ok = ok && VP8BitWriterAppend(&result->bw, &header, ALPHA_HEADER_LEN); + ok = ok && VP8BitWriterAppend(&result->bw, output, output_size); + + if (method != ALPHA_NO_COMPRESSION) { + VP8LBitWriterWipeOut(&tmp_bw); + } + ok = ok && !result->bw.error_; + result->score = VP8BitWriterSize(&result->bw); + return ok; +} + +// ----------------------------------------------------------------------------- + +static int GetNumColors(const uint8_t* data, int width, int height, + int stride) { + int j; + int colors = 0; + uint8_t color[256] = { 0 }; + + for (j = 0; j < height; ++j) { + int i; + const uint8_t* const p = data + j * stride; + for (i = 0; i < width; ++i) { + color[p[i]] = 1; + } + } + for (j = 0; j < 256; ++j) { + if (color[j] > 0) ++colors; + } + return colors; +} + +#define FILTER_TRY_NONE (1 << WEBP_FILTER_NONE) +#define FILTER_TRY_ALL ((1 << WEBP_FILTER_LAST) - 1) + +// Given the input 'filter' option, return an OR'd bit-set of filters to try. +static uint32_t GetFilterMap(const uint8_t* alpha, int width, int height, + int filter, int effort_level) { + uint32_t bit_map = 0U; + if (filter == WEBP_FILTER_FAST) { + // Quick estimate of the best candidate. + int try_filter_none = (effort_level > 3); + const int kMinColorsForFilterNone = 16; + const int kMaxColorsForFilterNone = 192; + const int num_colors = GetNumColors(alpha, width, height, width); + // For low number of colors, NONE yields better compression. + filter = (num_colors <= kMinColorsForFilterNone) + ? WEBP_FILTER_NONE + : WebPEstimateBestFilter(alpha, width, height, width); + bit_map |= 1 << filter; + // For large number of colors, try FILTER_NONE in addition to the best + // filter as well. + if (try_filter_none || num_colors > kMaxColorsForFilterNone) { + bit_map |= FILTER_TRY_NONE; + } + } else if (filter == WEBP_FILTER_NONE) { + bit_map = FILTER_TRY_NONE; + } else { // WEBP_FILTER_BEST -> try all + bit_map = FILTER_TRY_ALL; + } + return bit_map; +} + +static void InitFilterTrial(FilterTrial* const score) { + score->score = (size_t)~0U; + VP8BitWriterInit(&score->bw, 0); +} + +static int ApplyFiltersAndEncode(const uint8_t* alpha, int width, int height, + size_t data_size, int method, int filter, + int reduce_levels, int effort_level, + uint8_t** const output, + size_t* const output_size, + WebPAuxStats* const stats) { + int ok = 1; + FilterTrial best; + uint32_t try_map = + GetFilterMap(alpha, width, height, filter, effort_level); + InitFilterTrial(&best); + + if (try_map != FILTER_TRY_NONE) { + uint8_t* filtered_alpha = (uint8_t*)WebPSafeMalloc(1ULL, data_size); + if (filtered_alpha == NULL) return 0; + + for (filter = WEBP_FILTER_NONE; ok && try_map; ++filter, try_map >>= 1) { + if (try_map & 1) { + FilterTrial trial; + ok = EncodeAlphaInternal(alpha, width, height, method, filter, + reduce_levels, effort_level, filtered_alpha, + &trial); + if (ok && trial.score < best.score) { + VP8BitWriterWipeOut(&best.bw); + best = trial; + } else { + VP8BitWriterWipeOut(&trial.bw); + } + } + } + WebPSafeFree(filtered_alpha); + } else { + ok = EncodeAlphaInternal(alpha, width, height, method, WEBP_FILTER_NONE, + reduce_levels, effort_level, NULL, &best); + } + if (ok) { +#if !defined(WEBP_DISABLE_STATS) + if (stats != NULL) { + stats->lossless_features = best.stats.lossless_features; + stats->histogram_bits = best.stats.histogram_bits; + stats->transform_bits = best.stats.transform_bits; + stats->cache_bits = best.stats.cache_bits; + stats->palette_size = best.stats.palette_size; + stats->lossless_size = best.stats.lossless_size; + stats->lossless_hdr_size = best.stats.lossless_hdr_size; + stats->lossless_data_size = best.stats.lossless_data_size; + } +#else + (void)stats; +#endif + *output_size = VP8BitWriterSize(&best.bw); + *output = VP8BitWriterBuf(&best.bw); + } else { + VP8BitWriterWipeOut(&best.bw); + } + return ok; +} + +static int EncodeAlpha(VP8Encoder* const enc, + int quality, int method, int filter, + int effort_level, + uint8_t** const output, size_t* const output_size) { + const WebPPicture* const pic = enc->pic_; + const int width = pic->width; + const int height = pic->height; + + uint8_t* quant_alpha = NULL; + const size_t data_size = width * height; + uint64_t sse = 0; + int ok = 1; + const int reduce_levels = (quality < 100); + + // quick correctness checks + assert((uint64_t)data_size == (uint64_t)width * height); // as per spec + assert(enc != NULL && pic != NULL && pic->a != NULL); + assert(output != NULL && output_size != NULL); + assert(width > 0 && height > 0); + assert(pic->a_stride >= width); + assert(filter >= WEBP_FILTER_NONE && filter <= WEBP_FILTER_FAST); + + if (quality < 0 || quality > 100) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_INVALID_CONFIGURATION); + } + + if (method < ALPHA_NO_COMPRESSION || method > ALPHA_LOSSLESS_COMPRESSION) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_INVALID_CONFIGURATION); + } + + if (method == ALPHA_NO_COMPRESSION) { + // Don't filter, as filtering will make no impact on compressed size. + filter = WEBP_FILTER_NONE; + } + + quant_alpha = (uint8_t*)WebPSafeMalloc(1ULL, data_size); + if (quant_alpha == NULL) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + + // Extract alpha data (width x height) from raw_data (stride x height). + WebPCopyPlane(pic->a, pic->a_stride, quant_alpha, width, width, height); + + if (reduce_levels) { // No Quantization required for 'quality = 100'. + // 16 alpha levels gives quite a low MSE w.r.t original alpha plane hence + // mapped to moderate quality 70. Hence Quality:[0, 70] -> Levels:[2, 16] + // and Quality:]70, 100] -> Levels:]16, 256]. + const int alpha_levels = (quality <= 70) ? (2 + quality / 5) + : (16 + (quality - 70) * 8); + ok = QuantizeLevels(quant_alpha, width, height, alpha_levels, &sse); + } + + if (ok) { + VP8FiltersInit(); + ok = ApplyFiltersAndEncode(quant_alpha, width, height, data_size, method, + filter, reduce_levels, effort_level, output, + output_size, pic->stats); + if (!ok) { + WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); // imprecise + } +#if !defined(WEBP_DISABLE_STATS) + if (pic->stats != NULL) { // need stats? + pic->stats->coded_size += (int)(*output_size); + enc->sse_[3] = sse; + } +#endif + } + + WebPSafeFree(quant_alpha); + return ok; +} + +//------------------------------------------------------------------------------ +// Main calls + +static int CompressAlphaJob(void* arg1, void* unused) { + VP8Encoder* const enc = (VP8Encoder*)arg1; + const WebPConfig* config = enc->config_; + uint8_t* alpha_data = NULL; + size_t alpha_size = 0; + const int effort_level = config->method; // maps to [0..6] + const WEBP_FILTER_TYPE filter = + (config->alpha_filtering == 0) ? WEBP_FILTER_NONE : + (config->alpha_filtering == 1) ? WEBP_FILTER_FAST : + WEBP_FILTER_BEST; + if (!EncodeAlpha(enc, config->alpha_quality, config->alpha_compression, + filter, effort_level, &alpha_data, &alpha_size)) { + return 0; + } + if (alpha_size != (uint32_t)alpha_size) { // Soundness check. + WebPSafeFree(alpha_data); + return 0; + } + enc->alpha_data_size_ = (uint32_t)alpha_size; + enc->alpha_data_ = alpha_data; + (void)unused; + return 1; +} + +void VP8EncInitAlpha(VP8Encoder* const enc) { + WebPInitAlphaProcessing(); + enc->has_alpha_ = WebPPictureHasTransparency(enc->pic_); + enc->alpha_data_ = NULL; + enc->alpha_data_size_ = 0; + if (enc->thread_level_ > 0) { + WebPWorker* const worker = &enc->alpha_worker_; + WebPGetWorkerInterface()->Init(worker); + worker->data1 = enc; + worker->data2 = NULL; + worker->hook = CompressAlphaJob; + } +} + +int VP8EncStartAlpha(VP8Encoder* const enc) { + if (enc->has_alpha_) { + if (enc->thread_level_ > 0) { + WebPWorker* const worker = &enc->alpha_worker_; + // Makes sure worker is good to go. + if (!WebPGetWorkerInterface()->Reset(worker)) { + return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + WebPGetWorkerInterface()->Launch(worker); + return 1; + } else { + return CompressAlphaJob(enc, NULL); // just do the job right away + } + } + return 1; +} + +int VP8EncFinishAlpha(VP8Encoder* const enc) { + if (enc->has_alpha_) { + if (enc->thread_level_ > 0) { + WebPWorker* const worker = &enc->alpha_worker_; + if (!WebPGetWorkerInterface()->Sync(worker)) return 0; // error + } + } + return WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_); +} + +int VP8EncDeleteAlpha(VP8Encoder* const enc) { + int ok = 1; + if (enc->thread_level_ > 0) { + WebPWorker* const worker = &enc->alpha_worker_; + // finish anything left in flight + ok = WebPGetWorkerInterface()->Sync(worker); + // still need to end the worker, even if !ok + WebPGetWorkerInterface()->End(worker); + } + WebPSafeFree(enc->alpha_data_); + enc->alpha_data_ = NULL; + enc->alpha_data_size_ = 0; + enc->has_alpha_ = 0; + return ok; +} diff --git a/third-party/webp/libwebp/src/enc/analysis_enc.c b/third-party/webp/libwebp/src/enc/analysis_enc.c new file mode 100644 index 0000000000..962eaa998f --- /dev/null +++ b/third-party/webp/libwebp/src/enc/analysis_enc.c @@ -0,0 +1,483 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Macroblock analysis +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include +#include + +#include "src/enc/vp8i_enc.h" +#include "src/enc/cost_enc.h" +#include "src/utils/utils.h" + +#define MAX_ITERS_K_MEANS 6 + +//------------------------------------------------------------------------------ +// Smooth the segment map by replacing isolated block by the majority of its +// neighbours. + +static void SmoothSegmentMap(VP8Encoder* const enc) { + int n, x, y; + const int w = enc->mb_w_; + const int h = enc->mb_h_; + const int majority_cnt_3_x_3_grid = 5; + uint8_t* const tmp = (uint8_t*)WebPSafeMalloc(w * h, sizeof(*tmp)); + assert((uint64_t)(w * h) == (uint64_t)w * h); // no overflow, as per spec + + if (tmp == NULL) return; + for (y = 1; y < h - 1; ++y) { + for (x = 1; x < w - 1; ++x) { + int cnt[NUM_MB_SEGMENTS] = { 0 }; + const VP8MBInfo* const mb = &enc->mb_info_[x + w * y]; + int majority_seg = mb->segment_; + // Check the 8 neighbouring segment values. + cnt[mb[-w - 1].segment_]++; // top-left + cnt[mb[-w + 0].segment_]++; // top + cnt[mb[-w + 1].segment_]++; // top-right + cnt[mb[ - 1].segment_]++; // left + cnt[mb[ + 1].segment_]++; // right + cnt[mb[ w - 1].segment_]++; // bottom-left + cnt[mb[ w + 0].segment_]++; // bottom + cnt[mb[ w + 1].segment_]++; // bottom-right + for (n = 0; n < NUM_MB_SEGMENTS; ++n) { + if (cnt[n] >= majority_cnt_3_x_3_grid) { + majority_seg = n; + break; + } + } + tmp[x + y * w] = majority_seg; + } + } + for (y = 1; y < h - 1; ++y) { + for (x = 1; x < w - 1; ++x) { + VP8MBInfo* const mb = &enc->mb_info_[x + w * y]; + mb->segment_ = tmp[x + y * w]; + } + } + WebPSafeFree(tmp); +} + +//------------------------------------------------------------------------------ +// set segment susceptibility alpha_ / beta_ + +static WEBP_INLINE int clip(int v, int m, int M) { + return (v < m) ? m : (v > M) ? M : v; +} + +static void SetSegmentAlphas(VP8Encoder* const enc, + const int centers[NUM_MB_SEGMENTS], + int mid) { + const int nb = enc->segment_hdr_.num_segments_; + int min = centers[0], max = centers[0]; + int n; + + if (nb > 1) { + for (n = 0; n < nb; ++n) { + if (min > centers[n]) min = centers[n]; + if (max < centers[n]) max = centers[n]; + } + } + if (max == min) max = min + 1; + assert(mid <= max && mid >= min); + for (n = 0; n < nb; ++n) { + const int alpha = 255 * (centers[n] - mid) / (max - min); + const int beta = 255 * (centers[n] - min) / (max - min); + enc->dqm_[n].alpha_ = clip(alpha, -127, 127); + enc->dqm_[n].beta_ = clip(beta, 0, 255); + } +} + +//------------------------------------------------------------------------------ +// Compute susceptibility based on DCT-coeff histograms: +// the higher, the "easier" the macroblock is to compress. + +#define MAX_ALPHA 255 // 8b of precision for susceptibilities. +#define ALPHA_SCALE (2 * MAX_ALPHA) // scaling factor for alpha. +#define DEFAULT_ALPHA (-1) +#define IS_BETTER_ALPHA(alpha, best_alpha) ((alpha) > (best_alpha)) + +static int FinalAlphaValue(int alpha) { + alpha = MAX_ALPHA - alpha; + return clip(alpha, 0, MAX_ALPHA); +} + +static int GetAlpha(const VP8Histogram* const histo) { + // 'alpha' will later be clipped to [0..MAX_ALPHA] range, clamping outer + // values which happen to be mostly noise. This leaves the maximum precision + // for handling the useful small values which contribute most. + const int max_value = histo->max_value; + const int last_non_zero = histo->last_non_zero; + const int alpha = + (max_value > 1) ? ALPHA_SCALE * last_non_zero / max_value : 0; + return alpha; +} + +static void InitHistogram(VP8Histogram* const histo) { + histo->max_value = 0; + histo->last_non_zero = 1; +} + +//------------------------------------------------------------------------------ +// Simplified k-Means, to assign Nb segments based on alpha-histogram + +static void AssignSegments(VP8Encoder* const enc, + const int alphas[MAX_ALPHA + 1]) { + // 'num_segments_' is previously validated and <= NUM_MB_SEGMENTS, but an + // explicit check is needed to avoid spurious warning about 'n + 1' exceeding + // array bounds of 'centers' with some compilers (noticed with gcc-4.9). + const int nb = (enc->segment_hdr_.num_segments_ < NUM_MB_SEGMENTS) ? + enc->segment_hdr_.num_segments_ : NUM_MB_SEGMENTS; + int centers[NUM_MB_SEGMENTS]; + int weighted_average = 0; + int map[MAX_ALPHA + 1]; + int a, n, k; + int min_a = 0, max_a = MAX_ALPHA, range_a; + // 'int' type is ok for histo, and won't overflow + int accum[NUM_MB_SEGMENTS], dist_accum[NUM_MB_SEGMENTS]; + + assert(nb >= 1); + assert(nb <= NUM_MB_SEGMENTS); + + // bracket the input + for (n = 0; n <= MAX_ALPHA && alphas[n] == 0; ++n) {} + min_a = n; + for (n = MAX_ALPHA; n > min_a && alphas[n] == 0; --n) {} + max_a = n; + range_a = max_a - min_a; + + // Spread initial centers evenly + for (k = 0, n = 1; k < nb; ++k, n += 2) { + assert(n < 2 * nb); + centers[k] = min_a + (n * range_a) / (2 * nb); + } + + for (k = 0; k < MAX_ITERS_K_MEANS; ++k) { // few iters are enough + int total_weight; + int displaced; + // Reset stats + for (n = 0; n < nb; ++n) { + accum[n] = 0; + dist_accum[n] = 0; + } + // Assign nearest center for each 'a' + n = 0; // track the nearest center for current 'a' + for (a = min_a; a <= max_a; ++a) { + if (alphas[a]) { + while (n + 1 < nb && abs(a - centers[n + 1]) < abs(a - centers[n])) { + n++; + } + map[a] = n; + // accumulate contribution into best centroid + dist_accum[n] += a * alphas[a]; + accum[n] += alphas[a]; + } + } + // All point are classified. Move the centroids to the + // center of their respective cloud. + displaced = 0; + weighted_average = 0; + total_weight = 0; + for (n = 0; n < nb; ++n) { + if (accum[n]) { + const int new_center = (dist_accum[n] + accum[n] / 2) / accum[n]; + displaced += abs(centers[n] - new_center); + centers[n] = new_center; + weighted_average += new_center * accum[n]; + total_weight += accum[n]; + } + } + weighted_average = (weighted_average + total_weight / 2) / total_weight; + if (displaced < 5) break; // no need to keep on looping... + } + + // Map each original value to the closest centroid + for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) { + VP8MBInfo* const mb = &enc->mb_info_[n]; + const int alpha = mb->alpha_; + mb->segment_ = map[alpha]; + mb->alpha_ = centers[map[alpha]]; // for the record. + } + + if (nb > 1) { + const int smooth = (enc->config_->preprocessing & 1); + if (smooth) SmoothSegmentMap(enc); + } + + SetSegmentAlphas(enc, centers, weighted_average); // pick some alphas. +} + +//------------------------------------------------------------------------------ +// Macroblock analysis: collect histogram for each mode, deduce the maximal +// susceptibility and set best modes for this macroblock. +// Segment assignment is done later. + +// Number of modes to inspect for alpha_ evaluation. We don't need to test all +// the possible modes during the analysis phase: we risk falling into a local +// optimum, or be subject to boundary effect +#define MAX_INTRA16_MODE 2 +#define MAX_INTRA4_MODE 2 +#define MAX_UV_MODE 2 + +static int MBAnalyzeBestIntra16Mode(VP8EncIterator* const it) { + const int max_mode = MAX_INTRA16_MODE; + int mode; + int best_alpha = DEFAULT_ALPHA; + int best_mode = 0; + + VP8MakeLuma16Preds(it); + for (mode = 0; mode < max_mode; ++mode) { + VP8Histogram histo; + int alpha; + + InitHistogram(&histo); + VP8CollectHistogram(it->yuv_in_ + Y_OFF_ENC, + it->yuv_p_ + VP8I16ModeOffsets[mode], + 0, 16, &histo); + alpha = GetAlpha(&histo); + if (IS_BETTER_ALPHA(alpha, best_alpha)) { + best_alpha = alpha; + best_mode = mode; + } + } + VP8SetIntra16Mode(it, best_mode); + return best_alpha; +} + +static int FastMBAnalyze(VP8EncIterator* const it) { + // Empirical cut-off value, should be around 16 (~=block size). We use the + // [8-17] range and favor intra4 at high quality, intra16 for low quality. + const int q = (int)it->enc_->config_->quality; + const uint32_t kThreshold = 8 + (17 - 8) * q / 100; + int k; + uint32_t dc[16], m, m2; + for (k = 0; k < 16; k += 4) { + VP8Mean16x4(it->yuv_in_ + Y_OFF_ENC + k * BPS, &dc[k]); + } + for (m = 0, m2 = 0, k = 0; k < 16; ++k) { + m += dc[k]; + m2 += dc[k] * dc[k]; + } + if (kThreshold * m2 < m * m) { + VP8SetIntra16Mode(it, 0); // DC16 + } else { + const uint8_t modes[16] = { 0 }; // DC4 + VP8SetIntra4Mode(it, modes); + } + return 0; +} + +static int MBAnalyzeBestUVMode(VP8EncIterator* const it) { + int best_alpha = DEFAULT_ALPHA; + int smallest_alpha = 0; + int best_mode = 0; + const int max_mode = MAX_UV_MODE; + int mode; + + VP8MakeChroma8Preds(it); + for (mode = 0; mode < max_mode; ++mode) { + VP8Histogram histo; + int alpha; + InitHistogram(&histo); + VP8CollectHistogram(it->yuv_in_ + U_OFF_ENC, + it->yuv_p_ + VP8UVModeOffsets[mode], + 16, 16 + 4 + 4, &histo); + alpha = GetAlpha(&histo); + if (IS_BETTER_ALPHA(alpha, best_alpha)) { + best_alpha = alpha; + } + // The best prediction mode tends to be the one with the smallest alpha. + if (mode == 0 || alpha < smallest_alpha) { + smallest_alpha = alpha; + best_mode = mode; + } + } + VP8SetIntraUVMode(it, best_mode); + return best_alpha; +} + +static void MBAnalyze(VP8EncIterator* const it, + int alphas[MAX_ALPHA + 1], + int* const alpha, int* const uv_alpha) { + const VP8Encoder* const enc = it->enc_; + int best_alpha, best_uv_alpha; + + VP8SetIntra16Mode(it, 0); // default: Intra16, DC_PRED + VP8SetSkip(it, 0); // not skipped + VP8SetSegment(it, 0); // default segment, spec-wise. + + if (enc->method_ <= 1) { + best_alpha = FastMBAnalyze(it); + } else { + best_alpha = MBAnalyzeBestIntra16Mode(it); + } + best_uv_alpha = MBAnalyzeBestUVMode(it); + + // Final susceptibility mix + best_alpha = (3 * best_alpha + best_uv_alpha + 2) >> 2; + best_alpha = FinalAlphaValue(best_alpha); + alphas[best_alpha]++; + it->mb_->alpha_ = best_alpha; // for later remapping. + + // Accumulate for later complexity analysis. + *alpha += best_alpha; // mixed susceptibility (not just luma) + *uv_alpha += best_uv_alpha; +} + +static void DefaultMBInfo(VP8MBInfo* const mb) { + mb->type_ = 1; // I16x16 + mb->uv_mode_ = 0; + mb->skip_ = 0; // not skipped + mb->segment_ = 0; // default segment + mb->alpha_ = 0; +} + +//------------------------------------------------------------------------------ +// Main analysis loop: +// Collect all susceptibilities for each macroblock and record their +// distribution in alphas[]. Segments is assigned a-posteriori, based on +// this histogram. +// We also pick an intra16 prediction mode, which shouldn't be considered +// final except for fast-encode settings. We can also pick some intra4 modes +// and decide intra4/intra16, but that's usually almost always a bad choice at +// this stage. + +static void ResetAllMBInfo(VP8Encoder* const enc) { + int n; + for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) { + DefaultMBInfo(&enc->mb_info_[n]); + } + // Default susceptibilities. + enc->dqm_[0].alpha_ = 0; + enc->dqm_[0].beta_ = 0; + // Note: we can't compute this alpha_ / uv_alpha_ -> set to default value. + enc->alpha_ = 0; + enc->uv_alpha_ = 0; + WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_); +} + +// struct used to collect job result +typedef struct { + WebPWorker worker; + int alphas[MAX_ALPHA + 1]; + int alpha, uv_alpha; + VP8EncIterator it; + int delta_progress; +} SegmentJob; + +// main work call +static int DoSegmentsJob(void* arg1, void* arg2) { + SegmentJob* const job = (SegmentJob*)arg1; + VP8EncIterator* const it = (VP8EncIterator*)arg2; + int ok = 1; + if (!VP8IteratorIsDone(it)) { + uint8_t tmp[32 + WEBP_ALIGN_CST]; + uint8_t* const scratch = (uint8_t*)WEBP_ALIGN(tmp); + do { + // Let's pretend we have perfect lossless reconstruction. + VP8IteratorImport(it, scratch); + MBAnalyze(it, job->alphas, &job->alpha, &job->uv_alpha); + ok = VP8IteratorProgress(it, job->delta_progress); + } while (ok && VP8IteratorNext(it)); + } + return ok; +} + +#ifdef WEBP_USE_THREAD +static void MergeJobs(const SegmentJob* const src, SegmentJob* const dst) { + int i; + for (i = 0; i <= MAX_ALPHA; ++i) dst->alphas[i] += src->alphas[i]; + dst->alpha += src->alpha; + dst->uv_alpha += src->uv_alpha; +} +#endif + +// initialize the job struct with some tasks to perform +static void InitSegmentJob(VP8Encoder* const enc, SegmentJob* const job, + int start_row, int end_row) { + WebPGetWorkerInterface()->Init(&job->worker); + job->worker.data1 = job; + job->worker.data2 = &job->it; + job->worker.hook = DoSegmentsJob; + VP8IteratorInit(enc, &job->it); + VP8IteratorSetRow(&job->it, start_row); + VP8IteratorSetCountDown(&job->it, (end_row - start_row) * enc->mb_w_); + memset(job->alphas, 0, sizeof(job->alphas)); + job->alpha = 0; + job->uv_alpha = 0; + // only one of both jobs can record the progress, since we don't + // expect the user's hook to be multi-thread safe + job->delta_progress = (start_row == 0) ? 20 : 0; +} + +// main entry point +int VP8EncAnalyze(VP8Encoder* const enc) { + int ok = 1; + const int do_segments = + enc->config_->emulate_jpeg_size || // We need the complexity evaluation. + (enc->segment_hdr_.num_segments_ > 1) || + (enc->method_ <= 1); // for method 0 - 1, we need preds_[] to be filled. + if (do_segments) { + const int last_row = enc->mb_h_; + const int total_mb = last_row * enc->mb_w_; +#ifdef WEBP_USE_THREAD + // We give a little more than a half work to the main thread. + const int split_row = (9 * last_row + 15) >> 4; + const int kMinSplitRow = 2; // minimal rows needed for mt to be worth it + const int do_mt = (enc->thread_level_ > 0) && (split_row >= kMinSplitRow); +#else + const int do_mt = 0; +#endif + const WebPWorkerInterface* const worker_interface = + WebPGetWorkerInterface(); + SegmentJob main_job; + if (do_mt) { +#ifdef WEBP_USE_THREAD + SegmentJob side_job; + // Note the use of '&' instead of '&&' because we must call the functions + // no matter what. + InitSegmentJob(enc, &main_job, 0, split_row); + InitSegmentJob(enc, &side_job, split_row, last_row); + // we don't need to call Reset() on main_job.worker, since we're calling + // WebPWorkerExecute() on it + ok &= worker_interface->Reset(&side_job.worker); + // launch the two jobs in parallel + if (ok) { + worker_interface->Launch(&side_job.worker); + worker_interface->Execute(&main_job.worker); + ok &= worker_interface->Sync(&side_job.worker); + ok &= worker_interface->Sync(&main_job.worker); + } + worker_interface->End(&side_job.worker); + if (ok) MergeJobs(&side_job, &main_job); // merge results together +#endif // WEBP_USE_THREAD + } else { + // Even for single-thread case, we use the generic Worker tools. + InitSegmentJob(enc, &main_job, 0, last_row); + worker_interface->Execute(&main_job.worker); + ok &= worker_interface->Sync(&main_job.worker); + } + worker_interface->End(&main_job.worker); + if (ok) { + enc->alpha_ = main_job.alpha / total_mb; + enc->uv_alpha_ = main_job.uv_alpha / total_mb; + AssignSegments(enc, main_job.alphas); + } + } else { // Use only one default segment. + ResetAllMBInfo(enc); + } + if (!ok) { + return WebPEncodingSetError(enc->pic_, + VP8_ENC_ERROR_OUT_OF_MEMORY); // imprecise + } + return ok; +} + diff --git a/third-party/webp/libwebp/src/enc/backward_references_cost_enc.c b/third-party/webp/libwebp/src/enc/backward_references_cost_enc.c new file mode 100644 index 0000000000..6968ef3c9f --- /dev/null +++ b/third-party/webp/libwebp/src/enc/backward_references_cost_enc.c @@ -0,0 +1,795 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Improves a given set of backward references by analyzing its bit cost. +// The algorithm is similar to the Zopfli compression algorithm but tailored to +// images. +// +// Author: Vincent Rabaud (vrabaud@google.com) +// + +#include +#include + +#include "src/dsp/lossless_common.h" +#include "src/enc/backward_references_enc.h" +#include "src/enc/histogram_enc.h" +#include "src/utils/color_cache_utils.h" +#include "src/utils/utils.h" + +#define VALUES_IN_BYTE 256 + +extern void VP8LClearBackwardRefs(VP8LBackwardRefs* const refs); +extern int VP8LDistanceToPlaneCode(int xsize, int dist); +extern void VP8LBackwardRefsCursorAdd(VP8LBackwardRefs* const refs, + const PixOrCopy v); + +typedef struct { + float alpha_[VALUES_IN_BYTE]; + float red_[VALUES_IN_BYTE]; + float blue_[VALUES_IN_BYTE]; + float distance_[NUM_DISTANCE_CODES]; + float* literal_; +} CostModel; + +static void ConvertPopulationCountTableToBitEstimates( + int num_symbols, const uint32_t population_counts[], float output[]) { + uint32_t sum = 0; + int nonzeros = 0; + int i; + for (i = 0; i < num_symbols; ++i) { + sum += population_counts[i]; + if (population_counts[i] > 0) { + ++nonzeros; + } + } + if (nonzeros <= 1) { + memset(output, 0, num_symbols * sizeof(*output)); + } else { + const float logsum = VP8LFastLog2(sum); + for (i = 0; i < num_symbols; ++i) { + output[i] = logsum - VP8LFastLog2(population_counts[i]); + } + } +} + +static int CostModelBuild(CostModel* const m, int xsize, int cache_bits, + const VP8LBackwardRefs* const refs) { + int ok = 0; + VP8LRefsCursor c = VP8LRefsCursorInit(refs); + VP8LHistogram* const histo = VP8LAllocateHistogram(cache_bits); + if (histo == NULL) goto Error; + + // The following code is similar to VP8LHistogramCreate but converts the + // distance to plane code. + VP8LHistogramInit(histo, cache_bits, /*init_arrays=*/ 1); + while (VP8LRefsCursorOk(&c)) { + VP8LHistogramAddSinglePixOrCopy(histo, c.cur_pos, VP8LDistanceToPlaneCode, + xsize); + VP8LRefsCursorNext(&c); + } + + ConvertPopulationCountTableToBitEstimates( + VP8LHistogramNumCodes(histo->palette_code_bits_), histo->literal_, + m->literal_); + ConvertPopulationCountTableToBitEstimates( + VALUES_IN_BYTE, histo->red_, m->red_); + ConvertPopulationCountTableToBitEstimates( + VALUES_IN_BYTE, histo->blue_, m->blue_); + ConvertPopulationCountTableToBitEstimates( + VALUES_IN_BYTE, histo->alpha_, m->alpha_); + ConvertPopulationCountTableToBitEstimates( + NUM_DISTANCE_CODES, histo->distance_, m->distance_); + ok = 1; + + Error: + VP8LFreeHistogram(histo); + return ok; +} + +static WEBP_INLINE float GetLiteralCost(const CostModel* const m, uint32_t v) { + return m->alpha_[v >> 24] + + m->red_[(v >> 16) & 0xff] + + m->literal_[(v >> 8) & 0xff] + + m->blue_[v & 0xff]; +} + +static WEBP_INLINE float GetCacheCost(const CostModel* const m, uint32_t idx) { + const int literal_idx = VALUES_IN_BYTE + NUM_LENGTH_CODES + idx; + return m->literal_[literal_idx]; +} + +static WEBP_INLINE float GetLengthCost(const CostModel* const m, + uint32_t length) { + int code, extra_bits; + VP8LPrefixEncodeBits(length, &code, &extra_bits); + return m->literal_[VALUES_IN_BYTE + code] + extra_bits; +} + +static WEBP_INLINE float GetDistanceCost(const CostModel* const m, + uint32_t distance) { + int code, extra_bits; + VP8LPrefixEncodeBits(distance, &code, &extra_bits); + return m->distance_[code] + extra_bits; +} + +static WEBP_INLINE void AddSingleLiteralWithCostModel( + const uint32_t* const argb, VP8LColorCache* const hashers, + const CostModel* const cost_model, int idx, int use_color_cache, + float prev_cost, float* const cost, uint16_t* const dist_array) { + float cost_val = prev_cost; + const uint32_t color = argb[idx]; + const int ix = use_color_cache ? VP8LColorCacheContains(hashers, color) : -1; + if (ix >= 0) { + // use_color_cache is true and hashers contains color + const float mul0 = 0.68f; + cost_val += GetCacheCost(cost_model, ix) * mul0; + } else { + const float mul1 = 0.82f; + if (use_color_cache) VP8LColorCacheInsert(hashers, color); + cost_val += GetLiteralCost(cost_model, color) * mul1; + } + if (cost[idx] > cost_val) { + cost[idx] = cost_val; + dist_array[idx] = 1; // only one is inserted. + } +} + +// ----------------------------------------------------------------------------- +// CostManager and interval handling + +// Empirical value to avoid high memory consumption but good for performance. +#define COST_CACHE_INTERVAL_SIZE_MAX 500 + +// To perform backward reference every pixel at index index_ is considered and +// the cost for the MAX_LENGTH following pixels computed. Those following pixels +// at index index_ + k (k from 0 to MAX_LENGTH) have a cost of: +// cost_ = distance cost at index + GetLengthCost(cost_model, k) +// and the minimum value is kept. GetLengthCost(cost_model, k) is cached in an +// array of size MAX_LENGTH. +// Instead of performing MAX_LENGTH comparisons per pixel, we keep track of the +// minimal values using intervals of constant cost. +// An interval is defined by the index_ of the pixel that generated it and +// is only useful in a range of indices from start_ to end_ (exclusive), i.e. +// it contains the minimum value for pixels between start_ and end_. +// Intervals are stored in a linked list and ordered by start_. When a new +// interval has a better value, old intervals are split or removed. There are +// therefore no overlapping intervals. +typedef struct CostInterval CostInterval; +struct CostInterval { + float cost_; + int start_; + int end_; + int index_; + CostInterval* previous_; + CostInterval* next_; +}; + +// The GetLengthCost(cost_model, k) are cached in a CostCacheInterval. +typedef struct { + float cost_; + int start_; + int end_; // Exclusive. +} CostCacheInterval; + +// This structure is in charge of managing intervals and costs. +// It caches the different CostCacheInterval, caches the different +// GetLengthCost(cost_model, k) in cost_cache_ and the CostInterval's (whose +// count_ is limited by COST_CACHE_INTERVAL_SIZE_MAX). +#define COST_MANAGER_MAX_FREE_LIST 10 +typedef struct { + CostInterval* head_; + int count_; // The number of stored intervals. + CostCacheInterval* cache_intervals_; + size_t cache_intervals_size_; + float cost_cache_[MAX_LENGTH]; // Contains the GetLengthCost(cost_model, k). + float* costs_; + uint16_t* dist_array_; + // Most of the time, we only need few intervals -> use a free-list, to avoid + // fragmentation with small allocs in most common cases. + CostInterval intervals_[COST_MANAGER_MAX_FREE_LIST]; + CostInterval* free_intervals_; + // These are regularly malloc'd remains. This list can't grow larger than than + // size COST_CACHE_INTERVAL_SIZE_MAX - COST_MANAGER_MAX_FREE_LIST, note. + CostInterval* recycled_intervals_; +} CostManager; + +static void CostIntervalAddToFreeList(CostManager* const manager, + CostInterval* const interval) { + interval->next_ = manager->free_intervals_; + manager->free_intervals_ = interval; +} + +static int CostIntervalIsInFreeList(const CostManager* const manager, + const CostInterval* const interval) { + return (interval >= &manager->intervals_[0] && + interval <= &manager->intervals_[COST_MANAGER_MAX_FREE_LIST - 1]); +} + +static void CostManagerInitFreeList(CostManager* const manager) { + int i; + manager->free_intervals_ = NULL; + for (i = 0; i < COST_MANAGER_MAX_FREE_LIST; ++i) { + CostIntervalAddToFreeList(manager, &manager->intervals_[i]); + } +} + +static void DeleteIntervalList(CostManager* const manager, + const CostInterval* interval) { + while (interval != NULL) { + const CostInterval* const next = interval->next_; + if (!CostIntervalIsInFreeList(manager, interval)) { + WebPSafeFree((void*)interval); + } // else: do nothing + interval = next; + } +} + +static void CostManagerClear(CostManager* const manager) { + if (manager == NULL) return; + + WebPSafeFree(manager->costs_); + WebPSafeFree(manager->cache_intervals_); + + // Clear the interval lists. + DeleteIntervalList(manager, manager->head_); + manager->head_ = NULL; + DeleteIntervalList(manager, manager->recycled_intervals_); + manager->recycled_intervals_ = NULL; + + // Reset pointers, count_ and cache_intervals_size_. + memset(manager, 0, sizeof(*manager)); + CostManagerInitFreeList(manager); +} + +static int CostManagerInit(CostManager* const manager, + uint16_t* const dist_array, int pix_count, + const CostModel* const cost_model) { + int i; + const int cost_cache_size = (pix_count > MAX_LENGTH) ? MAX_LENGTH : pix_count; + + manager->costs_ = NULL; + manager->cache_intervals_ = NULL; + manager->head_ = NULL; + manager->recycled_intervals_ = NULL; + manager->count_ = 0; + manager->dist_array_ = dist_array; + CostManagerInitFreeList(manager); + + // Fill in the cost_cache_. + // Has to be done in two passes due to a GCC bug on i686 + // related to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=323 + for (i = 0; i < cost_cache_size; ++i) { + manager->cost_cache_[i] = GetLengthCost(cost_model, i); + } + manager->cache_intervals_size_ = 1; + for (i = 1; i < cost_cache_size; ++i) { + // Get the number of bound intervals. + if (manager->cost_cache_[i] != manager->cost_cache_[i - 1]) { + ++manager->cache_intervals_size_; + } + } + + // With the current cost model, we usually have below 20 intervals. + // The worst case scenario with a cost model would be if every length has a + // different cost, hence MAX_LENGTH but that is impossible with the current + // implementation that spirals around a pixel. + assert(manager->cache_intervals_size_ <= MAX_LENGTH); + manager->cache_intervals_ = (CostCacheInterval*)WebPSafeMalloc( + manager->cache_intervals_size_, sizeof(*manager->cache_intervals_)); + if (manager->cache_intervals_ == NULL) { + CostManagerClear(manager); + return 0; + } + + // Fill in the cache_intervals_. + { + CostCacheInterval* cur = manager->cache_intervals_; + + // Consecutive values in cost_cache_ are compared and if a big enough + // difference is found, a new interval is created and bounded. + cur->start_ = 0; + cur->end_ = 1; + cur->cost_ = manager->cost_cache_[0]; + for (i = 1; i < cost_cache_size; ++i) { + const float cost_val = manager->cost_cache_[i]; + if (cost_val != cur->cost_) { + ++cur; + // Initialize an interval. + cur->start_ = i; + cur->cost_ = cost_val; + } + cur->end_ = i + 1; + } + assert((size_t)(cur - manager->cache_intervals_) + 1 == + manager->cache_intervals_size_); + } + + manager->costs_ = (float*)WebPSafeMalloc(pix_count, sizeof(*manager->costs_)); + if (manager->costs_ == NULL) { + CostManagerClear(manager); + return 0; + } + // Set the initial costs_ high for every pixel as we will keep the minimum. + for (i = 0; i < pix_count; ++i) manager->costs_[i] = FLT_MAX; + + return 1; +} + +// Given the cost and the position that define an interval, update the cost at +// pixel 'i' if it is smaller than the previously computed value. +static WEBP_INLINE void UpdateCost(CostManager* const manager, int i, + int position, float cost) { + const int k = i - position; + assert(k >= 0 && k < MAX_LENGTH); + + if (manager->costs_[i] > cost) { + manager->costs_[i] = cost; + manager->dist_array_[i] = k + 1; + } +} + +// Given the cost and the position that define an interval, update the cost for +// all the pixels between 'start' and 'end' excluded. +static WEBP_INLINE void UpdateCostPerInterval(CostManager* const manager, + int start, int end, int position, + float cost) { + int i; + for (i = start; i < end; ++i) UpdateCost(manager, i, position, cost); +} + +// Given two intervals, make 'prev' be the previous one of 'next' in 'manager'. +static WEBP_INLINE void ConnectIntervals(CostManager* const manager, + CostInterval* const prev, + CostInterval* const next) { + if (prev != NULL) { + prev->next_ = next; + } else { + manager->head_ = next; + } + + if (next != NULL) next->previous_ = prev; +} + +// Pop an interval in the manager. +static WEBP_INLINE void PopInterval(CostManager* const manager, + CostInterval* const interval) { + if (interval == NULL) return; + + ConnectIntervals(manager, interval->previous_, interval->next_); + if (CostIntervalIsInFreeList(manager, interval)) { + CostIntervalAddToFreeList(manager, interval); + } else { // recycle regularly malloc'd intervals too + interval->next_ = manager->recycled_intervals_; + manager->recycled_intervals_ = interval; + } + --manager->count_; + assert(manager->count_ >= 0); +} + +// Update the cost at index i by going over all the stored intervals that +// overlap with i. +// If 'do_clean_intervals' is set to something different than 0, intervals that +// end before 'i' will be popped. +static WEBP_INLINE void UpdateCostAtIndex(CostManager* const manager, int i, + int do_clean_intervals) { + CostInterval* current = manager->head_; + + while (current != NULL && current->start_ <= i) { + CostInterval* const next = current->next_; + if (current->end_ <= i) { + if (do_clean_intervals) { + // We have an outdated interval, remove it. + PopInterval(manager, current); + } + } else { + UpdateCost(manager, i, current->index_, current->cost_); + } + current = next; + } +} + +// Given a current orphan interval and its previous interval, before +// it was orphaned (which can be NULL), set it at the right place in the list +// of intervals using the start_ ordering and the previous interval as a hint. +static WEBP_INLINE void PositionOrphanInterval(CostManager* const manager, + CostInterval* const current, + CostInterval* previous) { + assert(current != NULL); + + if (previous == NULL) previous = manager->head_; + while (previous != NULL && current->start_ < previous->start_) { + previous = previous->previous_; + } + while (previous != NULL && previous->next_ != NULL && + previous->next_->start_ < current->start_) { + previous = previous->next_; + } + + if (previous != NULL) { + ConnectIntervals(manager, current, previous->next_); + } else { + ConnectIntervals(manager, current, manager->head_); + } + ConnectIntervals(manager, previous, current); +} + +// Insert an interval in the list contained in the manager by starting at +// interval_in as a hint. The intervals are sorted by start_ value. +static WEBP_INLINE void InsertInterval(CostManager* const manager, + CostInterval* const interval_in, + float cost, int position, int start, + int end) { + CostInterval* interval_new; + + if (start >= end) return; + if (manager->count_ >= COST_CACHE_INTERVAL_SIZE_MAX) { + // Serialize the interval if we cannot store it. + UpdateCostPerInterval(manager, start, end, position, cost); + return; + } + if (manager->free_intervals_ != NULL) { + interval_new = manager->free_intervals_; + manager->free_intervals_ = interval_new->next_; + } else if (manager->recycled_intervals_ != NULL) { + interval_new = manager->recycled_intervals_; + manager->recycled_intervals_ = interval_new->next_; + } else { // malloc for good + interval_new = (CostInterval*)WebPSafeMalloc(1, sizeof(*interval_new)); + if (interval_new == NULL) { + // Write down the interval if we cannot create it. + UpdateCostPerInterval(manager, start, end, position, cost); + return; + } + } + + interval_new->cost_ = cost; + interval_new->index_ = position; + interval_new->start_ = start; + interval_new->end_ = end; + PositionOrphanInterval(manager, interval_new, interval_in); + + ++manager->count_; +} + +// Given a new cost interval defined by its start at position, its length value +// and distance_cost, add its contributions to the previous intervals and costs. +// If handling the interval or one of its subintervals becomes to heavy, its +// contribution is added to the costs right away. +static WEBP_INLINE void PushInterval(CostManager* const manager, + float distance_cost, int position, + int len) { + size_t i; + CostInterval* interval = manager->head_; + CostInterval* interval_next; + const CostCacheInterval* const cost_cache_intervals = + manager->cache_intervals_; + // If the interval is small enough, no need to deal with the heavy + // interval logic, just serialize it right away. This constant is empirical. + const int kSkipDistance = 10; + + if (len < kSkipDistance) { + int j; + for (j = position; j < position + len; ++j) { + const int k = j - position; + float cost_tmp; + assert(k >= 0 && k < MAX_LENGTH); + cost_tmp = distance_cost + manager->cost_cache_[k]; + + if (manager->costs_[j] > cost_tmp) { + manager->costs_[j] = cost_tmp; + manager->dist_array_[j] = k + 1; + } + } + return; + } + + for (i = 0; i < manager->cache_intervals_size_ && + cost_cache_intervals[i].start_ < len; + ++i) { + // Define the intersection of the ith interval with the new one. + int start = position + cost_cache_intervals[i].start_; + const int end = position + (cost_cache_intervals[i].end_ > len + ? len + : cost_cache_intervals[i].end_); + const float cost = distance_cost + cost_cache_intervals[i].cost_; + + for (; interval != NULL && interval->start_ < end; + interval = interval_next) { + interval_next = interval->next_; + + // Make sure we have some overlap + if (start >= interval->end_) continue; + + if (cost >= interval->cost_) { + // When intervals are represented, the lower, the better. + // [**********************************************************[ + // start end + // [----------------------------------[ + // interval->start_ interval->end_ + // If we are worse than what we already have, add whatever we have so + // far up to interval. + const int start_new = interval->end_; + InsertInterval(manager, interval, cost, position, start, + interval->start_); + start = start_new; + if (start >= end) break; + continue; + } + + if (start <= interval->start_) { + if (interval->end_ <= end) { + // [----------------------------------[ + // interval->start_ interval->end_ + // [**************************************************************[ + // start end + // We can safely remove the old interval as it is fully included. + PopInterval(manager, interval); + } else { + // [------------------------------------[ + // interval->start_ interval->end_ + // [*****************************[ + // start end + interval->start_ = end; + break; + } + } else { + if (end < interval->end_) { + // [--------------------------------------------------------------[ + // interval->start_ interval->end_ + // [*****************************[ + // start end + // We have to split the old interval as it fully contains the new one. + const int end_original = interval->end_; + interval->end_ = start; + InsertInterval(manager, interval, interval->cost_, interval->index_, + end, end_original); + interval = interval->next_; + break; + } else { + // [------------------------------------[ + // interval->start_ interval->end_ + // [*****************************[ + // start end + interval->end_ = start; + } + } + } + // Insert the remaining interval from start to end. + InsertInterval(manager, interval, cost, position, start, end); + } +} + +static int BackwardReferencesHashChainDistanceOnly( + int xsize, int ysize, const uint32_t* const argb, int cache_bits, + const VP8LHashChain* const hash_chain, const VP8LBackwardRefs* const refs, + uint16_t* const dist_array) { + int i; + int ok = 0; + int cc_init = 0; + const int pix_count = xsize * ysize; + const int use_color_cache = (cache_bits > 0); + const size_t literal_array_size = + sizeof(float) * (VP8LHistogramNumCodes(cache_bits)); + const size_t cost_model_size = sizeof(CostModel) + literal_array_size; + CostModel* const cost_model = + (CostModel*)WebPSafeCalloc(1ULL, cost_model_size); + VP8LColorCache hashers; + CostManager* cost_manager = + (CostManager*)WebPSafeCalloc(1ULL, sizeof(*cost_manager)); + int offset_prev = -1, len_prev = -1; + float offset_cost = -1.f; + int first_offset_is_constant = -1; // initialized with 'impossible' value + int reach = 0; + + if (cost_model == NULL || cost_manager == NULL) goto Error; + + cost_model->literal_ = (float*)(cost_model + 1); + if (use_color_cache) { + cc_init = VP8LColorCacheInit(&hashers, cache_bits); + if (!cc_init) goto Error; + } + + if (!CostModelBuild(cost_model, xsize, cache_bits, refs)) { + goto Error; + } + + if (!CostManagerInit(cost_manager, dist_array, pix_count, cost_model)) { + goto Error; + } + + // We loop one pixel at a time, but store all currently best points to + // non-processed locations from this point. + dist_array[0] = 0; + // Add first pixel as literal. + AddSingleLiteralWithCostModel(argb, &hashers, cost_model, 0, use_color_cache, + 0.f, cost_manager->costs_, dist_array); + + for (i = 1; i < pix_count; ++i) { + const float prev_cost = cost_manager->costs_[i - 1]; + int offset, len; + VP8LHashChainFindCopy(hash_chain, i, &offset, &len); + + // Try adding the pixel as a literal. + AddSingleLiteralWithCostModel(argb, &hashers, cost_model, i, + use_color_cache, prev_cost, + cost_manager->costs_, dist_array); + + // If we are dealing with a non-literal. + if (len >= 2) { + if (offset != offset_prev) { + const int code = VP8LDistanceToPlaneCode(xsize, offset); + offset_cost = GetDistanceCost(cost_model, code); + first_offset_is_constant = 1; + PushInterval(cost_manager, prev_cost + offset_cost, i, len); + } else { + assert(offset_cost >= 0); + assert(len_prev >= 0); + assert(first_offset_is_constant == 0 || first_offset_is_constant == 1); + // Instead of considering all contributions from a pixel i by calling: + // PushInterval(cost_manager, prev_cost + offset_cost, i, len); + // we optimize these contributions in case offset_cost stays the same + // for consecutive pixels. This describes a set of pixels similar to a + // previous set (e.g. constant color regions). + if (first_offset_is_constant) { + reach = i - 1 + len_prev - 1; + first_offset_is_constant = 0; + } + + if (i + len - 1 > reach) { + // We can only be go further with the same offset if the previous + // length was maxed, hence len_prev == len == MAX_LENGTH. + // TODO(vrabaud), bump i to the end right away (insert cache and + // update cost). + // TODO(vrabaud), check if one of the points in between does not have + // a lower cost. + // Already consider the pixel at "reach" to add intervals that are + // better than whatever we add. + int offset_j, len_j = 0; + int j; + assert(len == MAX_LENGTH || len == pix_count - i); + // Figure out the last consecutive pixel within [i, reach + 1] with + // the same offset. + for (j = i; j <= reach; ++j) { + VP8LHashChainFindCopy(hash_chain, j + 1, &offset_j, &len_j); + if (offset_j != offset) { + VP8LHashChainFindCopy(hash_chain, j, &offset_j, &len_j); + break; + } + } + // Update the cost at j - 1 and j. + UpdateCostAtIndex(cost_manager, j - 1, 0); + UpdateCostAtIndex(cost_manager, j, 0); + + PushInterval(cost_manager, cost_manager->costs_[j - 1] + offset_cost, + j, len_j); + reach = j + len_j - 1; + } + } + } + + UpdateCostAtIndex(cost_manager, i, 1); + offset_prev = offset; + len_prev = len; + } + + ok = !refs->error_; + Error: + if (cc_init) VP8LColorCacheClear(&hashers); + CostManagerClear(cost_manager); + WebPSafeFree(cost_model); + WebPSafeFree(cost_manager); + return ok; +} + +// We pack the path at the end of *dist_array and return +// a pointer to this part of the array. Example: +// dist_array = [1x2xx3x2] => packed [1x2x1232], chosen_path = [1232] +static void TraceBackwards(uint16_t* const dist_array, + int dist_array_size, + uint16_t** const chosen_path, + int* const chosen_path_size) { + uint16_t* path = dist_array + dist_array_size; + uint16_t* cur = dist_array + dist_array_size - 1; + while (cur >= dist_array) { + const int k = *cur; + --path; + *path = k; + cur -= k; + } + *chosen_path = path; + *chosen_path_size = (int)(dist_array + dist_array_size - path); +} + +static int BackwardReferencesHashChainFollowChosenPath( + const uint32_t* const argb, int cache_bits, + const uint16_t* const chosen_path, int chosen_path_size, + const VP8LHashChain* const hash_chain, VP8LBackwardRefs* const refs) { + const int use_color_cache = (cache_bits > 0); + int ix; + int i = 0; + int ok = 0; + int cc_init = 0; + VP8LColorCache hashers; + + if (use_color_cache) { + cc_init = VP8LColorCacheInit(&hashers, cache_bits); + if (!cc_init) goto Error; + } + + VP8LClearBackwardRefs(refs); + for (ix = 0; ix < chosen_path_size; ++ix) { + const int len = chosen_path[ix]; + if (len != 1) { + int k; + const int offset = VP8LHashChainFindOffset(hash_chain, i); + VP8LBackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(offset, len)); + if (use_color_cache) { + for (k = 0; k < len; ++k) { + VP8LColorCacheInsert(&hashers, argb[i + k]); + } + } + i += len; + } else { + PixOrCopy v; + const int idx = + use_color_cache ? VP8LColorCacheContains(&hashers, argb[i]) : -1; + if (idx >= 0) { + // use_color_cache is true and hashers contains argb[i] + // push pixel as a color cache index + v = PixOrCopyCreateCacheIdx(idx); + } else { + if (use_color_cache) VP8LColorCacheInsert(&hashers, argb[i]); + v = PixOrCopyCreateLiteral(argb[i]); + } + VP8LBackwardRefsCursorAdd(refs, v); + ++i; + } + } + ok = !refs->error_; + Error: + if (cc_init) VP8LColorCacheClear(&hashers); + return ok; +} + +// Returns 1 on success. +extern int VP8LBackwardReferencesTraceBackwards( + int xsize, int ysize, const uint32_t* const argb, int cache_bits, + const VP8LHashChain* const hash_chain, + const VP8LBackwardRefs* const refs_src, VP8LBackwardRefs* const refs_dst); +int VP8LBackwardReferencesTraceBackwards(int xsize, int ysize, + const uint32_t* const argb, + int cache_bits, + const VP8LHashChain* const hash_chain, + const VP8LBackwardRefs* const refs_src, + VP8LBackwardRefs* const refs_dst) { + int ok = 0; + const int dist_array_size = xsize * ysize; + uint16_t* chosen_path = NULL; + int chosen_path_size = 0; + uint16_t* dist_array = + (uint16_t*)WebPSafeMalloc(dist_array_size, sizeof(*dist_array)); + + if (dist_array == NULL) goto Error; + + if (!BackwardReferencesHashChainDistanceOnly( + xsize, ysize, argb, cache_bits, hash_chain, refs_src, dist_array)) { + goto Error; + } + TraceBackwards(dist_array, dist_array_size, &chosen_path, &chosen_path_size); + if (!BackwardReferencesHashChainFollowChosenPath( + argb, cache_bits, chosen_path, chosen_path_size, hash_chain, + refs_dst)) { + goto Error; + } + ok = 1; + Error: + WebPSafeFree(dist_array); + return ok; +} diff --git a/third-party/webp/libwebp/src/enc/backward_references_enc.c b/third-party/webp/libwebp/src/enc/backward_references_enc.c new file mode 100644 index 0000000000..dc98bf1719 --- /dev/null +++ b/third-party/webp/libwebp/src/enc/backward_references_enc.c @@ -0,0 +1,1065 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Jyrki Alakuijala (jyrki@google.com) +// + +#include "src/enc/backward_references_enc.h" + +#include +#include +#include + +#include "src/dsp/dsp.h" +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" +#include "src/enc/histogram_enc.h" +#include "src/enc/vp8i_enc.h" +#include "src/utils/color_cache_utils.h" +#include "src/utils/utils.h" +#include "src/webp/encode.h" + +#define MIN_BLOCK_SIZE 256 // minimum block size for backward references + +#define MAX_ENTROPY (1e30f) + +// 1M window (4M bytes) minus 120 special codes for short distances. +#define WINDOW_SIZE ((1 << WINDOW_SIZE_BITS) - 120) + +// Minimum number of pixels for which it is cheaper to encode a +// distance + length instead of each pixel as a literal. +#define MIN_LENGTH 4 + +// ----------------------------------------------------------------------------- + +static const uint8_t plane_to_code_lut[128] = { + 96, 73, 55, 39, 23, 13, 5, 1, 255, 255, 255, 255, 255, 255, 255, 255, + 101, 78, 58, 42, 26, 16, 8, 2, 0, 3, 9, 17, 27, 43, 59, 79, + 102, 86, 62, 46, 32, 20, 10, 6, 4, 7, 11, 21, 33, 47, 63, 87, + 105, 90, 70, 52, 37, 28, 18, 14, 12, 15, 19, 29, 38, 53, 71, 91, + 110, 99, 82, 66, 48, 35, 30, 24, 22, 25, 31, 36, 49, 67, 83, 100, + 115, 108, 94, 76, 64, 50, 44, 40, 34, 41, 45, 51, 65, 77, 95, 109, + 118, 113, 103, 92, 80, 68, 60, 56, 54, 57, 61, 69, 81, 93, 104, 114, + 119, 116, 111, 106, 97, 88, 84, 74, 72, 75, 85, 89, 98, 107, 112, 117 +}; + +extern int VP8LDistanceToPlaneCode(int xsize, int dist); +int VP8LDistanceToPlaneCode(int xsize, int dist) { + const int yoffset = dist / xsize; + const int xoffset = dist - yoffset * xsize; + if (xoffset <= 8 && yoffset < 8) { + return plane_to_code_lut[yoffset * 16 + 8 - xoffset] + 1; + } else if (xoffset > xsize - 8 && yoffset < 7) { + return plane_to_code_lut[(yoffset + 1) * 16 + 8 + (xsize - xoffset)] + 1; + } + return dist + 120; +} + +// Returns the exact index where array1 and array2 are different. For an index +// inferior or equal to best_len_match, the return value just has to be strictly +// inferior to best_len_match. The current behavior is to return 0 if this index +// is best_len_match, and the index itself otherwise. +// If no two elements are the same, it returns max_limit. +static WEBP_INLINE int FindMatchLength(const uint32_t* const array1, + const uint32_t* const array2, + int best_len_match, int max_limit) { + // Before 'expensive' linear match, check if the two arrays match at the + // current best length index. + if (array1[best_len_match] != array2[best_len_match]) return 0; + + return VP8LVectorMismatch(array1, array2, max_limit); +} + +// ----------------------------------------------------------------------------- +// VP8LBackwardRefs + +struct PixOrCopyBlock { + PixOrCopyBlock* next_; // next block (or NULL) + PixOrCopy* start_; // data start + int size_; // currently used size +}; + +extern void VP8LClearBackwardRefs(VP8LBackwardRefs* const refs); +void VP8LClearBackwardRefs(VP8LBackwardRefs* const refs) { + assert(refs != NULL); + if (refs->tail_ != NULL) { + *refs->tail_ = refs->free_blocks_; // recycle all blocks at once + } + refs->free_blocks_ = refs->refs_; + refs->tail_ = &refs->refs_; + refs->last_block_ = NULL; + refs->refs_ = NULL; +} + +void VP8LBackwardRefsClear(VP8LBackwardRefs* const refs) { + assert(refs != NULL); + VP8LClearBackwardRefs(refs); + while (refs->free_blocks_ != NULL) { + PixOrCopyBlock* const next = refs->free_blocks_->next_; + WebPSafeFree(refs->free_blocks_); + refs->free_blocks_ = next; + } +} + +// Swaps the content of two VP8LBackwardRefs. +static void BackwardRefsSwap(VP8LBackwardRefs* const refs1, + VP8LBackwardRefs* const refs2) { + const int point_to_refs1 = + (refs1->tail_ != NULL && refs1->tail_ == &refs1->refs_); + const int point_to_refs2 = + (refs2->tail_ != NULL && refs2->tail_ == &refs2->refs_); + const VP8LBackwardRefs tmp = *refs1; + *refs1 = *refs2; + *refs2 = tmp; + if (point_to_refs2) refs1->tail_ = &refs1->refs_; + if (point_to_refs1) refs2->tail_ = &refs2->refs_; +} + +void VP8LBackwardRefsInit(VP8LBackwardRefs* const refs, int block_size) { + assert(refs != NULL); + memset(refs, 0, sizeof(*refs)); + refs->tail_ = &refs->refs_; + refs->block_size_ = + (block_size < MIN_BLOCK_SIZE) ? MIN_BLOCK_SIZE : block_size; +} + +VP8LRefsCursor VP8LRefsCursorInit(const VP8LBackwardRefs* const refs) { + VP8LRefsCursor c; + c.cur_block_ = refs->refs_; + if (refs->refs_ != NULL) { + c.cur_pos = c.cur_block_->start_; + c.last_pos_ = c.cur_pos + c.cur_block_->size_; + } else { + c.cur_pos = NULL; + c.last_pos_ = NULL; + } + return c; +} + +void VP8LRefsCursorNextBlock(VP8LRefsCursor* const c) { + PixOrCopyBlock* const b = c->cur_block_->next_; + c->cur_pos = (b == NULL) ? NULL : b->start_; + c->last_pos_ = (b == NULL) ? NULL : b->start_ + b->size_; + c->cur_block_ = b; +} + +// Create a new block, either from the free list or allocated +static PixOrCopyBlock* BackwardRefsNewBlock(VP8LBackwardRefs* const refs) { + PixOrCopyBlock* b = refs->free_blocks_; + if (b == NULL) { // allocate new memory chunk + const size_t total_size = + sizeof(*b) + refs->block_size_ * sizeof(*b->start_); + b = (PixOrCopyBlock*)WebPSafeMalloc(1ULL, total_size); + if (b == NULL) { + refs->error_ |= 1; + return NULL; + } + b->start_ = (PixOrCopy*)((uint8_t*)b + sizeof(*b)); // not always aligned + } else { // recycle from free-list + refs->free_blocks_ = b->next_; + } + *refs->tail_ = b; + refs->tail_ = &b->next_; + refs->last_block_ = b; + b->next_ = NULL; + b->size_ = 0; + return b; +} + +// Return 1 on success, 0 on error. +static int BackwardRefsClone(const VP8LBackwardRefs* const from, + VP8LBackwardRefs* const to) { + const PixOrCopyBlock* block_from = from->refs_; + VP8LClearBackwardRefs(to); + while (block_from != NULL) { + PixOrCopyBlock* const block_to = BackwardRefsNewBlock(to); + if (block_to == NULL) return 0; + memcpy(block_to->start_, block_from->start_, + block_from->size_ * sizeof(PixOrCopy)); + block_to->size_ = block_from->size_; + block_from = block_from->next_; + } + return 1; +} + +extern void VP8LBackwardRefsCursorAdd(VP8LBackwardRefs* const refs, + const PixOrCopy v); +void VP8LBackwardRefsCursorAdd(VP8LBackwardRefs* const refs, + const PixOrCopy v) { + PixOrCopyBlock* b = refs->last_block_; + if (b == NULL || b->size_ == refs->block_size_) { + b = BackwardRefsNewBlock(refs); + if (b == NULL) return; // refs->error_ is set + } + b->start_[b->size_++] = v; +} + +// ----------------------------------------------------------------------------- +// Hash chains + +int VP8LHashChainInit(VP8LHashChain* const p, int size) { + assert(p->size_ == 0); + assert(p->offset_length_ == NULL); + assert(size > 0); + p->offset_length_ = + (uint32_t*)WebPSafeMalloc(size, sizeof(*p->offset_length_)); + if (p->offset_length_ == NULL) return 0; + p->size_ = size; + + return 1; +} + +void VP8LHashChainClear(VP8LHashChain* const p) { + assert(p != NULL); + WebPSafeFree(p->offset_length_); + + p->size_ = 0; + p->offset_length_ = NULL; +} + +// ----------------------------------------------------------------------------- + +static const uint32_t kHashMultiplierHi = 0xc6a4a793u; +static const uint32_t kHashMultiplierLo = 0x5bd1e996u; + +static WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW WEBP_INLINE +uint32_t GetPixPairHash64(const uint32_t* const argb) { + uint32_t key; + key = argb[1] * kHashMultiplierHi; + key += argb[0] * kHashMultiplierLo; + key = key >> (32 - HASH_BITS); + return key; +} + +// Returns the maximum number of hash chain lookups to do for a +// given compression quality. Return value in range [8, 86]. +static int GetMaxItersForQuality(int quality) { + return 8 + (quality * quality) / 128; +} + +static int GetWindowSizeForHashChain(int quality, int xsize) { + const int max_window_size = (quality > 75) ? WINDOW_SIZE + : (quality > 50) ? (xsize << 8) + : (quality > 25) ? (xsize << 6) + : (xsize << 4); + assert(xsize > 0); + return (max_window_size > WINDOW_SIZE) ? WINDOW_SIZE : max_window_size; +} + +static WEBP_INLINE int MaxFindCopyLength(int len) { + return (len < MAX_LENGTH) ? len : MAX_LENGTH; +} + +int VP8LHashChainFill(VP8LHashChain* const p, int quality, + const uint32_t* const argb, int xsize, int ysize, + int low_effort, const WebPPicture* const pic, + int percent_range, int* const percent) { + const int size = xsize * ysize; + const int iter_max = GetMaxItersForQuality(quality); + const uint32_t window_size = GetWindowSizeForHashChain(quality, xsize); + int remaining_percent = percent_range; + int percent_start = *percent; + int pos; + int argb_comp; + uint32_t base_position; + int32_t* hash_to_first_index; + // Temporarily use the p->offset_length_ as a hash chain. + int32_t* chain = (int32_t*)p->offset_length_; + assert(size > 0); + assert(p->size_ != 0); + assert(p->offset_length_ != NULL); + + if (size <= 2) { + p->offset_length_[0] = p->offset_length_[size - 1] = 0; + return 1; + } + + hash_to_first_index = + (int32_t*)WebPSafeMalloc(HASH_SIZE, sizeof(*hash_to_first_index)); + if (hash_to_first_index == NULL) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + + percent_range = remaining_percent / 2; + remaining_percent -= percent_range; + + // Set the int32_t array to -1. + memset(hash_to_first_index, 0xff, HASH_SIZE * sizeof(*hash_to_first_index)); + // Fill the chain linking pixels with the same hash. + argb_comp = (argb[0] == argb[1]); + for (pos = 0; pos < size - 2;) { + uint32_t hash_code; + const int argb_comp_next = (argb[pos + 1] == argb[pos + 2]); + if (argb_comp && argb_comp_next) { + // Consecutive pixels with the same color will share the same hash. + // We therefore use a different hash: the color and its repetition + // length. + uint32_t tmp[2]; + uint32_t len = 1; + tmp[0] = argb[pos]; + // Figure out how far the pixels are the same. + // The last pixel has a different 64 bit hash, as its next pixel does + // not have the same color, so we just need to get to the last pixel equal + // to its follower. + while (pos + (int)len + 2 < size && argb[pos + len + 2] == argb[pos]) { + ++len; + } + if (len > MAX_LENGTH) { + // Skip the pixels that match for distance=1 and length>MAX_LENGTH + // because they are linked to their predecessor and we automatically + // check that in the main for loop below. Skipping means setting no + // predecessor in the chain, hence -1. + memset(chain + pos, 0xff, (len - MAX_LENGTH) * sizeof(*chain)); + pos += len - MAX_LENGTH; + len = MAX_LENGTH; + } + // Process the rest of the hash chain. + while (len) { + tmp[1] = len--; + hash_code = GetPixPairHash64(tmp); + chain[pos] = hash_to_first_index[hash_code]; + hash_to_first_index[hash_code] = pos++; + } + argb_comp = 0; + } else { + // Just move one pixel forward. + hash_code = GetPixPairHash64(argb + pos); + chain[pos] = hash_to_first_index[hash_code]; + hash_to_first_index[hash_code] = pos++; + argb_comp = argb_comp_next; + } + + if (!WebPReportProgress( + pic, percent_start + percent_range * pos / (size - 2), percent)) { + WebPSafeFree(hash_to_first_index); + return 0; + } + } + // Process the penultimate pixel. + chain[pos] = hash_to_first_index[GetPixPairHash64(argb + pos)]; + + WebPSafeFree(hash_to_first_index); + + percent_start += percent_range; + if (!WebPReportProgress(pic, percent_start, percent)) return 0; + percent_range = remaining_percent; + + // Find the best match interval at each pixel, defined by an offset to the + // pixel and a length. The right-most pixel cannot match anything to the right + // (hence a best length of 0) and the left-most pixel nothing to the left + // (hence an offset of 0). + assert(size > 2); + p->offset_length_[0] = p->offset_length_[size - 1] = 0; + for (base_position = size - 2; base_position > 0;) { + const int max_len = MaxFindCopyLength(size - 1 - base_position); + const uint32_t* const argb_start = argb + base_position; + int iter = iter_max; + int best_length = 0; + uint32_t best_distance = 0; + uint32_t best_argb; + const int min_pos = + (base_position > window_size) ? base_position - window_size : 0; + const int length_max = (max_len < 256) ? max_len : 256; + uint32_t max_base_position; + + pos = chain[base_position]; + if (!low_effort) { + int curr_length; + // Heuristic: use the comparison with the above line as an initialization. + if (base_position >= (uint32_t)xsize) { + curr_length = FindMatchLength(argb_start - xsize, argb_start, + best_length, max_len); + if (curr_length > best_length) { + best_length = curr_length; + best_distance = xsize; + } + --iter; + } + // Heuristic: compare to the previous pixel. + curr_length = + FindMatchLength(argb_start - 1, argb_start, best_length, max_len); + if (curr_length > best_length) { + best_length = curr_length; + best_distance = 1; + } + --iter; + // Skip the for loop if we already have the maximum. + if (best_length == MAX_LENGTH) pos = min_pos - 1; + } + best_argb = argb_start[best_length]; + + for (; pos >= min_pos && --iter; pos = chain[pos]) { + int curr_length; + assert(base_position > (uint32_t)pos); + + if (argb[pos + best_length] != best_argb) continue; + + curr_length = VP8LVectorMismatch(argb + pos, argb_start, max_len); + if (best_length < curr_length) { + best_length = curr_length; + best_distance = base_position - pos; + best_argb = argb_start[best_length]; + // Stop if we have reached a good enough length. + if (best_length >= length_max) break; + } + } + // We have the best match but in case the two intervals continue matching + // to the left, we have the best matches for the left-extended pixels. + max_base_position = base_position; + while (1) { + assert(best_length <= MAX_LENGTH); + assert(best_distance <= WINDOW_SIZE); + p->offset_length_[base_position] = + (best_distance << MAX_LENGTH_BITS) | (uint32_t)best_length; + --base_position; + // Stop if we don't have a match or if we are out of bounds. + if (best_distance == 0 || base_position == 0) break; + // Stop if we cannot extend the matching intervals to the left. + if (base_position < best_distance || + argb[base_position - best_distance] != argb[base_position]) { + break; + } + // Stop if we are matching at its limit because there could be a closer + // matching interval with the same maximum length. Then again, if the + // matching interval is as close as possible (best_distance == 1), we will + // never find anything better so let's continue. + if (best_length == MAX_LENGTH && best_distance != 1 && + base_position + MAX_LENGTH < max_base_position) { + break; + } + if (best_length < MAX_LENGTH) { + ++best_length; + max_base_position = base_position; + } + } + + if (!WebPReportProgress(pic, + percent_start + percent_range * + (size - 2 - base_position) / + (size - 2), + percent)) { + return 0; + } + } + + return WebPReportProgress(pic, percent_start + percent_range, percent); +} + +static WEBP_INLINE void AddSingleLiteral(uint32_t pixel, int use_color_cache, + VP8LColorCache* const hashers, + VP8LBackwardRefs* const refs) { + PixOrCopy v; + if (use_color_cache) { + const uint32_t key = VP8LColorCacheGetIndex(hashers, pixel); + if (VP8LColorCacheLookup(hashers, key) == pixel) { + v = PixOrCopyCreateCacheIdx(key); + } else { + v = PixOrCopyCreateLiteral(pixel); + VP8LColorCacheSet(hashers, key, pixel); + } + } else { + v = PixOrCopyCreateLiteral(pixel); + } + VP8LBackwardRefsCursorAdd(refs, v); +} + +static int BackwardReferencesRle(int xsize, int ysize, + const uint32_t* const argb, + int cache_bits, VP8LBackwardRefs* const refs) { + const int pix_count = xsize * ysize; + int i, k; + const int use_color_cache = (cache_bits > 0); + VP8LColorCache hashers; + + if (use_color_cache && !VP8LColorCacheInit(&hashers, cache_bits)) { + return 0; + } + VP8LClearBackwardRefs(refs); + // Add first pixel as literal. + AddSingleLiteral(argb[0], use_color_cache, &hashers, refs); + i = 1; + while (i < pix_count) { + const int max_len = MaxFindCopyLength(pix_count - i); + const int rle_len = FindMatchLength(argb + i, argb + i - 1, 0, max_len); + const int prev_row_len = (i < xsize) ? 0 : + FindMatchLength(argb + i, argb + i - xsize, 0, max_len); + if (rle_len >= prev_row_len && rle_len >= MIN_LENGTH) { + VP8LBackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(1, rle_len)); + // We don't need to update the color cache here since it is always the + // same pixel being copied, and that does not change the color cache + // state. + i += rle_len; + } else if (prev_row_len >= MIN_LENGTH) { + VP8LBackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(xsize, prev_row_len)); + if (use_color_cache) { + for (k = 0; k < prev_row_len; ++k) { + VP8LColorCacheInsert(&hashers, argb[i + k]); + } + } + i += prev_row_len; + } else { + AddSingleLiteral(argb[i], use_color_cache, &hashers, refs); + i++; + } + } + if (use_color_cache) VP8LColorCacheClear(&hashers); + return !refs->error_; +} + +static int BackwardReferencesLz77(int xsize, int ysize, + const uint32_t* const argb, int cache_bits, + const VP8LHashChain* const hash_chain, + VP8LBackwardRefs* const refs) { + int i; + int i_last_check = -1; + int ok = 0; + int cc_init = 0; + const int use_color_cache = (cache_bits > 0); + const int pix_count = xsize * ysize; + VP8LColorCache hashers; + + if (use_color_cache) { + cc_init = VP8LColorCacheInit(&hashers, cache_bits); + if (!cc_init) goto Error; + } + VP8LClearBackwardRefs(refs); + for (i = 0; i < pix_count;) { + // Alternative#1: Code the pixels starting at 'i' using backward reference. + int offset = 0; + int len = 0; + int j; + VP8LHashChainFindCopy(hash_chain, i, &offset, &len); + if (len >= MIN_LENGTH) { + const int len_ini = len; + int max_reach = 0; + const int j_max = + (i + len_ini >= pix_count) ? pix_count - 1 : i + len_ini; + // Only start from what we have not checked already. + i_last_check = (i > i_last_check) ? i : i_last_check; + // We know the best match for the current pixel but we try to find the + // best matches for the current pixel AND the next one combined. + // The naive method would use the intervals: + // [i,i+len) + [i+len, length of best match at i+len) + // while we check if we can use: + // [i,j) (where j<=i+len) + [j, length of best match at j) + for (j = i_last_check + 1; j <= j_max; ++j) { + const int len_j = VP8LHashChainFindLength(hash_chain, j); + const int reach = + j + (len_j >= MIN_LENGTH ? len_j : 1); // 1 for single literal. + if (reach > max_reach) { + len = j - i; + max_reach = reach; + if (max_reach >= pix_count) break; + } + } + } else { + len = 1; + } + // Go with literal or backward reference. + assert(len > 0); + if (len == 1) { + AddSingleLiteral(argb[i], use_color_cache, &hashers, refs); + } else { + VP8LBackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(offset, len)); + if (use_color_cache) { + for (j = i; j < i + len; ++j) VP8LColorCacheInsert(&hashers, argb[j]); + } + } + i += len; + } + + ok = !refs->error_; + Error: + if (cc_init) VP8LColorCacheClear(&hashers); + return ok; +} + +// Compute an LZ77 by forcing matches to happen within a given distance cost. +// We therefore limit the algorithm to the lowest 32 values in the PlaneCode +// definition. +#define WINDOW_OFFSETS_SIZE_MAX 32 +static int BackwardReferencesLz77Box(int xsize, int ysize, + const uint32_t* const argb, int cache_bits, + const VP8LHashChain* const hash_chain_best, + VP8LHashChain* hash_chain, + VP8LBackwardRefs* const refs) { + int i; + const int pix_count = xsize * ysize; + uint16_t* counts; + int window_offsets[WINDOW_OFFSETS_SIZE_MAX] = {0}; + int window_offsets_new[WINDOW_OFFSETS_SIZE_MAX] = {0}; + int window_offsets_size = 0; + int window_offsets_new_size = 0; + uint16_t* const counts_ini = + (uint16_t*)WebPSafeMalloc(xsize * ysize, sizeof(*counts_ini)); + int best_offset_prev = -1, best_length_prev = -1; + if (counts_ini == NULL) return 0; + + // counts[i] counts how many times a pixel is repeated starting at position i. + i = pix_count - 2; + counts = counts_ini + i; + counts[1] = 1; + for (; i >= 0; --i, --counts) { + if (argb[i] == argb[i + 1]) { + // Max out the counts to MAX_LENGTH. + counts[0] = counts[1] + (counts[1] != MAX_LENGTH); + } else { + counts[0] = 1; + } + } + + // Figure out the window offsets around a pixel. They are stored in a + // spiraling order around the pixel as defined by VP8LDistanceToPlaneCode. + { + int x, y; + for (y = 0; y <= 6; ++y) { + for (x = -6; x <= 6; ++x) { + const int offset = y * xsize + x; + int plane_code; + // Ignore offsets that bring us after the pixel. + if (offset <= 0) continue; + plane_code = VP8LDistanceToPlaneCode(xsize, offset) - 1; + if (plane_code >= WINDOW_OFFSETS_SIZE_MAX) continue; + window_offsets[plane_code] = offset; + } + } + // For narrow images, not all plane codes are reached, so remove those. + for (i = 0; i < WINDOW_OFFSETS_SIZE_MAX; ++i) { + if (window_offsets[i] == 0) continue; + window_offsets[window_offsets_size++] = window_offsets[i]; + } + // Given a pixel P, find the offsets that reach pixels unreachable from P-1 + // with any of the offsets in window_offsets[]. + for (i = 0; i < window_offsets_size; ++i) { + int j; + int is_reachable = 0; + for (j = 0; j < window_offsets_size && !is_reachable; ++j) { + is_reachable |= (window_offsets[i] == window_offsets[j] + 1); + } + if (!is_reachable) { + window_offsets_new[window_offsets_new_size] = window_offsets[i]; + ++window_offsets_new_size; + } + } + } + + hash_chain->offset_length_[0] = 0; + for (i = 1; i < pix_count; ++i) { + int ind; + int best_length = VP8LHashChainFindLength(hash_chain_best, i); + int best_offset; + int do_compute = 1; + + if (best_length >= MAX_LENGTH) { + // Do not recompute the best match if we already have a maximal one in the + // window. + best_offset = VP8LHashChainFindOffset(hash_chain_best, i); + for (ind = 0; ind < window_offsets_size; ++ind) { + if (best_offset == window_offsets[ind]) { + do_compute = 0; + break; + } + } + } + if (do_compute) { + // Figure out if we should use the offset/length from the previous pixel + // as an initial guess and therefore only inspect the offsets in + // window_offsets_new[]. + const int use_prev = + (best_length_prev > 1) && (best_length_prev < MAX_LENGTH); + const int num_ind = + use_prev ? window_offsets_new_size : window_offsets_size; + best_length = use_prev ? best_length_prev - 1 : 0; + best_offset = use_prev ? best_offset_prev : 0; + // Find the longest match in a window around the pixel. + for (ind = 0; ind < num_ind; ++ind) { + int curr_length = 0; + int j = i; + int j_offset = + use_prev ? i - window_offsets_new[ind] : i - window_offsets[ind]; + if (j_offset < 0 || argb[j_offset] != argb[i]) continue; + // The longest match is the sum of how many times each pixel is + // repeated. + do { + const int counts_j_offset = counts_ini[j_offset]; + const int counts_j = counts_ini[j]; + if (counts_j_offset != counts_j) { + curr_length += + (counts_j_offset < counts_j) ? counts_j_offset : counts_j; + break; + } + // The same color is repeated counts_pos times at j_offset and j. + curr_length += counts_j_offset; + j_offset += counts_j_offset; + j += counts_j_offset; + } while (curr_length <= MAX_LENGTH && j < pix_count && + argb[j_offset] == argb[j]); + if (best_length < curr_length) { + best_offset = + use_prev ? window_offsets_new[ind] : window_offsets[ind]; + if (curr_length >= MAX_LENGTH) { + best_length = MAX_LENGTH; + break; + } else { + best_length = curr_length; + } + } + } + } + + assert(i + best_length <= pix_count); + assert(best_length <= MAX_LENGTH); + if (best_length <= MIN_LENGTH) { + hash_chain->offset_length_[i] = 0; + best_offset_prev = 0; + best_length_prev = 0; + } else { + hash_chain->offset_length_[i] = + (best_offset << MAX_LENGTH_BITS) | (uint32_t)best_length; + best_offset_prev = best_offset; + best_length_prev = best_length; + } + } + hash_chain->offset_length_[0] = 0; + WebPSafeFree(counts_ini); + + return BackwardReferencesLz77(xsize, ysize, argb, cache_bits, hash_chain, + refs); +} + +// ----------------------------------------------------------------------------- + +static void BackwardReferences2DLocality(int xsize, + const VP8LBackwardRefs* const refs) { + VP8LRefsCursor c = VP8LRefsCursorInit(refs); + while (VP8LRefsCursorOk(&c)) { + if (PixOrCopyIsCopy(c.cur_pos)) { + const int dist = c.cur_pos->argb_or_distance; + const int transformed_dist = VP8LDistanceToPlaneCode(xsize, dist); + c.cur_pos->argb_or_distance = transformed_dist; + } + VP8LRefsCursorNext(&c); + } +} + +// Evaluate optimal cache bits for the local color cache. +// The input *best_cache_bits sets the maximum cache bits to use (passing 0 +// implies disabling the local color cache). The local color cache is also +// disabled for the lower (<= 25) quality. +// Returns 0 in case of memory error. +static int CalculateBestCacheSize(const uint32_t* argb, int quality, + const VP8LBackwardRefs* const refs, + int* const best_cache_bits) { + int i; + const int cache_bits_max = (quality <= 25) ? 0 : *best_cache_bits; + float entropy_min = MAX_ENTROPY; + int cc_init[MAX_COLOR_CACHE_BITS + 1] = { 0 }; + VP8LColorCache hashers[MAX_COLOR_CACHE_BITS + 1]; + VP8LRefsCursor c = VP8LRefsCursorInit(refs); + VP8LHistogram* histos[MAX_COLOR_CACHE_BITS + 1] = { NULL }; + int ok = 0; + + assert(cache_bits_max >= 0 && cache_bits_max <= MAX_COLOR_CACHE_BITS); + + if (cache_bits_max == 0) { + *best_cache_bits = 0; + // Local color cache is disabled. + return 1; + } + + // Allocate data. + for (i = 0; i <= cache_bits_max; ++i) { + histos[i] = VP8LAllocateHistogram(i); + if (histos[i] == NULL) goto Error; + VP8LHistogramInit(histos[i], i, /*init_arrays=*/ 1); + if (i == 0) continue; + cc_init[i] = VP8LColorCacheInit(&hashers[i], i); + if (!cc_init[i]) goto Error; + } + + // Find the cache_bits giving the lowest entropy. The search is done in a + // brute-force way as the function (entropy w.r.t cache_bits) can be + // anything in practice. + while (VP8LRefsCursorOk(&c)) { + const PixOrCopy* const v = c.cur_pos; + if (PixOrCopyIsLiteral(v)) { + const uint32_t pix = *argb++; + const uint32_t a = (pix >> 24) & 0xff; + const uint32_t r = (pix >> 16) & 0xff; + const uint32_t g = (pix >> 8) & 0xff; + const uint32_t b = (pix >> 0) & 0xff; + // The keys of the caches can be derived from the longest one. + int key = VP8LHashPix(pix, 32 - cache_bits_max); + // Do not use the color cache for cache_bits = 0. + ++histos[0]->blue_[b]; + ++histos[0]->literal_[g]; + ++histos[0]->red_[r]; + ++histos[0]->alpha_[a]; + // Deal with cache_bits > 0. + for (i = cache_bits_max; i >= 1; --i, key >>= 1) { + if (VP8LColorCacheLookup(&hashers[i], key) == pix) { + ++histos[i]->literal_[NUM_LITERAL_CODES + NUM_LENGTH_CODES + key]; + } else { + VP8LColorCacheSet(&hashers[i], key, pix); + ++histos[i]->blue_[b]; + ++histos[i]->literal_[g]; + ++histos[i]->red_[r]; + ++histos[i]->alpha_[a]; + } + } + } else { + int code, extra_bits, extra_bits_value; + // We should compute the contribution of the (distance,length) + // histograms but those are the same independently from the cache size. + // As those constant contributions are in the end added to the other + // histogram contributions, we can ignore them, except for the length + // prefix that is part of the literal_ histogram. + int len = PixOrCopyLength(v); + uint32_t argb_prev = *argb ^ 0xffffffffu; + VP8LPrefixEncode(len, &code, &extra_bits, &extra_bits_value); + for (i = 0; i <= cache_bits_max; ++i) { + ++histos[i]->literal_[NUM_LITERAL_CODES + code]; + } + // Update the color caches. + do { + if (*argb != argb_prev) { + // Efficiency: insert only if the color changes. + int key = VP8LHashPix(*argb, 32 - cache_bits_max); + for (i = cache_bits_max; i >= 1; --i, key >>= 1) { + hashers[i].colors_[key] = *argb; + } + argb_prev = *argb; + } + argb++; + } while (--len != 0); + } + VP8LRefsCursorNext(&c); + } + + for (i = 0; i <= cache_bits_max; ++i) { + const float entropy = VP8LHistogramEstimateBits(histos[i]); + if (i == 0 || entropy < entropy_min) { + entropy_min = entropy; + *best_cache_bits = i; + } + } + ok = 1; + Error: + for (i = 0; i <= cache_bits_max; ++i) { + if (cc_init[i]) VP8LColorCacheClear(&hashers[i]); + VP8LFreeHistogram(histos[i]); + } + return ok; +} + +// Update (in-place) backward references for specified cache_bits. +static int BackwardRefsWithLocalCache(const uint32_t* const argb, + int cache_bits, + VP8LBackwardRefs* const refs) { + int pixel_index = 0; + VP8LColorCache hashers; + VP8LRefsCursor c = VP8LRefsCursorInit(refs); + if (!VP8LColorCacheInit(&hashers, cache_bits)) return 0; + + while (VP8LRefsCursorOk(&c)) { + PixOrCopy* const v = c.cur_pos; + if (PixOrCopyIsLiteral(v)) { + const uint32_t argb_literal = v->argb_or_distance; + const int ix = VP8LColorCacheContains(&hashers, argb_literal); + if (ix >= 0) { + // hashers contains argb_literal + *v = PixOrCopyCreateCacheIdx(ix); + } else { + VP8LColorCacheInsert(&hashers, argb_literal); + } + ++pixel_index; + } else { + // refs was created without local cache, so it can not have cache indexes. + int k; + assert(PixOrCopyIsCopy(v)); + for (k = 0; k < v->len; ++k) { + VP8LColorCacheInsert(&hashers, argb[pixel_index++]); + } + } + VP8LRefsCursorNext(&c); + } + VP8LColorCacheClear(&hashers); + return 1; +} + +static VP8LBackwardRefs* GetBackwardReferencesLowEffort( + int width, int height, const uint32_t* const argb, + int* const cache_bits, const VP8LHashChain* const hash_chain, + VP8LBackwardRefs* const refs_lz77) { + *cache_bits = 0; + if (!BackwardReferencesLz77(width, height, argb, 0, hash_chain, refs_lz77)) { + return NULL; + } + BackwardReferences2DLocality(width, refs_lz77); + return refs_lz77; +} + +extern int VP8LBackwardReferencesTraceBackwards( + int xsize, int ysize, const uint32_t* const argb, int cache_bits, + const VP8LHashChain* const hash_chain, + const VP8LBackwardRefs* const refs_src, VP8LBackwardRefs* const refs_dst); +static int GetBackwardReferences(int width, int height, + const uint32_t* const argb, int quality, + int lz77_types_to_try, int cache_bits_max, + int do_no_cache, + const VP8LHashChain* const hash_chain, + VP8LBackwardRefs* const refs, + int* const cache_bits_best) { + VP8LHistogram* histo = NULL; + int i, lz77_type; + // Index 0 is for a color cache, index 1 for no cache (if needed). + int lz77_types_best[2] = {0, 0}; + float bit_costs_best[2] = {FLT_MAX, FLT_MAX}; + VP8LHashChain hash_chain_box; + VP8LBackwardRefs* const refs_tmp = &refs[do_no_cache ? 2 : 1]; + int status = 0; + memset(&hash_chain_box, 0, sizeof(hash_chain_box)); + + histo = VP8LAllocateHistogram(MAX_COLOR_CACHE_BITS); + if (histo == NULL) goto Error; + + for (lz77_type = 1; lz77_types_to_try; + lz77_types_to_try &= ~lz77_type, lz77_type <<= 1) { + int res = 0; + float bit_cost = 0.f; + if ((lz77_types_to_try & lz77_type) == 0) continue; + switch (lz77_type) { + case kLZ77RLE: + res = BackwardReferencesRle(width, height, argb, 0, refs_tmp); + break; + case kLZ77Standard: + // Compute LZ77 with no cache (0 bits), as the ideal LZ77 with a color + // cache is not that different in practice. + res = BackwardReferencesLz77(width, height, argb, 0, hash_chain, + refs_tmp); + break; + case kLZ77Box: + if (!VP8LHashChainInit(&hash_chain_box, width * height)) goto Error; + res = BackwardReferencesLz77Box(width, height, argb, 0, hash_chain, + &hash_chain_box, refs_tmp); + break; + default: + assert(0); + } + if (!res) goto Error; + + // Start with the no color cache case. + for (i = 1; i >= 0; --i) { + int cache_bits = (i == 1) ? 0 : cache_bits_max; + + if (i == 1 && !do_no_cache) continue; + + if (i == 0) { + // Try with a color cache. + if (!CalculateBestCacheSize(argb, quality, refs_tmp, &cache_bits)) { + goto Error; + } + if (cache_bits > 0) { + if (!BackwardRefsWithLocalCache(argb, cache_bits, refs_tmp)) { + goto Error; + } + } + } + + if (i == 0 && do_no_cache && cache_bits == 0) { + // No need to re-compute bit_cost as it was computed at i == 1. + } else { + VP8LHistogramCreate(histo, refs_tmp, cache_bits); + bit_cost = VP8LHistogramEstimateBits(histo); + } + + if (bit_cost < bit_costs_best[i]) { + if (i == 1) { + // Do not swap as the full cache analysis would have the wrong + // VP8LBackwardRefs to start with. + if (!BackwardRefsClone(refs_tmp, &refs[1])) goto Error; + } else { + BackwardRefsSwap(refs_tmp, &refs[0]); + } + bit_costs_best[i] = bit_cost; + lz77_types_best[i] = lz77_type; + if (i == 0) *cache_bits_best = cache_bits; + } + } + } + assert(lz77_types_best[0] > 0); + assert(!do_no_cache || lz77_types_best[1] > 0); + + // Improve on simple LZ77 but only for high quality (TraceBackwards is + // costly). + for (i = 1; i >= 0; --i) { + if (i == 1 && !do_no_cache) continue; + if ((lz77_types_best[i] == kLZ77Standard || + lz77_types_best[i] == kLZ77Box) && + quality >= 25) { + const VP8LHashChain* const hash_chain_tmp = + (lz77_types_best[i] == kLZ77Standard) ? hash_chain : &hash_chain_box; + const int cache_bits = (i == 1) ? 0 : *cache_bits_best; + float bit_cost_trace; + if (!VP8LBackwardReferencesTraceBackwards(width, height, argb, cache_bits, + hash_chain_tmp, &refs[i], + refs_tmp)) { + goto Error; + } + VP8LHistogramCreate(histo, refs_tmp, cache_bits); + bit_cost_trace = VP8LHistogramEstimateBits(histo); + if (bit_cost_trace < bit_costs_best[i]) { + BackwardRefsSwap(refs_tmp, &refs[i]); + } + } + + BackwardReferences2DLocality(width, &refs[i]); + + if (i == 1 && lz77_types_best[0] == lz77_types_best[1] && + *cache_bits_best == 0) { + // If the best cache size is 0 and we have the same best LZ77, just copy + // the data over and stop here. + if (!BackwardRefsClone(&refs[1], &refs[0])) goto Error; + break; + } + } + status = 1; + + Error: + VP8LHashChainClear(&hash_chain_box); + VP8LFreeHistogram(histo); + return status; +} + +int VP8LGetBackwardReferences( + int width, int height, const uint32_t* const argb, int quality, + int low_effort, int lz77_types_to_try, int cache_bits_max, int do_no_cache, + const VP8LHashChain* const hash_chain, VP8LBackwardRefs* const refs, + int* const cache_bits_best, const WebPPicture* const pic, int percent_range, + int* const percent) { + if (low_effort) { + VP8LBackwardRefs* refs_best; + *cache_bits_best = cache_bits_max; + refs_best = GetBackwardReferencesLowEffort( + width, height, argb, cache_bits_best, hash_chain, refs); + if (refs_best == NULL) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + // Set it in first position. + BackwardRefsSwap(refs_best, &refs[0]); + } else { + if (!GetBackwardReferences(width, height, argb, quality, lz77_types_to_try, + cache_bits_max, do_no_cache, hash_chain, refs, + cache_bits_best)) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + } + + return WebPReportProgress(pic, *percent + percent_range, percent); +} diff --git a/third-party/webp/libwebp/src/enc/backward_references_enc.h b/third-party/webp/libwebp/src/enc/backward_references_enc.h new file mode 100644 index 0000000000..4dff1c27b5 --- /dev/null +++ b/third-party/webp/libwebp/src/enc/backward_references_enc.h @@ -0,0 +1,244 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Jyrki Alakuijala (jyrki@google.com) +// + +#ifndef WEBP_ENC_BACKWARD_REFERENCES_ENC_H_ +#define WEBP_ENC_BACKWARD_REFERENCES_ENC_H_ + +#include +#include +#include "src/webp/types.h" +#include "src/webp/encode.h" +#include "src/webp/format_constants.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// The maximum allowed limit is 11. +#define MAX_COLOR_CACHE_BITS 10 + +// ----------------------------------------------------------------------------- +// PixOrCopy + +enum Mode { + kLiteral, + kCacheIdx, + kCopy, + kNone +}; + +typedef struct { + // mode as uint8_t to make the memory layout to be exactly 8 bytes. + uint8_t mode; + uint16_t len; + uint32_t argb_or_distance; +} PixOrCopy; + +static WEBP_INLINE PixOrCopy PixOrCopyCreateCopy(uint32_t distance, + uint16_t len) { + PixOrCopy retval; + retval.mode = kCopy; + retval.argb_or_distance = distance; + retval.len = len; + return retval; +} + +static WEBP_INLINE PixOrCopy PixOrCopyCreateCacheIdx(int idx) { + PixOrCopy retval; + assert(idx >= 0); + assert(idx < (1 << MAX_COLOR_CACHE_BITS)); + retval.mode = kCacheIdx; + retval.argb_or_distance = idx; + retval.len = 1; + return retval; +} + +static WEBP_INLINE PixOrCopy PixOrCopyCreateLiteral(uint32_t argb) { + PixOrCopy retval; + retval.mode = kLiteral; + retval.argb_or_distance = argb; + retval.len = 1; + return retval; +} + +static WEBP_INLINE int PixOrCopyIsLiteral(const PixOrCopy* const p) { + return (p->mode == kLiteral); +} + +static WEBP_INLINE int PixOrCopyIsCacheIdx(const PixOrCopy* const p) { + return (p->mode == kCacheIdx); +} + +static WEBP_INLINE int PixOrCopyIsCopy(const PixOrCopy* const p) { + return (p->mode == kCopy); +} + +static WEBP_INLINE uint32_t PixOrCopyLiteral(const PixOrCopy* const p, + int component) { + assert(p->mode == kLiteral); + return (p->argb_or_distance >> (component * 8)) & 0xff; +} + +static WEBP_INLINE uint32_t PixOrCopyLength(const PixOrCopy* const p) { + return p->len; +} + +static WEBP_INLINE uint32_t PixOrCopyCacheIdx(const PixOrCopy* const p) { + assert(p->mode == kCacheIdx); + assert(p->argb_or_distance < (1U << MAX_COLOR_CACHE_BITS)); + return p->argb_or_distance; +} + +static WEBP_INLINE uint32_t PixOrCopyDistance(const PixOrCopy* const p) { + assert(p->mode == kCopy); + return p->argb_or_distance; +} + +// ----------------------------------------------------------------------------- +// VP8LHashChain + +#define HASH_BITS 18 +#define HASH_SIZE (1 << HASH_BITS) + +// If you change this, you need MAX_LENGTH_BITS + WINDOW_SIZE_BITS <= 32 as it +// is used in VP8LHashChain. +#define MAX_LENGTH_BITS 12 +#define WINDOW_SIZE_BITS 20 +// We want the max value to be attainable and stored in MAX_LENGTH_BITS bits. +#define MAX_LENGTH ((1 << MAX_LENGTH_BITS) - 1) +#if MAX_LENGTH_BITS + WINDOW_SIZE_BITS > 32 +#error "MAX_LENGTH_BITS + WINDOW_SIZE_BITS > 32" +#endif + +typedef struct VP8LHashChain VP8LHashChain; +struct VP8LHashChain { + // The 20 most significant bits contain the offset at which the best match + // is found. These 20 bits are the limit defined by GetWindowSizeForHashChain + // (through WINDOW_SIZE = 1<<20). + // The lower 12 bits contain the length of the match. The 12 bit limit is + // defined in MaxFindCopyLength with MAX_LENGTH=4096. + uint32_t* offset_length_; + // This is the maximum size of the hash_chain that can be constructed. + // Typically this is the pixel count (width x height) for a given image. + int size_; +}; + +// Must be called first, to set size. +int VP8LHashChainInit(VP8LHashChain* const p, int size); +// Pre-compute the best matches for argb. pic and percent are for progress. +int VP8LHashChainFill(VP8LHashChain* const p, int quality, + const uint32_t* const argb, int xsize, int ysize, + int low_effort, const WebPPicture* const pic, + int percent_range, int* const percent); +void VP8LHashChainClear(VP8LHashChain* const p); // release memory + +static WEBP_INLINE int VP8LHashChainFindOffset(const VP8LHashChain* const p, + const int base_position) { + return p->offset_length_[base_position] >> MAX_LENGTH_BITS; +} + +static WEBP_INLINE int VP8LHashChainFindLength(const VP8LHashChain* const p, + const int base_position) { + return p->offset_length_[base_position] & ((1U << MAX_LENGTH_BITS) - 1); +} + +static WEBP_INLINE void VP8LHashChainFindCopy(const VP8LHashChain* const p, + int base_position, + int* const offset_ptr, + int* const length_ptr) { + *offset_ptr = VP8LHashChainFindOffset(p, base_position); + *length_ptr = VP8LHashChainFindLength(p, base_position); +} + +// ----------------------------------------------------------------------------- +// VP8LBackwardRefs (block-based backward-references storage) + +// maximum number of reference blocks the image will be segmented into +#define MAX_REFS_BLOCK_PER_IMAGE 16 + +typedef struct PixOrCopyBlock PixOrCopyBlock; // forward declaration +typedef struct VP8LBackwardRefs VP8LBackwardRefs; + +// Container for blocks chain +struct VP8LBackwardRefs { + int block_size_; // common block-size + int error_; // set to true if some memory error occurred + PixOrCopyBlock* refs_; // list of currently used blocks + PixOrCopyBlock** tail_; // for list recycling + PixOrCopyBlock* free_blocks_; // free-list + PixOrCopyBlock* last_block_; // used for adding new refs (internal) +}; + +// Initialize the object. 'block_size' is the common block size to store +// references (typically, width * height / MAX_REFS_BLOCK_PER_IMAGE). +void VP8LBackwardRefsInit(VP8LBackwardRefs* const refs, int block_size); +// Release memory for backward references. +void VP8LBackwardRefsClear(VP8LBackwardRefs* const refs); + +// Cursor for iterating on references content +typedef struct { + // public: + PixOrCopy* cur_pos; // current position + // private: + PixOrCopyBlock* cur_block_; // current block in the refs list + const PixOrCopy* last_pos_; // sentinel for switching to next block +} VP8LRefsCursor; + +// Returns a cursor positioned at the beginning of the references list. +VP8LRefsCursor VP8LRefsCursorInit(const VP8LBackwardRefs* const refs); +// Returns true if cursor is pointing at a valid position. +static WEBP_INLINE int VP8LRefsCursorOk(const VP8LRefsCursor* const c) { + return (c->cur_pos != NULL); +} +// Move to next block of references. Internal, not to be called directly. +void VP8LRefsCursorNextBlock(VP8LRefsCursor* const c); +// Move to next position, or NULL. Should not be called if !VP8LRefsCursorOk(). +static WEBP_INLINE void VP8LRefsCursorNext(VP8LRefsCursor* const c) { + assert(c != NULL); + assert(VP8LRefsCursorOk(c)); + if (++c->cur_pos == c->last_pos_) VP8LRefsCursorNextBlock(c); +} + +// ----------------------------------------------------------------------------- +// Main entry points + +enum VP8LLZ77Type { + kLZ77Standard = 1, + kLZ77RLE = 2, + kLZ77Box = 4 +}; + +// Evaluates best possible backward references for specified quality. +// The input cache_bits to 'VP8LGetBackwardReferences' sets the maximum cache +// bits to use (passing 0 implies disabling the local color cache). +// The optimal cache bits is evaluated and set for the *cache_bits_best +// parameter with the matching refs_best. +// If do_no_cache == 0, refs is an array of 2 values and the best +// VP8LBackwardRefs is put in the first element. +// If do_no_cache != 0, refs is an array of 3 values and the best +// VP8LBackwardRefs is put in the first element, the best value with no-cache in +// the second element. +// In both cases, the last element is used as temporary internally. +// pic and percent are for progress. +// Returns false in case of error (stored in pic->error_code). +int VP8LGetBackwardReferences( + int width, int height, const uint32_t* const argb, int quality, + int low_effort, int lz77_types_to_try, int cache_bits_max, int do_no_cache, + const VP8LHashChain* const hash_chain, VP8LBackwardRefs* const refs, + int* const cache_bits_best, const WebPPicture* const pic, int percent_range, + int* const percent); + +#ifdef __cplusplus +} +#endif + +#endif // WEBP_ENC_BACKWARD_REFERENCES_ENC_H_ diff --git a/third-party/webp/libwebp/src/enc/config_enc.c b/third-party/webp/libwebp/src/enc/config_enc.c new file mode 100644 index 0000000000..3518b41403 --- /dev/null +++ b/third-party/webp/libwebp/src/enc/config_enc.c @@ -0,0 +1,157 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Coding tools configuration +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifdef HAVE_CONFIG_H +#include "src/webp/config.h" +#endif + +#include "src/webp/encode.h" + +//------------------------------------------------------------------------------ +// WebPConfig +//------------------------------------------------------------------------------ + +int WebPConfigInitInternal(WebPConfig* config, + WebPPreset preset, float quality, int version) { + if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_ENCODER_ABI_VERSION)) { + return 0; // caller/system version mismatch! + } + if (config == NULL) return 0; + + config->quality = quality; + config->target_size = 0; + config->target_PSNR = 0.; + config->method = 4; + config->sns_strength = 50; + config->filter_strength = 60; // mid-filtering + config->filter_sharpness = 0; + config->filter_type = 1; // default: strong (so U/V is filtered too) + config->partitions = 0; + config->segments = 4; + config->pass = 1; + config->qmin = 0; + config->qmax = 100; + config->show_compressed = 0; + config->preprocessing = 0; + config->autofilter = 0; + config->partition_limit = 0; + config->alpha_compression = 1; + config->alpha_filtering = 1; + config->alpha_quality = 100; + config->lossless = 0; + config->exact = 0; + config->image_hint = WEBP_HINT_DEFAULT; + config->emulate_jpeg_size = 0; + config->thread_level = 0; + config->low_memory = 0; + config->near_lossless = 100; + config->use_delta_palette = 0; + config->use_sharp_yuv = 0; + + // TODO(skal): tune. + switch (preset) { + case WEBP_PRESET_PICTURE: + config->sns_strength = 80; + config->filter_sharpness = 4; + config->filter_strength = 35; + config->preprocessing &= ~2; // no dithering + break; + case WEBP_PRESET_PHOTO: + config->sns_strength = 80; + config->filter_sharpness = 3; + config->filter_strength = 30; + config->preprocessing |= 2; + break; + case WEBP_PRESET_DRAWING: + config->sns_strength = 25; + config->filter_sharpness = 6; + config->filter_strength = 10; + break; + case WEBP_PRESET_ICON: + config->sns_strength = 0; + config->filter_strength = 0; // disable filtering to retain sharpness + config->preprocessing &= ~2; // no dithering + break; + case WEBP_PRESET_TEXT: + config->sns_strength = 0; + config->filter_strength = 0; // disable filtering to retain sharpness + config->preprocessing &= ~2; // no dithering + config->segments = 2; + break; + case WEBP_PRESET_DEFAULT: + default: + break; + } + return WebPValidateConfig(config); +} + +int WebPValidateConfig(const WebPConfig* config) { + if (config == NULL) return 0; + if (config->quality < 0 || config->quality > 100) return 0; + if (config->target_size < 0) return 0; + if (config->target_PSNR < 0) return 0; + if (config->method < 0 || config->method > 6) return 0; + if (config->segments < 1 || config->segments > 4) return 0; + if (config->sns_strength < 0 || config->sns_strength > 100) return 0; + if (config->filter_strength < 0 || config->filter_strength > 100) return 0; + if (config->filter_sharpness < 0 || config->filter_sharpness > 7) return 0; + if (config->filter_type < 0 || config->filter_type > 1) return 0; + if (config->autofilter < 0 || config->autofilter > 1) return 0; + if (config->pass < 1 || config->pass > 10) return 0; + if (config->qmin < 0 || config->qmax > 100 || config->qmin > config->qmax) { + return 0; + } + if (config->show_compressed < 0 || config->show_compressed > 1) return 0; + if (config->preprocessing < 0 || config->preprocessing > 7) return 0; + if (config->partitions < 0 || config->partitions > 3) return 0; + if (config->partition_limit < 0 || config->partition_limit > 100) return 0; + if (config->alpha_compression < 0) return 0; + if (config->alpha_filtering < 0) return 0; + if (config->alpha_quality < 0 || config->alpha_quality > 100) return 0; + if (config->lossless < 0 || config->lossless > 1) return 0; + if (config->near_lossless < 0 || config->near_lossless > 100) return 0; + if (config->image_hint >= WEBP_HINT_LAST) return 0; + if (config->emulate_jpeg_size < 0 || config->emulate_jpeg_size > 1) return 0; + if (config->thread_level < 0 || config->thread_level > 1) return 0; + if (config->low_memory < 0 || config->low_memory > 1) return 0; + if (config->exact < 0 || config->exact > 1) return 0; + if (config->use_delta_palette < 0 || config->use_delta_palette > 1) { + return 0; + } + if (config->use_sharp_yuv < 0 || config->use_sharp_yuv > 1) return 0; + + return 1; +} + +//------------------------------------------------------------------------------ + +#define MAX_LEVEL 9 + +// Mapping between -z level and -m / -q parameter settings. +static const struct { + uint8_t method_; + uint8_t quality_; +} kLosslessPresets[MAX_LEVEL + 1] = { + { 0, 0 }, { 1, 20 }, { 2, 25 }, { 3, 30 }, { 3, 50 }, + { 4, 50 }, { 4, 75 }, { 4, 90 }, { 5, 90 }, { 6, 100 } +}; + +int WebPConfigLosslessPreset(WebPConfig* config, int level) { + if (config == NULL || level < 0 || level > MAX_LEVEL) return 0; + config->lossless = 1; + config->method = kLosslessPresets[level].method_; + config->quality = kLosslessPresets[level].quality_; + return 1; +} + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/src/enc/cost_enc.c b/third-party/webp/libwebp/src/enc/cost_enc.c new file mode 100644 index 0000000000..48fd9bc347 --- /dev/null +++ b/third-party/webp/libwebp/src/enc/cost_enc.c @@ -0,0 +1,342 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Cost tables for level and modes +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/enc/cost_enc.h" + +//------------------------------------------------------------------------------ +// Level cost tables + +// For each given level, the following table gives the pattern of contexts to +// use for coding it (in [][0]) as well as the bit value to use for each +// context (in [][1]). +const uint16_t VP8LevelCodes[MAX_VARIABLE_LEVEL][2] = { + {0x001, 0x000}, {0x007, 0x001}, {0x00f, 0x005}, + {0x00f, 0x00d}, {0x033, 0x003}, {0x033, 0x003}, {0x033, 0x023}, + {0x033, 0x023}, {0x033, 0x023}, {0x033, 0x023}, {0x0d3, 0x013}, + {0x0d3, 0x013}, {0x0d3, 0x013}, {0x0d3, 0x013}, {0x0d3, 0x013}, + {0x0d3, 0x013}, {0x0d3, 0x013}, {0x0d3, 0x013}, {0x0d3, 0x093}, + {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, + {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, + {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, + {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, {0x153, 0x053}, + {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, + {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, + {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, + {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, + {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, + {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, + {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, + {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x153} +}; + +static int VariableLevelCost(int level, const uint8_t probas[NUM_PROBAS]) { + int pattern = VP8LevelCodes[level - 1][0]; + int bits = VP8LevelCodes[level - 1][1]; + int cost = 0; + int i; + for (i = 2; pattern; ++i) { + if (pattern & 1) { + cost += VP8BitCost(bits & 1, probas[i]); + } + bits >>= 1; + pattern >>= 1; + } + return cost; +} + +//------------------------------------------------------------------------------ +// Pre-calc level costs once for all + +void VP8CalculateLevelCosts(VP8EncProba* const proba) { + int ctype, band, ctx; + + if (!proba->dirty_) return; // nothing to do. + + for (ctype = 0; ctype < NUM_TYPES; ++ctype) { + int n; + for (band = 0; band < NUM_BANDS; ++band) { + for (ctx = 0; ctx < NUM_CTX; ++ctx) { + const uint8_t* const p = proba->coeffs_[ctype][band][ctx]; + uint16_t* const table = proba->level_cost_[ctype][band][ctx]; + const int cost0 = (ctx > 0) ? VP8BitCost(1, p[0]) : 0; + const int cost_base = VP8BitCost(1, p[1]) + cost0; + int v; + table[0] = VP8BitCost(0, p[1]) + cost0; + for (v = 1; v <= MAX_VARIABLE_LEVEL; ++v) { + table[v] = cost_base + VariableLevelCost(v, p); + } + // Starting at level 67 and up, the variable part of the cost is + // actually constant. + } + } + for (n = 0; n < 16; ++n) { // replicate bands. We don't need to sentinel. + for (ctx = 0; ctx < NUM_CTX; ++ctx) { + proba->remapped_costs_[ctype][n][ctx] = + proba->level_cost_[ctype][VP8EncBands[n]][ctx]; + } + } + } + proba->dirty_ = 0; +} + +//------------------------------------------------------------------------------ +// Mode cost tables. + +// These are the fixed probabilities (in the coding trees) turned into bit-cost +// by calling VP8BitCost(). +const uint16_t VP8FixedCostsUV[4] = { 302, 984, 439, 642 }; +// note: these values include the fixed VP8BitCost(1, 145) mode selection cost. +const uint16_t VP8FixedCostsI16[4] = { 663, 919, 872, 919 }; +const uint16_t VP8FixedCostsI4[NUM_BMODES][NUM_BMODES][NUM_BMODES] = { + { { 40, 1151, 1723, 1874, 2103, 2019, 1628, 1777, 2226, 2137 }, + { 192, 469, 1296, 1308, 1849, 1794, 1781, 1703, 1713, 1522 }, + { 142, 910, 762, 1684, 1849, 1576, 1460, 1305, 1801, 1657 }, + { 559, 641, 1370, 421, 1182, 1569, 1612, 1725, 863, 1007 }, + { 299, 1059, 1256, 1108, 636, 1068, 1581, 1883, 869, 1142 }, + { 277, 1111, 707, 1362, 1089, 672, 1603, 1541, 1545, 1291 }, + { 214, 781, 1609, 1303, 1632, 2229, 726, 1560, 1713, 918 }, + { 152, 1037, 1046, 1759, 1983, 2174, 1358, 742, 1740, 1390 }, + { 512, 1046, 1420, 753, 752, 1297, 1486, 1613, 460, 1207 }, + { 424, 827, 1362, 719, 1462, 1202, 1199, 1476, 1199, 538 } }, + { { 240, 402, 1134, 1491, 1659, 1505, 1517, 1555, 1979, 2099 }, + { 467, 242, 960, 1232, 1714, 1620, 1834, 1570, 1676, 1391 }, + { 500, 455, 463, 1507, 1699, 1282, 1564, 982, 2114, 2114 }, + { 672, 643, 1372, 331, 1589, 1667, 1453, 1938, 996, 876 }, + { 458, 783, 1037, 911, 738, 968, 1165, 1518, 859, 1033 }, + { 504, 815, 504, 1139, 1219, 719, 1506, 1085, 1268, 1268 }, + { 333, 630, 1445, 1239, 1883, 3672, 799, 1548, 1865, 598 }, + { 399, 644, 746, 1342, 1856, 1350, 1493, 613, 1855, 1015 }, + { 622, 749, 1205, 608, 1066, 1408, 1290, 1406, 546, 971 }, + { 500, 753, 1041, 668, 1230, 1617, 1297, 1425, 1383, 523 } }, + { { 394, 553, 523, 1502, 1536, 981, 1608, 1142, 1666, 2181 }, + { 655, 430, 375, 1411, 1861, 1220, 1677, 1135, 1978, 1553 }, + { 690, 640, 245, 1954, 2070, 1194, 1528, 982, 1972, 2232 }, + { 559, 834, 741, 867, 1131, 980, 1225, 852, 1092, 784 }, + { 690, 875, 516, 959, 673, 894, 1056, 1190, 1528, 1126 }, + { 740, 951, 384, 1277, 1177, 492, 1579, 1155, 1846, 1513 }, + { 323, 775, 1062, 1776, 3062, 1274, 813, 1188, 1372, 655 }, + { 488, 971, 484, 1767, 1515, 1775, 1115, 503, 1539, 1461 }, + { 740, 1006, 998, 709, 851, 1230, 1337, 788, 741, 721 }, + { 522, 1073, 573, 1045, 1346, 887, 1046, 1146, 1203, 697 } }, + { { 105, 864, 1442, 1009, 1934, 1840, 1519, 1920, 1673, 1579 }, + { 534, 305, 1193, 683, 1388, 2164, 1802, 1894, 1264, 1170 }, + { 305, 518, 877, 1108, 1426, 3215, 1425, 1064, 1320, 1242 }, + { 683, 732, 1927, 257, 1493, 2048, 1858, 1552, 1055, 947 }, + { 394, 814, 1024, 660, 959, 1556, 1282, 1289, 893, 1047 }, + { 528, 615, 996, 940, 1201, 635, 1094, 2515, 803, 1358 }, + { 347, 614, 1609, 1187, 3133, 1345, 1007, 1339, 1017, 667 }, + { 218, 740, 878, 1605, 3650, 3650, 1345, 758, 1357, 1617 }, + { 672, 750, 1541, 558, 1257, 1599, 1870, 2135, 402, 1087 }, + { 592, 684, 1161, 430, 1092, 1497, 1475, 1489, 1095, 822 } }, + { { 228, 1056, 1059, 1368, 752, 982, 1512, 1518, 987, 1782 }, + { 494, 514, 818, 942, 965, 892, 1610, 1356, 1048, 1363 }, + { 512, 648, 591, 1042, 761, 991, 1196, 1454, 1309, 1463 }, + { 683, 749, 1043, 676, 841, 1396, 1133, 1138, 654, 939 }, + { 622, 1101, 1126, 994, 361, 1077, 1203, 1318, 877, 1219 }, + { 631, 1068, 857, 1650, 651, 477, 1650, 1419, 828, 1170 }, + { 555, 727, 1068, 1335, 3127, 1339, 820, 1331, 1077, 429 }, + { 504, 879, 624, 1398, 889, 889, 1392, 808, 891, 1406 }, + { 683, 1602, 1289, 977, 578, 983, 1280, 1708, 406, 1122 }, + { 399, 865, 1433, 1070, 1072, 764, 968, 1477, 1223, 678 } }, + { { 333, 760, 935, 1638, 1010, 529, 1646, 1410, 1472, 2219 }, + { 512, 494, 750, 1160, 1215, 610, 1870, 1868, 1628, 1169 }, + { 572, 646, 492, 1934, 1208, 603, 1580, 1099, 1398, 1995 }, + { 786, 789, 942, 581, 1018, 951, 1599, 1207, 731, 768 }, + { 690, 1015, 672, 1078, 582, 504, 1693, 1438, 1108, 2897 }, + { 768, 1267, 571, 2005, 1243, 244, 2881, 1380, 1786, 1453 }, + { 452, 899, 1293, 903, 1311, 3100, 465, 1311, 1319, 813 }, + { 394, 927, 942, 1103, 1358, 1104, 946, 593, 1363, 1109 }, + { 559, 1005, 1007, 1016, 658, 1173, 1021, 1164, 623, 1028 }, + { 564, 796, 632, 1005, 1014, 863, 2316, 1268, 938, 764 } }, + { { 266, 606, 1098, 1228, 1497, 1243, 948, 1030, 1734, 1461 }, + { 366, 585, 901, 1060, 1407, 1247, 876, 1134, 1620, 1054 }, + { 452, 565, 542, 1729, 1479, 1479, 1016, 886, 2938, 1150 }, + { 555, 1088, 1533, 950, 1354, 895, 834, 1019, 1021, 496 }, + { 704, 815, 1193, 971, 973, 640, 1217, 2214, 832, 578 }, + { 672, 1245, 579, 871, 875, 774, 872, 1273, 1027, 949 }, + { 296, 1134, 2050, 1784, 1636, 3425, 442, 1550, 2076, 722 }, + { 342, 982, 1259, 1846, 1848, 1848, 622, 568, 1847, 1052 }, + { 555, 1064, 1304, 828, 746, 1343, 1075, 1329, 1078, 494 }, + { 288, 1167, 1285, 1174, 1639, 1639, 833, 2254, 1304, 509 } }, + { { 342, 719, 767, 1866, 1757, 1270, 1246, 550, 1746, 2151 }, + { 483, 653, 694, 1509, 1459, 1410, 1218, 507, 1914, 1266 }, + { 488, 757, 447, 2979, 1813, 1268, 1654, 539, 1849, 2109 }, + { 522, 1097, 1085, 851, 1365, 1111, 851, 901, 961, 605 }, + { 709, 716, 841, 728, 736, 945, 941, 862, 2845, 1057 }, + { 512, 1323, 500, 1336, 1083, 681, 1342, 717, 1604, 1350 }, + { 452, 1155, 1372, 1900, 1501, 3290, 311, 944, 1919, 922 }, + { 403, 1520, 977, 2132, 1733, 3522, 1076, 276, 3335, 1547 }, + { 559, 1374, 1101, 615, 673, 2462, 974, 795, 984, 984 }, + { 547, 1122, 1062, 812, 1410, 951, 1140, 622, 1268, 651 } }, + { { 165, 982, 1235, 938, 1334, 1366, 1659, 1578, 964, 1612 }, + { 592, 422, 925, 847, 1139, 1112, 1387, 2036, 861, 1041 }, + { 403, 837, 732, 770, 941, 1658, 1250, 809, 1407, 1407 }, + { 896, 874, 1071, 381, 1568, 1722, 1437, 2192, 480, 1035 }, + { 640, 1098, 1012, 1032, 684, 1382, 1581, 2106, 416, 865 }, + { 559, 1005, 819, 914, 710, 770, 1418, 920, 838, 1435 }, + { 415, 1258, 1245, 870, 1278, 3067, 770, 1021, 1287, 522 }, + { 406, 990, 601, 1009, 1265, 1265, 1267, 759, 1017, 1277 }, + { 968, 1182, 1329, 788, 1032, 1292, 1705, 1714, 203, 1403 }, + { 732, 877, 1279, 471, 901, 1161, 1545, 1294, 755, 755 } }, + { { 111, 931, 1378, 1185, 1933, 1648, 1148, 1714, 1873, 1307 }, + { 406, 414, 1030, 1023, 1910, 1404, 1313, 1647, 1509, 793 }, + { 342, 640, 575, 1088, 1241, 1349, 1161, 1350, 1756, 1502 }, + { 559, 766, 1185, 357, 1682, 1428, 1329, 1897, 1219, 802 }, + { 473, 909, 1164, 771, 719, 2508, 1427, 1432, 722, 782 }, + { 342, 892, 785, 1145, 1150, 794, 1296, 1550, 973, 1057 }, + { 208, 1036, 1326, 1343, 1606, 3395, 815, 1455, 1618, 712 }, + { 228, 928, 890, 1046, 3499, 1711, 994, 829, 1720, 1318 }, + { 768, 724, 1058, 636, 991, 1075, 1319, 1324, 616, 825 }, + { 305, 1167, 1358, 899, 1587, 1587, 987, 1988, 1332, 501 } } +}; + +//------------------------------------------------------------------------------ +// helper functions for residuals struct VP8Residual. + +void VP8InitResidual(int first, int coeff_type, + VP8Encoder* const enc, VP8Residual* const res) { + res->coeff_type = coeff_type; + res->prob = enc->proba_.coeffs_[coeff_type]; + res->stats = enc->proba_.stats_[coeff_type]; + res->costs = enc->proba_.remapped_costs_[coeff_type]; + res->first = first; +} + +//------------------------------------------------------------------------------ +// Mode costs + +int VP8GetCostLuma4(VP8EncIterator* const it, const int16_t levels[16]) { + const int x = (it->i4_ & 3), y = (it->i4_ >> 2); + VP8Residual res; + VP8Encoder* const enc = it->enc_; + int R = 0; + int ctx; + + VP8InitResidual(0, 3, enc, &res); + ctx = it->top_nz_[x] + it->left_nz_[y]; + VP8SetResidualCoeffs(levels, &res); + R += VP8GetResidualCost(ctx, &res); + return R; +} + +int VP8GetCostLuma16(VP8EncIterator* const it, const VP8ModeScore* const rd) { + VP8Residual res; + VP8Encoder* const enc = it->enc_; + int x, y; + int R = 0; + + VP8IteratorNzToBytes(it); // re-import the non-zero context + + // DC + VP8InitResidual(0, 1, enc, &res); + VP8SetResidualCoeffs(rd->y_dc_levels, &res); + R += VP8GetResidualCost(it->top_nz_[8] + it->left_nz_[8], &res); + + // AC + VP8InitResidual(1, 0, enc, &res); + for (y = 0; y < 4; ++y) { + for (x = 0; x < 4; ++x) { + const int ctx = it->top_nz_[x] + it->left_nz_[y]; + VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); + R += VP8GetResidualCost(ctx, &res); + it->top_nz_[x] = it->left_nz_[y] = (res.last >= 0); + } + } + return R; +} + +int VP8GetCostUV(VP8EncIterator* const it, const VP8ModeScore* const rd) { + VP8Residual res; + VP8Encoder* const enc = it->enc_; + int ch, x, y; + int R = 0; + + VP8IteratorNzToBytes(it); // re-import the non-zero context + + VP8InitResidual(0, 2, enc, &res); + for (ch = 0; ch <= 2; ch += 2) { + for (y = 0; y < 2; ++y) { + for (x = 0; x < 2; ++x) { + const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; + VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); + R += VP8GetResidualCost(ctx, &res); + it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = (res.last >= 0); + } + } + } + return R; +} + + +//------------------------------------------------------------------------------ +// Recording of token probabilities. + +// We keep the table-free variant around for reference, in case. +#define USE_LEVEL_CODE_TABLE + +// Simulate block coding, but only record statistics. +// Note: no need to record the fixed probas. +int VP8RecordCoeffs(int ctx, const VP8Residual* const res) { + int n = res->first; + // should be stats[VP8EncBands[n]], but it's equivalent for n=0 or 1 + proba_t* s = res->stats[n][ctx]; + if (res->last < 0) { + VP8RecordStats(0, s + 0); + return 0; + } + while (n <= res->last) { + int v; + VP8RecordStats(1, s + 0); // order of record doesn't matter + while ((v = res->coeffs[n++]) == 0) { + VP8RecordStats(0, s + 1); + s = res->stats[VP8EncBands[n]][0]; + } + VP8RecordStats(1, s + 1); + if (!VP8RecordStats(2u < (unsigned int)(v + 1), s + 2)) { // v = -1 or 1 + s = res->stats[VP8EncBands[n]][1]; + } else { + v = abs(v); +#if !defined(USE_LEVEL_CODE_TABLE) + if (!VP8RecordStats(v > 4, s + 3)) { + if (VP8RecordStats(v != 2, s + 4)) + VP8RecordStats(v == 4, s + 5); + } else if (!VP8RecordStats(v > 10, s + 6)) { + VP8RecordStats(v > 6, s + 7); + } else if (!VP8RecordStats((v >= 3 + (8 << 2)), s + 8)) { + VP8RecordStats((v >= 3 + (8 << 1)), s + 9); + } else { + VP8RecordStats((v >= 3 + (8 << 3)), s + 10); + } +#else + if (v > MAX_VARIABLE_LEVEL) { + v = MAX_VARIABLE_LEVEL; + } + + { + const int bits = VP8LevelCodes[v - 1][1]; + int pattern = VP8LevelCodes[v - 1][0]; + int i; + for (i = 0; (pattern >>= 1) != 0; ++i) { + const int mask = 2 << i; + if (pattern & 1) VP8RecordStats(!!(bits & mask), s + 3 + i); + } + } +#endif + s = res->stats[VP8EncBands[n]][2]; + } + } + if (n < 16) VP8RecordStats(0, s + 0); + return 1; +} + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/src/enc/cost_enc.h b/third-party/webp/libwebp/src/enc/cost_enc.h new file mode 100644 index 0000000000..a4b177b342 --- /dev/null +++ b/third-party/webp/libwebp/src/enc/cost_enc.h @@ -0,0 +1,82 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Cost tables for level and modes. +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_ENC_COST_ENC_H_ +#define WEBP_ENC_COST_ENC_H_ + +#include +#include +#include "src/enc/vp8i_enc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// On-the-fly info about the current set of residuals. Handy to avoid +// passing zillions of params. +typedef struct VP8Residual VP8Residual; +struct VP8Residual { + int first; + int last; + const int16_t* coeffs; + + int coeff_type; + ProbaArray* prob; + StatsArray* stats; + CostArrayPtr costs; +}; + +void VP8InitResidual(int first, int coeff_type, + VP8Encoder* const enc, VP8Residual* const res); + +int VP8RecordCoeffs(int ctx, const VP8Residual* const res); + +// Record proba context used. +static WEBP_INLINE int VP8RecordStats(int bit, proba_t* const stats) { + proba_t p = *stats; + // An overflow is inbound. Note we handle this at 0xfffe0000u instead of + // 0xffff0000u to make sure p + 1u does not overflow. + if (p >= 0xfffe0000u) { + p = ((p + 1u) >> 1) & 0x7fff7fffu; // -> divide the stats by 2. + } + // record bit count (lower 16 bits) and increment total count (upper 16 bits). + p += 0x00010000u + bit; + *stats = p; + return bit; +} + +// Cost of coding one event with probability 'proba'. +static WEBP_INLINE int VP8BitCost(int bit, uint8_t proba) { + return !bit ? VP8EntropyCost[proba] : VP8EntropyCost[255 - proba]; +} + +// Level cost calculations +extern const uint16_t VP8LevelCodes[MAX_VARIABLE_LEVEL][2]; +void VP8CalculateLevelCosts(VP8EncProba* const proba); +static WEBP_INLINE int VP8LevelCost(const uint16_t* const table, int level) { + return VP8LevelFixedCosts[level] + + table[(level > MAX_VARIABLE_LEVEL) ? MAX_VARIABLE_LEVEL : level]; +} + +// Mode costs +extern const uint16_t VP8FixedCostsUV[4]; +extern const uint16_t VP8FixedCostsI16[4]; +extern const uint16_t VP8FixedCostsI4[NUM_BMODES][NUM_BMODES][NUM_BMODES]; + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_ENC_COST_ENC_H_ diff --git a/third-party/webp/libwebp/src/enc/filter_enc.c b/third-party/webp/libwebp/src/enc/filter_enc.c new file mode 100644 index 0000000000..580800bfb8 --- /dev/null +++ b/third-party/webp/libwebp/src/enc/filter_enc.c @@ -0,0 +1,235 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Selecting filter level +// +// Author: somnath@google.com (Somnath Banerjee) + +#include +#include "src/enc/vp8i_enc.h" +#include "src/dsp/dsp.h" + +// This table gives, for a given sharpness, the filtering strength to be +// used (at least) in order to filter a given edge step delta. +// This is constructed by brute force inspection: for all delta, we iterate +// over all possible filtering strength / thresh until needs_filter() returns +// true. +#define MAX_DELTA_SIZE 64 +static const uint8_t kLevelsFromDelta[8][MAX_DELTA_SIZE] = { + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63 }, + { 0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 17, 18, + 20, 21, 23, 24, 26, 27, 29, 30, 32, 33, 35, 36, 38, 39, 41, 42, + 44, 45, 47, 48, 50, 51, 53, 54, 56, 57, 59, 60, 62, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 }, + { 0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 14, 16, 17, 19, + 20, 22, 23, 25, 26, 28, 29, 31, 32, 34, 35, 37, 38, 40, 41, 43, + 44, 46, 47, 49, 50, 52, 53, 55, 56, 58, 59, 61, 62, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 }, + { 0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 15, 16, 18, 19, + 21, 22, 24, 25, 27, 28, 30, 31, 33, 34, 36, 37, 39, 40, 42, 43, + 45, 46, 48, 49, 51, 52, 54, 55, 57, 58, 60, 61, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 }, + { 0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 14, 15, 17, 18, 20, + 21, 23, 24, 26, 27, 29, 30, 32, 33, 35, 36, 38, 39, 41, 42, 44, + 45, 47, 48, 50, 51, 53, 54, 56, 57, 59, 60, 62, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 }, + { 0, 1, 2, 4, 5, 7, 8, 9, 11, 12, 13, 15, 16, 17, 19, 20, + 22, 23, 25, 26, 28, 29, 31, 32, 34, 35, 37, 38, 40, 41, 43, 44, + 46, 47, 49, 50, 52, 53, 55, 56, 58, 59, 61, 62, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 }, + { 0, 1, 2, 4, 5, 7, 8, 9, 11, 12, 13, 15, 16, 18, 19, 21, + 22, 24, 25, 27, 28, 30, 31, 33, 34, 36, 37, 39, 40, 42, 43, 45, + 46, 48, 49, 51, 52, 54, 55, 57, 58, 60, 61, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 }, + { 0, 1, 2, 4, 5, 7, 8, 9, 11, 12, 14, 15, 17, 18, 20, 21, + 23, 24, 26, 27, 29, 30, 32, 33, 35, 36, 38, 39, 41, 42, 44, 45, + 47, 48, 50, 51, 53, 54, 56, 57, 59, 60, 62, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 } +}; + +int VP8FilterStrengthFromDelta(int sharpness, int delta) { + const int pos = (delta < MAX_DELTA_SIZE) ? delta : MAX_DELTA_SIZE - 1; + assert(sharpness >= 0 && sharpness <= 7); + return kLevelsFromDelta[sharpness][pos]; +} + +//------------------------------------------------------------------------------ +// Paragraph 15.4: compute the inner-edge filtering strength + +#if !defined(WEBP_REDUCE_SIZE) + +static int GetILevel(int sharpness, int level) { + if (sharpness > 0) { + if (sharpness > 4) { + level >>= 2; + } else { + level >>= 1; + } + if (level > 9 - sharpness) { + level = 9 - sharpness; + } + } + if (level < 1) level = 1; + return level; +} + +static void DoFilter(const VP8EncIterator* const it, int level) { + const VP8Encoder* const enc = it->enc_; + const int ilevel = GetILevel(enc->config_->filter_sharpness, level); + const int limit = 2 * level + ilevel; + + uint8_t* const y_dst = it->yuv_out2_ + Y_OFF_ENC; + uint8_t* const u_dst = it->yuv_out2_ + U_OFF_ENC; + uint8_t* const v_dst = it->yuv_out2_ + V_OFF_ENC; + + // copy current block to yuv_out2_ + memcpy(y_dst, it->yuv_out_, YUV_SIZE_ENC * sizeof(uint8_t)); + + if (enc->filter_hdr_.simple_ == 1) { // simple + VP8SimpleHFilter16i(y_dst, BPS, limit); + VP8SimpleVFilter16i(y_dst, BPS, limit); + } else { // complex + const int hev_thresh = (level >= 40) ? 2 : (level >= 15) ? 1 : 0; + VP8HFilter16i(y_dst, BPS, limit, ilevel, hev_thresh); + VP8HFilter8i(u_dst, v_dst, BPS, limit, ilevel, hev_thresh); + VP8VFilter16i(y_dst, BPS, limit, ilevel, hev_thresh); + VP8VFilter8i(u_dst, v_dst, BPS, limit, ilevel, hev_thresh); + } +} + +//------------------------------------------------------------------------------ +// SSIM metric for one macroblock + +static double GetMBSSIM(const uint8_t* yuv1, const uint8_t* yuv2) { + int x, y; + double sum = 0.; + + // compute SSIM in a 10 x 10 window + for (y = VP8_SSIM_KERNEL; y < 16 - VP8_SSIM_KERNEL; y++) { + for (x = VP8_SSIM_KERNEL; x < 16 - VP8_SSIM_KERNEL; x++) { + sum += VP8SSIMGetClipped(yuv1 + Y_OFF_ENC, BPS, yuv2 + Y_OFF_ENC, BPS, + x, y, 16, 16); + } + } + for (x = 1; x < 7; x++) { + for (y = 1; y < 7; y++) { + sum += VP8SSIMGetClipped(yuv1 + U_OFF_ENC, BPS, yuv2 + U_OFF_ENC, BPS, + x, y, 8, 8); + sum += VP8SSIMGetClipped(yuv1 + V_OFF_ENC, BPS, yuv2 + V_OFF_ENC, BPS, + x, y, 8, 8); + } + } + return sum; +} + +#endif // !defined(WEBP_REDUCE_SIZE) + +//------------------------------------------------------------------------------ +// Exposed APIs: Encoder should call the following 3 functions to adjust +// loop filter strength + +void VP8InitFilter(VP8EncIterator* const it) { +#if !defined(WEBP_REDUCE_SIZE) + if (it->lf_stats_ != NULL) { + int s, i; + for (s = 0; s < NUM_MB_SEGMENTS; s++) { + for (i = 0; i < MAX_LF_LEVELS; i++) { + (*it->lf_stats_)[s][i] = 0; + } + } + VP8SSIMDspInit(); + } +#else + (void)it; +#endif +} + +void VP8StoreFilterStats(VP8EncIterator* const it) { +#if !defined(WEBP_REDUCE_SIZE) + int d; + VP8Encoder* const enc = it->enc_; + const int s = it->mb_->segment_; + const int level0 = enc->dqm_[s].fstrength_; + + // explore +/-quant range of values around level0 + const int delta_min = -enc->dqm_[s].quant_; + const int delta_max = enc->dqm_[s].quant_; + const int step_size = (delta_max - delta_min >= 4) ? 4 : 1; + + if (it->lf_stats_ == NULL) return; + + // NOTE: Currently we are applying filter only across the sublock edges + // There are two reasons for that. + // 1. Applying filter on macro block edges will change the pixels in + // the left and top macro blocks. That will be hard to restore + // 2. Macro Blocks on the bottom and right are not yet compressed. So we + // cannot apply filter on the right and bottom macro block edges. + if (it->mb_->type_ == 1 && it->mb_->skip_) return; + + // Always try filter level zero + (*it->lf_stats_)[s][0] += GetMBSSIM(it->yuv_in_, it->yuv_out_); + + for (d = delta_min; d <= delta_max; d += step_size) { + const int level = level0 + d; + if (level <= 0 || level >= MAX_LF_LEVELS) { + continue; + } + DoFilter(it, level); + (*it->lf_stats_)[s][level] += GetMBSSIM(it->yuv_in_, it->yuv_out2_); + } +#else // defined(WEBP_REDUCE_SIZE) + (void)it; +#endif // !defined(WEBP_REDUCE_SIZE) +} + +void VP8AdjustFilterStrength(VP8EncIterator* const it) { + VP8Encoder* const enc = it->enc_; +#if !defined(WEBP_REDUCE_SIZE) + if (it->lf_stats_ != NULL) { + int s; + for (s = 0; s < NUM_MB_SEGMENTS; s++) { + int i, best_level = 0; + // Improvement over filter level 0 should be at least 1e-5 (relatively) + double best_v = 1.00001 * (*it->lf_stats_)[s][0]; + for (i = 1; i < MAX_LF_LEVELS; i++) { + const double v = (*it->lf_stats_)[s][i]; + if (v > best_v) { + best_v = v; + best_level = i; + } + } + enc->dqm_[s].fstrength_ = best_level; + } + return; + } +#endif // !defined(WEBP_REDUCE_SIZE) + if (enc->config_->filter_strength > 0) { + int max_level = 0; + int s; + for (s = 0; s < NUM_MB_SEGMENTS; s++) { + VP8SegmentInfo* const dqm = &enc->dqm_[s]; + // this '>> 3' accounts for some inverse WHT scaling + const int delta = (dqm->max_edge_ * dqm->y2_.q_[1]) >> 3; + const int level = + VP8FilterStrengthFromDelta(enc->filter_hdr_.sharpness_, delta); + if (level > dqm->fstrength_) { + dqm->fstrength_ = level; + } + if (max_level < dqm->fstrength_) { + max_level = dqm->fstrength_; + } + } + enc->filter_hdr_.level_ = max_level; + } +} + +// ----------------------------------------------------------------------------- diff --git a/third-party/webp/libwebp/src/enc/frame_enc.c b/third-party/webp/libwebp/src/enc/frame_enc.c new file mode 100644 index 0000000000..01860ca757 --- /dev/null +++ b/third-party/webp/libwebp/src/enc/frame_enc.c @@ -0,0 +1,905 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// frame coding and analysis +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include + +#include "src/enc/cost_enc.h" +#include "src/enc/vp8i_enc.h" +#include "src/dsp/dsp.h" +#include "src/webp/format_constants.h" // RIFF constants + +#define SEGMENT_VISU 0 +#define DEBUG_SEARCH 0 // useful to track search convergence + +//------------------------------------------------------------------------------ +// multi-pass convergence + +#define HEADER_SIZE_ESTIMATE (RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE + \ + VP8_FRAME_HEADER_SIZE) +#define DQ_LIMIT 0.4 // convergence is considered reached if dq < DQ_LIMIT +// we allow 2k of extra head-room in PARTITION0 limit. +#define PARTITION0_SIZE_LIMIT ((VP8_MAX_PARTITION0_SIZE - 2048ULL) << 11) + +static float Clamp(float v, float min, float max) { + return (v < min) ? min : (v > max) ? max : v; +} + +typedef struct { // struct for organizing convergence in either size or PSNR + int is_first; + float dq; + float q, last_q; + float qmin, qmax; + double value, last_value; // PSNR or size + double target; + int do_size_search; +} PassStats; + +static int InitPassStats(const VP8Encoder* const enc, PassStats* const s) { + const uint64_t target_size = (uint64_t)enc->config_->target_size; + const int do_size_search = (target_size != 0); + const float target_PSNR = enc->config_->target_PSNR; + + s->is_first = 1; + s->dq = 10.f; + s->qmin = 1.f * enc->config_->qmin; + s->qmax = 1.f * enc->config_->qmax; + s->q = s->last_q = Clamp(enc->config_->quality, s->qmin, s->qmax); + s->target = do_size_search ? (double)target_size + : (target_PSNR > 0.) ? target_PSNR + : 40.; // default, just in case + s->value = s->last_value = 0.; + s->do_size_search = do_size_search; + return do_size_search; +} + +static float ComputeNextQ(PassStats* const s) { + float dq; + if (s->is_first) { + dq = (s->value > s->target) ? -s->dq : s->dq; + s->is_first = 0; + } else if (s->value != s->last_value) { + const double slope = (s->target - s->value) / (s->last_value - s->value); + dq = (float)(slope * (s->last_q - s->q)); + } else { + dq = 0.; // we're done?! + } + // Limit variable to avoid large swings. + s->dq = Clamp(dq, -30.f, 30.f); + s->last_q = s->q; + s->last_value = s->value; + s->q = Clamp(s->q + s->dq, s->qmin, s->qmax); + return s->q; +} + +//------------------------------------------------------------------------------ +// Tables for level coding + +const uint8_t VP8Cat3[] = { 173, 148, 140 }; +const uint8_t VP8Cat4[] = { 176, 155, 140, 135 }; +const uint8_t VP8Cat5[] = { 180, 157, 141, 134, 130 }; +const uint8_t VP8Cat6[] = + { 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129 }; + +//------------------------------------------------------------------------------ +// Reset the statistics about: number of skips, token proba, level cost,... + +static void ResetStats(VP8Encoder* const enc) { + VP8EncProba* const proba = &enc->proba_; + VP8CalculateLevelCosts(proba); + proba->nb_skip_ = 0; +} + +//------------------------------------------------------------------------------ +// Skip decision probability + +#define SKIP_PROBA_THRESHOLD 250 // value below which using skip_proba is OK. + +static int CalcSkipProba(uint64_t nb, uint64_t total) { + return (int)(total ? (total - nb) * 255 / total : 255); +} + +// Returns the bit-cost for coding the skip probability. +static int FinalizeSkipProba(VP8Encoder* const enc) { + VP8EncProba* const proba = &enc->proba_; + const int nb_mbs = enc->mb_w_ * enc->mb_h_; + const int nb_events = proba->nb_skip_; + int size; + proba->skip_proba_ = CalcSkipProba(nb_events, nb_mbs); + proba->use_skip_proba_ = (proba->skip_proba_ < SKIP_PROBA_THRESHOLD); + size = 256; // 'use_skip_proba' bit + if (proba->use_skip_proba_) { + size += nb_events * VP8BitCost(1, proba->skip_proba_) + + (nb_mbs - nb_events) * VP8BitCost(0, proba->skip_proba_); + size += 8 * 256; // cost of signaling the skip_proba_ itself. + } + return size; +} + +// Collect statistics and deduce probabilities for next coding pass. +// Return the total bit-cost for coding the probability updates. +static int CalcTokenProba(int nb, int total) { + assert(nb <= total); + return nb ? (255 - nb * 255 / total) : 255; +} + +// Cost of coding 'nb' 1's and 'total-nb' 0's using 'proba' probability. +static int BranchCost(int nb, int total, int proba) { + return nb * VP8BitCost(1, proba) + (total - nb) * VP8BitCost(0, proba); +} + +static void ResetTokenStats(VP8Encoder* const enc) { + VP8EncProba* const proba = &enc->proba_; + memset(proba->stats_, 0, sizeof(proba->stats_)); +} + +static int FinalizeTokenProbas(VP8EncProba* const proba) { + int has_changed = 0; + int size = 0; + int t, b, c, p; + for (t = 0; t < NUM_TYPES; ++t) { + for (b = 0; b < NUM_BANDS; ++b) { + for (c = 0; c < NUM_CTX; ++c) { + for (p = 0; p < NUM_PROBAS; ++p) { + const proba_t stats = proba->stats_[t][b][c][p]; + const int nb = (stats >> 0) & 0xffff; + const int total = (stats >> 16) & 0xffff; + const int update_proba = VP8CoeffsUpdateProba[t][b][c][p]; + const int old_p = VP8CoeffsProba0[t][b][c][p]; + const int new_p = CalcTokenProba(nb, total); + const int old_cost = BranchCost(nb, total, old_p) + + VP8BitCost(0, update_proba); + const int new_cost = BranchCost(nb, total, new_p) + + VP8BitCost(1, update_proba) + + 8 * 256; + const int use_new_p = (old_cost > new_cost); + size += VP8BitCost(use_new_p, update_proba); + if (use_new_p) { // only use proba that seem meaningful enough. + proba->coeffs_[t][b][c][p] = new_p; + has_changed |= (new_p != old_p); + size += 8 * 256; + } else { + proba->coeffs_[t][b][c][p] = old_p; + } + } + } + } + } + proba->dirty_ = has_changed; + return size; +} + +//------------------------------------------------------------------------------ +// Finalize Segment probability based on the coding tree + +static int GetProba(int a, int b) { + const int total = a + b; + return (total == 0) ? 255 // that's the default probability. + : (255 * a + total / 2) / total; // rounded proba +} + +static void ResetSegments(VP8Encoder* const enc) { + int n; + for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) { + enc->mb_info_[n].segment_ = 0; + } +} + +static void SetSegmentProbas(VP8Encoder* const enc) { + int p[NUM_MB_SEGMENTS] = { 0 }; + int n; + + for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) { + const VP8MBInfo* const mb = &enc->mb_info_[n]; + ++p[mb->segment_]; + } +#if !defined(WEBP_DISABLE_STATS) + if (enc->pic_->stats != NULL) { + for (n = 0; n < NUM_MB_SEGMENTS; ++n) { + enc->pic_->stats->segment_size[n] = p[n]; + } + } +#endif + if (enc->segment_hdr_.num_segments_ > 1) { + uint8_t* const probas = enc->proba_.segments_; + probas[0] = GetProba(p[0] + p[1], p[2] + p[3]); + probas[1] = GetProba(p[0], p[1]); + probas[2] = GetProba(p[2], p[3]); + + enc->segment_hdr_.update_map_ = + (probas[0] != 255) || (probas[1] != 255) || (probas[2] != 255); + if (!enc->segment_hdr_.update_map_) ResetSegments(enc); + enc->segment_hdr_.size_ = + p[0] * (VP8BitCost(0, probas[0]) + VP8BitCost(0, probas[1])) + + p[1] * (VP8BitCost(0, probas[0]) + VP8BitCost(1, probas[1])) + + p[2] * (VP8BitCost(1, probas[0]) + VP8BitCost(0, probas[2])) + + p[3] * (VP8BitCost(1, probas[0]) + VP8BitCost(1, probas[2])); + } else { + enc->segment_hdr_.update_map_ = 0; + enc->segment_hdr_.size_ = 0; + } +} + +//------------------------------------------------------------------------------ +// Coefficient coding + +static int PutCoeffs(VP8BitWriter* const bw, int ctx, const VP8Residual* res) { + int n = res->first; + // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 + const uint8_t* p = res->prob[n][ctx]; + if (!VP8PutBit(bw, res->last >= 0, p[0])) { + return 0; + } + + while (n < 16) { + const int c = res->coeffs[n++]; + const int sign = c < 0; + int v = sign ? -c : c; + if (!VP8PutBit(bw, v != 0, p[1])) { + p = res->prob[VP8EncBands[n]][0]; + continue; + } + if (!VP8PutBit(bw, v > 1, p[2])) { + p = res->prob[VP8EncBands[n]][1]; + } else { + if (!VP8PutBit(bw, v > 4, p[3])) { + if (VP8PutBit(bw, v != 2, p[4])) { + VP8PutBit(bw, v == 4, p[5]); + } + } else if (!VP8PutBit(bw, v > 10, p[6])) { + if (!VP8PutBit(bw, v > 6, p[7])) { + VP8PutBit(bw, v == 6, 159); + } else { + VP8PutBit(bw, v >= 9, 165); + VP8PutBit(bw, !(v & 1), 145); + } + } else { + int mask; + const uint8_t* tab; + if (v < 3 + (8 << 1)) { // VP8Cat3 (3b) + VP8PutBit(bw, 0, p[8]); + VP8PutBit(bw, 0, p[9]); + v -= 3 + (8 << 0); + mask = 1 << 2; + tab = VP8Cat3; + } else if (v < 3 + (8 << 2)) { // VP8Cat4 (4b) + VP8PutBit(bw, 0, p[8]); + VP8PutBit(bw, 1, p[9]); + v -= 3 + (8 << 1); + mask = 1 << 3; + tab = VP8Cat4; + } else if (v < 3 + (8 << 3)) { // VP8Cat5 (5b) + VP8PutBit(bw, 1, p[8]); + VP8PutBit(bw, 0, p[10]); + v -= 3 + (8 << 2); + mask = 1 << 4; + tab = VP8Cat5; + } else { // VP8Cat6 (11b) + VP8PutBit(bw, 1, p[8]); + VP8PutBit(bw, 1, p[10]); + v -= 3 + (8 << 3); + mask = 1 << 10; + tab = VP8Cat6; + } + while (mask) { + VP8PutBit(bw, !!(v & mask), *tab++); + mask >>= 1; + } + } + p = res->prob[VP8EncBands[n]][2]; + } + VP8PutBitUniform(bw, sign); + if (n == 16 || !VP8PutBit(bw, n <= res->last, p[0])) { + return 1; // EOB + } + } + return 1; +} + +static void CodeResiduals(VP8BitWriter* const bw, VP8EncIterator* const it, + const VP8ModeScore* const rd) { + int x, y, ch; + VP8Residual res; + uint64_t pos1, pos2, pos3; + const int i16 = (it->mb_->type_ == 1); + const int segment = it->mb_->segment_; + VP8Encoder* const enc = it->enc_; + + VP8IteratorNzToBytes(it); + + pos1 = VP8BitWriterPos(bw); + if (i16) { + VP8InitResidual(0, 1, enc, &res); + VP8SetResidualCoeffs(rd->y_dc_levels, &res); + it->top_nz_[8] = it->left_nz_[8] = + PutCoeffs(bw, it->top_nz_[8] + it->left_nz_[8], &res); + VP8InitResidual(1, 0, enc, &res); + } else { + VP8InitResidual(0, 3, enc, &res); + } + + // luma-AC + for (y = 0; y < 4; ++y) { + for (x = 0; x < 4; ++x) { + const int ctx = it->top_nz_[x] + it->left_nz_[y]; + VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); + it->top_nz_[x] = it->left_nz_[y] = PutCoeffs(bw, ctx, &res); + } + } + pos2 = VP8BitWriterPos(bw); + + // U/V + VP8InitResidual(0, 2, enc, &res); + for (ch = 0; ch <= 2; ch += 2) { + for (y = 0; y < 2; ++y) { + for (x = 0; x < 2; ++x) { + const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; + VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); + it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = + PutCoeffs(bw, ctx, &res); + } + } + } + pos3 = VP8BitWriterPos(bw); + it->luma_bits_ = pos2 - pos1; + it->uv_bits_ = pos3 - pos2; + it->bit_count_[segment][i16] += it->luma_bits_; + it->bit_count_[segment][2] += it->uv_bits_; + VP8IteratorBytesToNz(it); +} + +// Same as CodeResiduals, but doesn't actually write anything. +// Instead, it just records the event distribution. +static void RecordResiduals(VP8EncIterator* const it, + const VP8ModeScore* const rd) { + int x, y, ch; + VP8Residual res; + VP8Encoder* const enc = it->enc_; + + VP8IteratorNzToBytes(it); + + if (it->mb_->type_ == 1) { // i16x16 + VP8InitResidual(0, 1, enc, &res); + VP8SetResidualCoeffs(rd->y_dc_levels, &res); + it->top_nz_[8] = it->left_nz_[8] = + VP8RecordCoeffs(it->top_nz_[8] + it->left_nz_[8], &res); + VP8InitResidual(1, 0, enc, &res); + } else { + VP8InitResidual(0, 3, enc, &res); + } + + // luma-AC + for (y = 0; y < 4; ++y) { + for (x = 0; x < 4; ++x) { + const int ctx = it->top_nz_[x] + it->left_nz_[y]; + VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); + it->top_nz_[x] = it->left_nz_[y] = VP8RecordCoeffs(ctx, &res); + } + } + + // U/V + VP8InitResidual(0, 2, enc, &res); + for (ch = 0; ch <= 2; ch += 2) { + for (y = 0; y < 2; ++y) { + for (x = 0; x < 2; ++x) { + const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; + VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); + it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = + VP8RecordCoeffs(ctx, &res); + } + } + } + + VP8IteratorBytesToNz(it); +} + +//------------------------------------------------------------------------------ +// Token buffer + +#if !defined(DISABLE_TOKEN_BUFFER) + +static int RecordTokens(VP8EncIterator* const it, const VP8ModeScore* const rd, + VP8TBuffer* const tokens) { + int x, y, ch; + VP8Residual res; + VP8Encoder* const enc = it->enc_; + + VP8IteratorNzToBytes(it); + if (it->mb_->type_ == 1) { // i16x16 + const int ctx = it->top_nz_[8] + it->left_nz_[8]; + VP8InitResidual(0, 1, enc, &res); + VP8SetResidualCoeffs(rd->y_dc_levels, &res); + it->top_nz_[8] = it->left_nz_[8] = + VP8RecordCoeffTokens(ctx, &res, tokens); + VP8InitResidual(1, 0, enc, &res); + } else { + VP8InitResidual(0, 3, enc, &res); + } + + // luma-AC + for (y = 0; y < 4; ++y) { + for (x = 0; x < 4; ++x) { + const int ctx = it->top_nz_[x] + it->left_nz_[y]; + VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); + it->top_nz_[x] = it->left_nz_[y] = + VP8RecordCoeffTokens(ctx, &res, tokens); + } + } + + // U/V + VP8InitResidual(0, 2, enc, &res); + for (ch = 0; ch <= 2; ch += 2) { + for (y = 0; y < 2; ++y) { + for (x = 0; x < 2; ++x) { + const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; + VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); + it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = + VP8RecordCoeffTokens(ctx, &res, tokens); + } + } + } + VP8IteratorBytesToNz(it); + return !tokens->error_; +} + +#endif // !DISABLE_TOKEN_BUFFER + +//------------------------------------------------------------------------------ +// ExtraInfo map / Debug function + +#if !defined(WEBP_DISABLE_STATS) + +#if SEGMENT_VISU +static void SetBlock(uint8_t* p, int value, int size) { + int y; + for (y = 0; y < size; ++y) { + memset(p, value, size); + p += BPS; + } +} +#endif + +static void ResetSSE(VP8Encoder* const enc) { + enc->sse_[0] = 0; + enc->sse_[1] = 0; + enc->sse_[2] = 0; + // Note: enc->sse_[3] is managed by alpha.c + enc->sse_count_ = 0; +} + +static void StoreSSE(const VP8EncIterator* const it) { + VP8Encoder* const enc = it->enc_; + const uint8_t* const in = it->yuv_in_; + const uint8_t* const out = it->yuv_out_; + // Note: not totally accurate at boundary. And doesn't include in-loop filter. + enc->sse_[0] += VP8SSE16x16(in + Y_OFF_ENC, out + Y_OFF_ENC); + enc->sse_[1] += VP8SSE8x8(in + U_OFF_ENC, out + U_OFF_ENC); + enc->sse_[2] += VP8SSE8x8(in + V_OFF_ENC, out + V_OFF_ENC); + enc->sse_count_ += 16 * 16; +} + +static void StoreSideInfo(const VP8EncIterator* const it) { + VP8Encoder* const enc = it->enc_; + const VP8MBInfo* const mb = it->mb_; + WebPPicture* const pic = enc->pic_; + + if (pic->stats != NULL) { + StoreSSE(it); + enc->block_count_[0] += (mb->type_ == 0); + enc->block_count_[1] += (mb->type_ == 1); + enc->block_count_[2] += (mb->skip_ != 0); + } + + if (pic->extra_info != NULL) { + uint8_t* const info = &pic->extra_info[it->x_ + it->y_ * enc->mb_w_]; + switch (pic->extra_info_type) { + case 1: *info = mb->type_; break; + case 2: *info = mb->segment_; break; + case 3: *info = enc->dqm_[mb->segment_].quant_; break; + case 4: *info = (mb->type_ == 1) ? it->preds_[0] : 0xff; break; + case 5: *info = mb->uv_mode_; break; + case 6: { + const int b = (int)((it->luma_bits_ + it->uv_bits_ + 7) >> 3); + *info = (b > 255) ? 255 : b; break; + } + case 7: *info = mb->alpha_; break; + default: *info = 0; break; + } + } +#if SEGMENT_VISU // visualize segments and prediction modes + SetBlock(it->yuv_out_ + Y_OFF_ENC, mb->segment_ * 64, 16); + SetBlock(it->yuv_out_ + U_OFF_ENC, it->preds_[0] * 64, 8); + SetBlock(it->yuv_out_ + V_OFF_ENC, mb->uv_mode_ * 64, 8); +#endif +} + +static void ResetSideInfo(const VP8EncIterator* const it) { + VP8Encoder* const enc = it->enc_; + WebPPicture* const pic = enc->pic_; + if (pic->stats != NULL) { + memset(enc->block_count_, 0, sizeof(enc->block_count_)); + } + ResetSSE(enc); +} +#else // defined(WEBP_DISABLE_STATS) +static void ResetSSE(VP8Encoder* const enc) { + (void)enc; +} +static void StoreSideInfo(const VP8EncIterator* const it) { + VP8Encoder* const enc = it->enc_; + WebPPicture* const pic = enc->pic_; + if (pic->extra_info != NULL) { + if (it->x_ == 0 && it->y_ == 0) { // only do it once, at start + memset(pic->extra_info, 0, + enc->mb_w_ * enc->mb_h_ * sizeof(*pic->extra_info)); + } + } +} + +static void ResetSideInfo(const VP8EncIterator* const it) { + (void)it; +} +#endif // !defined(WEBP_DISABLE_STATS) + +static double GetPSNR(uint64_t mse, uint64_t size) { + return (mse > 0 && size > 0) ? 10. * log10(255. * 255. * size / mse) : 99; +} + +//------------------------------------------------------------------------------ +// StatLoop(): only collect statistics (number of skips, token usage, ...). +// This is used for deciding optimal probabilities. It also modifies the +// quantizer value if some target (size, PSNR) was specified. + +static void SetLoopParams(VP8Encoder* const enc, float q) { + // Make sure the quality parameter is inside valid bounds + q = Clamp(q, 0.f, 100.f); + + VP8SetSegmentParams(enc, q); // setup segment quantizations and filters + SetSegmentProbas(enc); // compute segment probabilities + + ResetStats(enc); + ResetSSE(enc); +} + +static uint64_t OneStatPass(VP8Encoder* const enc, VP8RDLevel rd_opt, + int nb_mbs, int percent_delta, + PassStats* const s) { + VP8EncIterator it; + uint64_t size = 0; + uint64_t size_p0 = 0; + uint64_t distortion = 0; + const uint64_t pixel_count = (uint64_t)nb_mbs * 384; + + VP8IteratorInit(enc, &it); + SetLoopParams(enc, s->q); + do { + VP8ModeScore info; + VP8IteratorImport(&it, NULL); + if (VP8Decimate(&it, &info, rd_opt)) { + // Just record the number of skips and act like skip_proba is not used. + ++enc->proba_.nb_skip_; + } + RecordResiduals(&it, &info); + size += info.R + info.H; + size_p0 += info.H; + distortion += info.D; + if (percent_delta && !VP8IteratorProgress(&it, percent_delta)) { + return 0; + } + VP8IteratorSaveBoundary(&it); + } while (VP8IteratorNext(&it) && --nb_mbs > 0); + + size_p0 += enc->segment_hdr_.size_; + if (s->do_size_search) { + size += FinalizeSkipProba(enc); + size += FinalizeTokenProbas(&enc->proba_); + size = ((size + size_p0 + 1024) >> 11) + HEADER_SIZE_ESTIMATE; + s->value = (double)size; + } else { + s->value = GetPSNR(distortion, pixel_count); + } + return size_p0; +} + +static int StatLoop(VP8Encoder* const enc) { + const int method = enc->method_; + const int do_search = enc->do_search_; + const int fast_probe = ((method == 0 || method == 3) && !do_search); + int num_pass_left = enc->config_->pass; + const int task_percent = 20; + const int percent_per_pass = + (task_percent + num_pass_left / 2) / num_pass_left; + const int final_percent = enc->percent_ + task_percent; + const VP8RDLevel rd_opt = + (method >= 3 || do_search) ? RD_OPT_BASIC : RD_OPT_NONE; + int nb_mbs = enc->mb_w_ * enc->mb_h_; + PassStats stats; + + InitPassStats(enc, &stats); + ResetTokenStats(enc); + + // Fast mode: quick analysis pass over few mbs. Better than nothing. + if (fast_probe) { + if (method == 3) { // we need more stats for method 3 to be reliable. + nb_mbs = (nb_mbs > 200) ? nb_mbs >> 1 : 100; + } else { + nb_mbs = (nb_mbs > 200) ? nb_mbs >> 2 : 50; + } + } + + while (num_pass_left-- > 0) { + const int is_last_pass = (fabs(stats.dq) <= DQ_LIMIT) || + (num_pass_left == 0) || + (enc->max_i4_header_bits_ == 0); + const uint64_t size_p0 = + OneStatPass(enc, rd_opt, nb_mbs, percent_per_pass, &stats); + if (size_p0 == 0) return 0; +#if (DEBUG_SEARCH > 0) + printf("#%d value:%.1lf -> %.1lf q:%.2f -> %.2f\n", + num_pass_left, stats.last_value, stats.value, stats.last_q, stats.q); +#endif + if (enc->max_i4_header_bits_ > 0 && size_p0 > PARTITION0_SIZE_LIMIT) { + ++num_pass_left; + enc->max_i4_header_bits_ >>= 1; // strengthen header bit limitation... + continue; // ...and start over + } + if (is_last_pass) { + break; + } + // If no target size: just do several pass without changing 'q' + if (do_search) { + ComputeNextQ(&stats); + if (fabs(stats.dq) <= DQ_LIMIT) break; + } + } + if (!do_search || !stats.do_size_search) { + // Need to finalize probas now, since it wasn't done during the search. + FinalizeSkipProba(enc); + FinalizeTokenProbas(&enc->proba_); + } + VP8CalculateLevelCosts(&enc->proba_); // finalize costs + return WebPReportProgress(enc->pic_, final_percent, &enc->percent_); +} + +//------------------------------------------------------------------------------ +// Main loops +// + +static const uint8_t kAverageBytesPerMB[8] = { 50, 24, 16, 9, 7, 5, 3, 2 }; + +static int PreLoopInitialize(VP8Encoder* const enc) { + int p; + int ok = 1; + const int average_bytes_per_MB = kAverageBytesPerMB[enc->base_quant_ >> 4]; + const int bytes_per_parts = + enc->mb_w_ * enc->mb_h_ * average_bytes_per_MB / enc->num_parts_; + // Initialize the bit-writers + for (p = 0; ok && p < enc->num_parts_; ++p) { + ok = VP8BitWriterInit(enc->parts_ + p, bytes_per_parts); + } + if (!ok) { + VP8EncFreeBitWriters(enc); // malloc error occurred + return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + return ok; +} + +static int PostLoopFinalize(VP8EncIterator* const it, int ok) { + VP8Encoder* const enc = it->enc_; + if (ok) { // Finalize the partitions, check for extra errors. + int p; + for (p = 0; p < enc->num_parts_; ++p) { + VP8BitWriterFinish(enc->parts_ + p); + ok &= !enc->parts_[p].error_; + } + } + + if (ok) { // All good. Finish up. +#if !defined(WEBP_DISABLE_STATS) + if (enc->pic_->stats != NULL) { // finalize byte counters... + int i, s; + for (i = 0; i <= 2; ++i) { + for (s = 0; s < NUM_MB_SEGMENTS; ++s) { + enc->residual_bytes_[i][s] = (int)((it->bit_count_[s][i] + 7) >> 3); + } + } + } +#endif + VP8AdjustFilterStrength(it); // ...and store filter stats. + } else { + // Something bad happened -> need to do some memory cleanup. + VP8EncFreeBitWriters(enc); + return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + return ok; +} + +//------------------------------------------------------------------------------ +// VP8EncLoop(): does the final bitstream coding. + +static void ResetAfterSkip(VP8EncIterator* const it) { + if (it->mb_->type_ == 1) { + *it->nz_ = 0; // reset all predictors + it->left_nz_[8] = 0; + } else { + *it->nz_ &= (1 << 24); // preserve the dc_nz bit + } +} + +int VP8EncLoop(VP8Encoder* const enc) { + VP8EncIterator it; + int ok = PreLoopInitialize(enc); + if (!ok) return 0; + + StatLoop(enc); // stats-collection loop + + VP8IteratorInit(enc, &it); + VP8InitFilter(&it); + do { + VP8ModeScore info; + const int dont_use_skip = !enc->proba_.use_skip_proba_; + const VP8RDLevel rd_opt = enc->rd_opt_level_; + + VP8IteratorImport(&it, NULL); + // Warning! order is important: first call VP8Decimate() and + // *then* decide how to code the skip decision if there's one. + if (!VP8Decimate(&it, &info, rd_opt) || dont_use_skip) { + CodeResiduals(it.bw_, &it, &info); + if (it.bw_->error_) { + // enc->pic_->error_code is set in PostLoopFinalize(). + ok = 0; + break; + } + } else { // reset predictors after a skip + ResetAfterSkip(&it); + } + StoreSideInfo(&it); + VP8StoreFilterStats(&it); + VP8IteratorExport(&it); + ok = VP8IteratorProgress(&it, 20); + VP8IteratorSaveBoundary(&it); + } while (ok && VP8IteratorNext(&it)); + + return PostLoopFinalize(&it, ok); +} + +//------------------------------------------------------------------------------ +// Single pass using Token Buffer. + +#if !defined(DISABLE_TOKEN_BUFFER) + +#define MIN_COUNT 96 // minimum number of macroblocks before updating stats + +int VP8EncTokenLoop(VP8Encoder* const enc) { + // Roughly refresh the proba eight times per pass + int max_count = (enc->mb_w_ * enc->mb_h_) >> 3; + int num_pass_left = enc->config_->pass; + int remaining_progress = 40; // percents + const int do_search = enc->do_search_; + VP8EncIterator it; + VP8EncProba* const proba = &enc->proba_; + const VP8RDLevel rd_opt = enc->rd_opt_level_; + const uint64_t pixel_count = (uint64_t)enc->mb_w_ * enc->mb_h_ * 384; + PassStats stats; + int ok; + + InitPassStats(enc, &stats); + ok = PreLoopInitialize(enc); + if (!ok) return 0; + + if (max_count < MIN_COUNT) max_count = MIN_COUNT; + + assert(enc->num_parts_ == 1); + assert(enc->use_tokens_); + assert(proba->use_skip_proba_ == 0); + assert(rd_opt >= RD_OPT_BASIC); // otherwise, token-buffer won't be useful + assert(num_pass_left > 0); + + while (ok && num_pass_left-- > 0) { + const int is_last_pass = (fabs(stats.dq) <= DQ_LIMIT) || + (num_pass_left == 0) || + (enc->max_i4_header_bits_ == 0); + uint64_t size_p0 = 0; + uint64_t distortion = 0; + int cnt = max_count; + // The final number of passes is not trivial to know in advance. + const int pass_progress = remaining_progress / (2 + num_pass_left); + remaining_progress -= pass_progress; + VP8IteratorInit(enc, &it); + SetLoopParams(enc, stats.q); + if (is_last_pass) { + ResetTokenStats(enc); + VP8InitFilter(&it); // don't collect stats until last pass (too costly) + } + VP8TBufferClear(&enc->tokens_); + do { + VP8ModeScore info; + VP8IteratorImport(&it, NULL); + if (--cnt < 0) { + FinalizeTokenProbas(proba); + VP8CalculateLevelCosts(proba); // refresh cost tables for rd-opt + cnt = max_count; + } + VP8Decimate(&it, &info, rd_opt); + ok = RecordTokens(&it, &info, &enc->tokens_); + if (!ok) { + WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); + break; + } + size_p0 += info.H; + distortion += info.D; + if (is_last_pass) { + StoreSideInfo(&it); + VP8StoreFilterStats(&it); + VP8IteratorExport(&it); + ok = VP8IteratorProgress(&it, pass_progress); + } + VP8IteratorSaveBoundary(&it); + } while (ok && VP8IteratorNext(&it)); + if (!ok) break; + + size_p0 += enc->segment_hdr_.size_; + if (stats.do_size_search) { + uint64_t size = FinalizeTokenProbas(&enc->proba_); + size += VP8EstimateTokenSize(&enc->tokens_, + (const uint8_t*)proba->coeffs_); + size = (size + size_p0 + 1024) >> 11; // -> size in bytes + size += HEADER_SIZE_ESTIMATE; + stats.value = (double)size; + } else { // compute and store PSNR + stats.value = GetPSNR(distortion, pixel_count); + } + +#if (DEBUG_SEARCH > 0) + printf("#%2d metric:%.1lf -> %.1lf last_q=%.2lf q=%.2lf dq=%.2lf " + " range:[%.1f, %.1f]\n", + num_pass_left, stats.last_value, stats.value, + stats.last_q, stats.q, stats.dq, stats.qmin, stats.qmax); +#endif + if (enc->max_i4_header_bits_ > 0 && size_p0 > PARTITION0_SIZE_LIMIT) { + ++num_pass_left; + enc->max_i4_header_bits_ >>= 1; // strengthen header bit limitation... + if (is_last_pass) { + ResetSideInfo(&it); + } + continue; // ...and start over + } + if (is_last_pass) { + break; // done + } + if (do_search) { + ComputeNextQ(&stats); // Adjust q + } + } + if (ok) { + if (!stats.do_size_search) { + FinalizeTokenProbas(&enc->proba_); + } + ok = VP8EmitTokens(&enc->tokens_, enc->parts_ + 0, + (const uint8_t*)proba->coeffs_, 1); + } + ok = ok && WebPReportProgress(enc->pic_, enc->percent_ + remaining_progress, + &enc->percent_); + return PostLoopFinalize(&it, ok); +} + +#else + +int VP8EncTokenLoop(VP8Encoder* const enc) { + (void)enc; + return 0; // we shouldn't be here. +} + +#endif // DISABLE_TOKEN_BUFFER + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/src/enc/histogram_enc.c b/third-party/webp/libwebp/src/enc/histogram_enc.c new file mode 100644 index 0000000000..3ca67b3ad0 --- /dev/null +++ b/third-party/webp/libwebp/src/enc/histogram_enc.c @@ -0,0 +1,1250 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Jyrki Alakuijala (jyrki@google.com) +// +#ifdef HAVE_CONFIG_H +#include "src/webp/config.h" +#endif + +#include +#include + +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" +#include "src/enc/backward_references_enc.h" +#include "src/enc/histogram_enc.h" +#include "src/enc/vp8i_enc.h" +#include "src/utils/utils.h" + +#define MAX_BIT_COST FLT_MAX + +// Number of partitions for the three dominant (literal, red and blue) symbol +// costs. +#define NUM_PARTITIONS 4 +// The size of the bin-hash corresponding to the three dominant costs. +#define BIN_SIZE (NUM_PARTITIONS * NUM_PARTITIONS * NUM_PARTITIONS) +// Maximum number of histograms allowed in greedy combining algorithm. +#define MAX_HISTO_GREEDY 100 + +static void HistogramClear(VP8LHistogram* const p) { + uint32_t* const literal = p->literal_; + const int cache_bits = p->palette_code_bits_; + const int histo_size = VP8LGetHistogramSize(cache_bits); + memset(p, 0, histo_size); + p->palette_code_bits_ = cache_bits; + p->literal_ = literal; +} + +// Swap two histogram pointers. +static void HistogramSwap(VP8LHistogram** const A, VP8LHistogram** const B) { + VP8LHistogram* const tmp = *A; + *A = *B; + *B = tmp; +} + +static void HistogramCopy(const VP8LHistogram* const src, + VP8LHistogram* const dst) { + uint32_t* const dst_literal = dst->literal_; + const int dst_cache_bits = dst->palette_code_bits_; + const int literal_size = VP8LHistogramNumCodes(dst_cache_bits); + const int histo_size = VP8LGetHistogramSize(dst_cache_bits); + assert(src->palette_code_bits_ == dst_cache_bits); + memcpy(dst, src, histo_size); + dst->literal_ = dst_literal; + memcpy(dst->literal_, src->literal_, literal_size * sizeof(*dst->literal_)); +} + +int VP8LGetHistogramSize(int cache_bits) { + const int literal_size = VP8LHistogramNumCodes(cache_bits); + const size_t total_size = sizeof(VP8LHistogram) + sizeof(int) * literal_size; + assert(total_size <= (size_t)0x7fffffff); + return (int)total_size; +} + +void VP8LFreeHistogram(VP8LHistogram* const histo) { + WebPSafeFree(histo); +} + +void VP8LFreeHistogramSet(VP8LHistogramSet* const histo) { + WebPSafeFree(histo); +} + +void VP8LHistogramStoreRefs(const VP8LBackwardRefs* const refs, + VP8LHistogram* const histo) { + VP8LRefsCursor c = VP8LRefsCursorInit(refs); + while (VP8LRefsCursorOk(&c)) { + VP8LHistogramAddSinglePixOrCopy(histo, c.cur_pos, NULL, 0); + VP8LRefsCursorNext(&c); + } +} + +void VP8LHistogramCreate(VP8LHistogram* const p, + const VP8LBackwardRefs* const refs, + int palette_code_bits) { + if (palette_code_bits >= 0) { + p->palette_code_bits_ = palette_code_bits; + } + HistogramClear(p); + VP8LHistogramStoreRefs(refs, p); +} + +void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits, + int init_arrays) { + p->palette_code_bits_ = palette_code_bits; + if (init_arrays) { + HistogramClear(p); + } else { + p->trivial_symbol_ = 0; + p->bit_cost_ = 0.; + p->literal_cost_ = 0.; + p->red_cost_ = 0.; + p->blue_cost_ = 0.; + memset(p->is_used_, 0, sizeof(p->is_used_)); + } +} + +VP8LHistogram* VP8LAllocateHistogram(int cache_bits) { + VP8LHistogram* histo = NULL; + const int total_size = VP8LGetHistogramSize(cache_bits); + uint8_t* const memory = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*memory)); + if (memory == NULL) return NULL; + histo = (VP8LHistogram*)memory; + // literal_ won't necessary be aligned. + histo->literal_ = (uint32_t*)(memory + sizeof(VP8LHistogram)); + VP8LHistogramInit(histo, cache_bits, /*init_arrays=*/ 0); + return histo; +} + +// Resets the pointers of the histograms to point to the bit buffer in the set. +static void HistogramSetResetPointers(VP8LHistogramSet* const set, + int cache_bits) { + int i; + const int histo_size = VP8LGetHistogramSize(cache_bits); + uint8_t* memory = (uint8_t*) (set->histograms); + memory += set->max_size * sizeof(*set->histograms); + for (i = 0; i < set->max_size; ++i) { + memory = (uint8_t*) WEBP_ALIGN(memory); + set->histograms[i] = (VP8LHistogram*) memory; + // literal_ won't necessary be aligned. + set->histograms[i]->literal_ = (uint32_t*)(memory + sizeof(VP8LHistogram)); + memory += histo_size; + } +} + +// Returns the total size of the VP8LHistogramSet. +static size_t HistogramSetTotalSize(int size, int cache_bits) { + const int histo_size = VP8LGetHistogramSize(cache_bits); + return (sizeof(VP8LHistogramSet) + size * (sizeof(VP8LHistogram*) + + histo_size + WEBP_ALIGN_CST)); +} + +VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits) { + int i; + VP8LHistogramSet* set; + const size_t total_size = HistogramSetTotalSize(size, cache_bits); + uint8_t* memory = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*memory)); + if (memory == NULL) return NULL; + + set = (VP8LHistogramSet*)memory; + memory += sizeof(*set); + set->histograms = (VP8LHistogram**)memory; + set->max_size = size; + set->size = size; + HistogramSetResetPointers(set, cache_bits); + for (i = 0; i < size; ++i) { + VP8LHistogramInit(set->histograms[i], cache_bits, /*init_arrays=*/ 0); + } + return set; +} + +void VP8LHistogramSetClear(VP8LHistogramSet* const set) { + int i; + const int cache_bits = set->histograms[0]->palette_code_bits_; + const int size = set->max_size; + const size_t total_size = HistogramSetTotalSize(size, cache_bits); + uint8_t* memory = (uint8_t*)set; + + memset(memory, 0, total_size); + memory += sizeof(*set); + set->histograms = (VP8LHistogram**)memory; + set->max_size = size; + set->size = size; + HistogramSetResetPointers(set, cache_bits); + for (i = 0; i < size; ++i) { + set->histograms[i]->palette_code_bits_ = cache_bits; + } +} + +// Removes the histogram 'i' from 'set' by setting it to NULL. +static void HistogramSetRemoveHistogram(VP8LHistogramSet* const set, int i, + int* const num_used) { + assert(set->histograms[i] != NULL); + set->histograms[i] = NULL; + --*num_used; + // If we remove the last valid one, shrink until the next valid one. + if (i == set->size - 1) { + while (set->size >= 1 && set->histograms[set->size - 1] == NULL) { + --set->size; + } + } +} + +// ----------------------------------------------------------------------------- + +void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo, + const PixOrCopy* const v, + int (*const distance_modifier)(int, int), + int distance_modifier_arg0) { + if (PixOrCopyIsLiteral(v)) { + ++histo->alpha_[PixOrCopyLiteral(v, 3)]; + ++histo->red_[PixOrCopyLiteral(v, 2)]; + ++histo->literal_[PixOrCopyLiteral(v, 1)]; + ++histo->blue_[PixOrCopyLiteral(v, 0)]; + } else if (PixOrCopyIsCacheIdx(v)) { + const int literal_ix = + NUM_LITERAL_CODES + NUM_LENGTH_CODES + PixOrCopyCacheIdx(v); + assert(histo->palette_code_bits_ != 0); + ++histo->literal_[literal_ix]; + } else { + int code, extra_bits; + VP8LPrefixEncodeBits(PixOrCopyLength(v), &code, &extra_bits); + ++histo->literal_[NUM_LITERAL_CODES + code]; + if (distance_modifier == NULL) { + VP8LPrefixEncodeBits(PixOrCopyDistance(v), &code, &extra_bits); + } else { + VP8LPrefixEncodeBits( + distance_modifier(distance_modifier_arg0, PixOrCopyDistance(v)), + &code, &extra_bits); + } + ++histo->distance_[code]; + } +} + +// ----------------------------------------------------------------------------- +// Entropy-related functions. + +static WEBP_INLINE float BitsEntropyRefine(const VP8LBitEntropy* entropy) { + float mix; + if (entropy->nonzeros < 5) { + if (entropy->nonzeros <= 1) { + return 0; + } + // Two symbols, they will be 0 and 1 in a Huffman code. + // Let's mix in a bit of entropy to favor good clustering when + // distributions of these are combined. + if (entropy->nonzeros == 2) { + return 0.99f * entropy->sum + 0.01f * entropy->entropy; + } + // No matter what the entropy says, we cannot be better than min_limit + // with Huffman coding. I am mixing a bit of entropy into the + // min_limit since it produces much better (~0.5 %) compression results + // perhaps because of better entropy clustering. + if (entropy->nonzeros == 3) { + mix = 0.95f; + } else { + mix = 0.7f; // nonzeros == 4. + } + } else { + mix = 0.627f; + } + + { + float min_limit = 2.f * entropy->sum - entropy->max_val; + min_limit = mix * min_limit + (1.f - mix) * entropy->entropy; + return (entropy->entropy < min_limit) ? min_limit : entropy->entropy; + } +} + +float VP8LBitsEntropy(const uint32_t* const array, int n) { + VP8LBitEntropy entropy; + VP8LBitsEntropyUnrefined(array, n, &entropy); + + return BitsEntropyRefine(&entropy); +} + +static float InitialHuffmanCost(void) { + // Small bias because Huffman code length is typically not stored in + // full length. + static const int kHuffmanCodeOfHuffmanCodeSize = CODE_LENGTH_CODES * 3; + static const float kSmallBias = 9.1f; + return kHuffmanCodeOfHuffmanCodeSize - kSmallBias; +} + +// Finalize the Huffman cost based on streak numbers and length type (<3 or >=3) +static float FinalHuffmanCost(const VP8LStreaks* const stats) { + // The constants in this function are experimental and got rounded from + // their original values in 1/8 when switched to 1/1024. + float retval = InitialHuffmanCost(); + // Second coefficient: Many zeros in the histogram are covered efficiently + // by a run-length encode. Originally 2/8. + retval += stats->counts[0] * 1.5625f + 0.234375f * stats->streaks[0][1]; + // Second coefficient: Constant values are encoded less efficiently, but still + // RLE'ed. Originally 6/8. + retval += stats->counts[1] * 2.578125f + 0.703125f * stats->streaks[1][1]; + // 0s are usually encoded more efficiently than non-0s. + // Originally 15/8. + retval += 1.796875f * stats->streaks[0][0]; + // Originally 26/8. + retval += 3.28125f * stats->streaks[1][0]; + return retval; +} + +// Get the symbol entropy for the distribution 'population'. +// Set 'trivial_sym', if there's only one symbol present in the distribution. +static float PopulationCost(const uint32_t* const population, int length, + uint32_t* const trivial_sym, + uint8_t* const is_used) { + VP8LBitEntropy bit_entropy; + VP8LStreaks stats; + VP8LGetEntropyUnrefined(population, length, &bit_entropy, &stats); + if (trivial_sym != NULL) { + *trivial_sym = (bit_entropy.nonzeros == 1) ? bit_entropy.nonzero_code + : VP8L_NON_TRIVIAL_SYM; + } + // The histogram is used if there is at least one non-zero streak. + *is_used = (stats.streaks[1][0] != 0 || stats.streaks[1][1] != 0); + + return BitsEntropyRefine(&bit_entropy) + FinalHuffmanCost(&stats); +} + +// trivial_at_end is 1 if the two histograms only have one element that is +// non-zero: both the zero-th one, or both the last one. +static WEBP_INLINE float GetCombinedEntropy(const uint32_t* const X, + const uint32_t* const Y, int length, + int is_X_used, int is_Y_used, + int trivial_at_end) { + VP8LStreaks stats; + if (trivial_at_end) { + // This configuration is due to palettization that transforms an indexed + // pixel into 0xff000000 | (pixel << 8) in VP8LBundleColorMap. + // BitsEntropyRefine is 0 for histograms with only one non-zero value. + // Only FinalHuffmanCost needs to be evaluated. + memset(&stats, 0, sizeof(stats)); + // Deal with the non-zero value at index 0 or length-1. + stats.streaks[1][0] = 1; + // Deal with the following/previous zero streak. + stats.counts[0] = 1; + stats.streaks[0][1] = length - 1; + return FinalHuffmanCost(&stats); + } else { + VP8LBitEntropy bit_entropy; + if (is_X_used) { + if (is_Y_used) { + VP8LGetCombinedEntropyUnrefined(X, Y, length, &bit_entropy, &stats); + } else { + VP8LGetEntropyUnrefined(X, length, &bit_entropy, &stats); + } + } else { + if (is_Y_used) { + VP8LGetEntropyUnrefined(Y, length, &bit_entropy, &stats); + } else { + memset(&stats, 0, sizeof(stats)); + stats.counts[0] = 1; + stats.streaks[0][length > 3] = length; + VP8LBitEntropyInit(&bit_entropy); + } + } + + return BitsEntropyRefine(&bit_entropy) + FinalHuffmanCost(&stats); + } +} + +// Estimates the Entropy + Huffman + other block overhead size cost. +float VP8LHistogramEstimateBits(VP8LHistogram* const p) { + return PopulationCost(p->literal_, + VP8LHistogramNumCodes(p->palette_code_bits_), NULL, + &p->is_used_[0]) + + PopulationCost(p->red_, NUM_LITERAL_CODES, NULL, &p->is_used_[1]) + + PopulationCost(p->blue_, NUM_LITERAL_CODES, NULL, &p->is_used_[2]) + + PopulationCost(p->alpha_, NUM_LITERAL_CODES, NULL, &p->is_used_[3]) + + PopulationCost(p->distance_, NUM_DISTANCE_CODES, NULL, + &p->is_used_[4]) + + (float)VP8LExtraCost(p->literal_ + NUM_LITERAL_CODES, + NUM_LENGTH_CODES) + + (float)VP8LExtraCost(p->distance_, NUM_DISTANCE_CODES); +} + +// ----------------------------------------------------------------------------- +// Various histogram combine/cost-eval functions + +static int GetCombinedHistogramEntropy(const VP8LHistogram* const a, + const VP8LHistogram* const b, + float cost_threshold, float* cost) { + const int palette_code_bits = a->palette_code_bits_; + int trivial_at_end = 0; + assert(a->palette_code_bits_ == b->palette_code_bits_); + *cost += GetCombinedEntropy(a->literal_, b->literal_, + VP8LHistogramNumCodes(palette_code_bits), + a->is_used_[0], b->is_used_[0], 0); + *cost += (float)VP8LExtraCostCombined(a->literal_ + NUM_LITERAL_CODES, + b->literal_ + NUM_LITERAL_CODES, + NUM_LENGTH_CODES); + if (*cost > cost_threshold) return 0; + + if (a->trivial_symbol_ != VP8L_NON_TRIVIAL_SYM && + a->trivial_symbol_ == b->trivial_symbol_) { + // A, R and B are all 0 or 0xff. + const uint32_t color_a = (a->trivial_symbol_ >> 24) & 0xff; + const uint32_t color_r = (a->trivial_symbol_ >> 16) & 0xff; + const uint32_t color_b = (a->trivial_symbol_ >> 0) & 0xff; + if ((color_a == 0 || color_a == 0xff) && + (color_r == 0 || color_r == 0xff) && + (color_b == 0 || color_b == 0xff)) { + trivial_at_end = 1; + } + } + + *cost += + GetCombinedEntropy(a->red_, b->red_, NUM_LITERAL_CODES, a->is_used_[1], + b->is_used_[1], trivial_at_end); + if (*cost > cost_threshold) return 0; + + *cost += + GetCombinedEntropy(a->blue_, b->blue_, NUM_LITERAL_CODES, a->is_used_[2], + b->is_used_[2], trivial_at_end); + if (*cost > cost_threshold) return 0; + + *cost += + GetCombinedEntropy(a->alpha_, b->alpha_, NUM_LITERAL_CODES, + a->is_used_[3], b->is_used_[3], trivial_at_end); + if (*cost > cost_threshold) return 0; + + *cost += + GetCombinedEntropy(a->distance_, b->distance_, NUM_DISTANCE_CODES, + a->is_used_[4], b->is_used_[4], 0); + *cost += (float)VP8LExtraCostCombined(a->distance_, b->distance_, + NUM_DISTANCE_CODES); + if (*cost > cost_threshold) return 0; + + return 1; +} + +static WEBP_INLINE void HistogramAdd(const VP8LHistogram* const a, + const VP8LHistogram* const b, + VP8LHistogram* const out) { + VP8LHistogramAdd(a, b, out); + out->trivial_symbol_ = (a->trivial_symbol_ == b->trivial_symbol_) + ? a->trivial_symbol_ + : VP8L_NON_TRIVIAL_SYM; +} + +// Performs out = a + b, computing the cost C(a+b) - C(a) - C(b) while comparing +// to the threshold value 'cost_threshold'. The score returned is +// Score = C(a+b) - C(a) - C(b), where C(a) + C(b) is known and fixed. +// Since the previous score passed is 'cost_threshold', we only need to compare +// the partial cost against 'cost_threshold + C(a) + C(b)' to possibly bail-out +// early. +static float HistogramAddEval(const VP8LHistogram* const a, + const VP8LHistogram* const b, + VP8LHistogram* const out, float cost_threshold) { + float cost = 0; + const float sum_cost = a->bit_cost_ + b->bit_cost_; + cost_threshold += sum_cost; + + if (GetCombinedHistogramEntropy(a, b, cost_threshold, &cost)) { + HistogramAdd(a, b, out); + out->bit_cost_ = cost; + out->palette_code_bits_ = a->palette_code_bits_; + } + + return cost - sum_cost; +} + +// Same as HistogramAddEval(), except that the resulting histogram +// is not stored. Only the cost C(a+b) - C(a) is evaluated. We omit +// the term C(b) which is constant over all the evaluations. +static float HistogramAddThresh(const VP8LHistogram* const a, + const VP8LHistogram* const b, + float cost_threshold) { + float cost; + assert(a != NULL && b != NULL); + cost = -a->bit_cost_; + GetCombinedHistogramEntropy(a, b, cost_threshold, &cost); + return cost; +} + +// ----------------------------------------------------------------------------- + +// The structure to keep track of cost range for the three dominant entropy +// symbols. +typedef struct { + float literal_max_; + float literal_min_; + float red_max_; + float red_min_; + float blue_max_; + float blue_min_; +} DominantCostRange; + +static void DominantCostRangeInit(DominantCostRange* const c) { + c->literal_max_ = 0.; + c->literal_min_ = MAX_BIT_COST; + c->red_max_ = 0.; + c->red_min_ = MAX_BIT_COST; + c->blue_max_ = 0.; + c->blue_min_ = MAX_BIT_COST; +} + +static void UpdateDominantCostRange( + const VP8LHistogram* const h, DominantCostRange* const c) { + if (c->literal_max_ < h->literal_cost_) c->literal_max_ = h->literal_cost_; + if (c->literal_min_ > h->literal_cost_) c->literal_min_ = h->literal_cost_; + if (c->red_max_ < h->red_cost_) c->red_max_ = h->red_cost_; + if (c->red_min_ > h->red_cost_) c->red_min_ = h->red_cost_; + if (c->blue_max_ < h->blue_cost_) c->blue_max_ = h->blue_cost_; + if (c->blue_min_ > h->blue_cost_) c->blue_min_ = h->blue_cost_; +} + +static void UpdateHistogramCost(VP8LHistogram* const h) { + uint32_t alpha_sym, red_sym, blue_sym; + const float alpha_cost = + PopulationCost(h->alpha_, NUM_LITERAL_CODES, &alpha_sym, &h->is_used_[3]); + const float distance_cost = + PopulationCost(h->distance_, NUM_DISTANCE_CODES, NULL, &h->is_used_[4]) + + (float)VP8LExtraCost(h->distance_, NUM_DISTANCE_CODES); + const int num_codes = VP8LHistogramNumCodes(h->palette_code_bits_); + h->literal_cost_ = + PopulationCost(h->literal_, num_codes, NULL, &h->is_used_[0]) + + (float)VP8LExtraCost(h->literal_ + NUM_LITERAL_CODES, NUM_LENGTH_CODES); + h->red_cost_ = + PopulationCost(h->red_, NUM_LITERAL_CODES, &red_sym, &h->is_used_[1]); + h->blue_cost_ = + PopulationCost(h->blue_, NUM_LITERAL_CODES, &blue_sym, &h->is_used_[2]); + h->bit_cost_ = h->literal_cost_ + h->red_cost_ + h->blue_cost_ + + alpha_cost + distance_cost; + if ((alpha_sym | red_sym | blue_sym) == VP8L_NON_TRIVIAL_SYM) { + h->trivial_symbol_ = VP8L_NON_TRIVIAL_SYM; + } else { + h->trivial_symbol_ = + ((uint32_t)alpha_sym << 24) | (red_sym << 16) | (blue_sym << 0); + } +} + +static int GetBinIdForEntropy(float min, float max, float val) { + const float range = max - min; + if (range > 0.) { + const float delta = val - min; + return (int)((NUM_PARTITIONS - 1e-6) * delta / range); + } else { + return 0; + } +} + +static int GetHistoBinIndex(const VP8LHistogram* const h, + const DominantCostRange* const c, int low_effort) { + int bin_id = GetBinIdForEntropy(c->literal_min_, c->literal_max_, + h->literal_cost_); + assert(bin_id < NUM_PARTITIONS); + if (!low_effort) { + bin_id = bin_id * NUM_PARTITIONS + + GetBinIdForEntropy(c->red_min_, c->red_max_, h->red_cost_); + bin_id = bin_id * NUM_PARTITIONS + + GetBinIdForEntropy(c->blue_min_, c->blue_max_, h->blue_cost_); + assert(bin_id < BIN_SIZE); + } + return bin_id; +} + +// Construct the histograms from backward references. +static void HistogramBuild( + int xsize, int histo_bits, const VP8LBackwardRefs* const backward_refs, + VP8LHistogramSet* const image_histo) { + int x = 0, y = 0; + const int histo_xsize = VP8LSubSampleSize(xsize, histo_bits); + VP8LHistogram** const histograms = image_histo->histograms; + VP8LRefsCursor c = VP8LRefsCursorInit(backward_refs); + assert(histo_bits > 0); + VP8LHistogramSetClear(image_histo); + while (VP8LRefsCursorOk(&c)) { + const PixOrCopy* const v = c.cur_pos; + const int ix = (y >> histo_bits) * histo_xsize + (x >> histo_bits); + VP8LHistogramAddSinglePixOrCopy(histograms[ix], v, NULL, 0); + x += PixOrCopyLength(v); + while (x >= xsize) { + x -= xsize; + ++y; + } + VP8LRefsCursorNext(&c); + } +} + +// Copies the histograms and computes its bit_cost. +static const uint16_t kInvalidHistogramSymbol = (uint16_t)(-1); +static void HistogramCopyAndAnalyze(VP8LHistogramSet* const orig_histo, + VP8LHistogramSet* const image_histo, + int* const num_used, + uint16_t* const histogram_symbols) { + int i, cluster_id; + int num_used_orig = *num_used; + VP8LHistogram** const orig_histograms = orig_histo->histograms; + VP8LHistogram** const histograms = image_histo->histograms; + assert(image_histo->max_size == orig_histo->max_size); + for (cluster_id = 0, i = 0; i < orig_histo->max_size; ++i) { + VP8LHistogram* const histo = orig_histograms[i]; + UpdateHistogramCost(histo); + + // Skip the histogram if it is completely empty, which can happen for tiles + // with no information (when they are skipped because of LZ77). + if (!histo->is_used_[0] && !histo->is_used_[1] && !histo->is_used_[2] + && !histo->is_used_[3] && !histo->is_used_[4]) { + // The first histogram is always used. If an histogram is empty, we set + // its id to be the same as the previous one: this will improve + // compressibility for later LZ77. + assert(i > 0); + HistogramSetRemoveHistogram(image_histo, i, num_used); + HistogramSetRemoveHistogram(orig_histo, i, &num_used_orig); + histogram_symbols[i] = kInvalidHistogramSymbol; + } else { + // Copy histograms from orig_histo[] to image_histo[]. + HistogramCopy(histo, histograms[i]); + histogram_symbols[i] = cluster_id++; + assert(cluster_id <= image_histo->max_size); + } + } +} + +// Partition histograms to different entropy bins for three dominant (literal, +// red and blue) symbol costs and compute the histogram aggregate bit_cost. +static void HistogramAnalyzeEntropyBin(VP8LHistogramSet* const image_histo, + uint16_t* const bin_map, + int low_effort) { + int i; + VP8LHistogram** const histograms = image_histo->histograms; + const int histo_size = image_histo->size; + DominantCostRange cost_range; + DominantCostRangeInit(&cost_range); + + // Analyze the dominant (literal, red and blue) entropy costs. + for (i = 0; i < histo_size; ++i) { + if (histograms[i] == NULL) continue; + UpdateDominantCostRange(histograms[i], &cost_range); + } + + // bin-hash histograms on three of the dominant (literal, red and blue) + // symbol costs and store the resulting bin_id for each histogram. + for (i = 0; i < histo_size; ++i) { + // bin_map[i] is not set to a special value as its use will later be guarded + // by another (histograms[i] == NULL). + if (histograms[i] == NULL) continue; + bin_map[i] = GetHistoBinIndex(histograms[i], &cost_range, low_effort); + } +} + +// Merges some histograms with same bin_id together if it's advantageous. +// Sets the remaining histograms to NULL. +static void HistogramCombineEntropyBin( + VP8LHistogramSet* const image_histo, int* num_used, + const uint16_t* const clusters, uint16_t* const cluster_mappings, + VP8LHistogram* cur_combo, const uint16_t* const bin_map, int num_bins, + float combine_cost_factor, int low_effort) { + VP8LHistogram** const histograms = image_histo->histograms; + int idx; + struct { + int16_t first; // position of the histogram that accumulates all + // histograms with the same bin_id + uint16_t num_combine_failures; // number of combine failures per bin_id + } bin_info[BIN_SIZE]; + + assert(num_bins <= BIN_SIZE); + for (idx = 0; idx < num_bins; ++idx) { + bin_info[idx].first = -1; + bin_info[idx].num_combine_failures = 0; + } + + // By default, a cluster matches itself. + for (idx = 0; idx < *num_used; ++idx) cluster_mappings[idx] = idx; + for (idx = 0; idx < image_histo->size; ++idx) { + int bin_id, first; + if (histograms[idx] == NULL) continue; + bin_id = bin_map[idx]; + first = bin_info[bin_id].first; + if (first == -1) { + bin_info[bin_id].first = idx; + } else if (low_effort) { + HistogramAdd(histograms[idx], histograms[first], histograms[first]); + HistogramSetRemoveHistogram(image_histo, idx, num_used); + cluster_mappings[clusters[idx]] = clusters[first]; + } else { + // try to merge #idx into #first (both share the same bin_id) + const float bit_cost = histograms[idx]->bit_cost_; + const float bit_cost_thresh = -bit_cost * combine_cost_factor; + const float curr_cost_diff = HistogramAddEval( + histograms[first], histograms[idx], cur_combo, bit_cost_thresh); + if (curr_cost_diff < bit_cost_thresh) { + // Try to merge two histograms only if the combo is a trivial one or + // the two candidate histograms are already non-trivial. + // For some images, 'try_combine' turns out to be false for a lot of + // histogram pairs. In that case, we fallback to combining + // histograms as usual to avoid increasing the header size. + const int try_combine = + (cur_combo->trivial_symbol_ != VP8L_NON_TRIVIAL_SYM) || + ((histograms[idx]->trivial_symbol_ == VP8L_NON_TRIVIAL_SYM) && + (histograms[first]->trivial_symbol_ == VP8L_NON_TRIVIAL_SYM)); + const int max_combine_failures = 32; + if (try_combine || + bin_info[bin_id].num_combine_failures >= max_combine_failures) { + // move the (better) merged histogram to its final slot + HistogramSwap(&cur_combo, &histograms[first]); + HistogramSetRemoveHistogram(image_histo, idx, num_used); + cluster_mappings[clusters[idx]] = clusters[first]; + } else { + ++bin_info[bin_id].num_combine_failures; + } + } + } + } + if (low_effort) { + // for low_effort case, update the final cost when everything is merged + for (idx = 0; idx < image_histo->size; ++idx) { + if (histograms[idx] == NULL) continue; + UpdateHistogramCost(histograms[idx]); + } + } +} + +// Implement a Lehmer random number generator with a multiplicative constant of +// 48271 and a modulo constant of 2^31 - 1. +static uint32_t MyRand(uint32_t* const seed) { + *seed = (uint32_t)(((uint64_t)(*seed) * 48271u) % 2147483647u); + assert(*seed > 0); + return *seed; +} + +// ----------------------------------------------------------------------------- +// Histogram pairs priority queue + +// Pair of histograms. Negative idx1 value means that pair is out-of-date. +typedef struct { + int idx1; + int idx2; + float cost_diff; + float cost_combo; +} HistogramPair; + +typedef struct { + HistogramPair* queue; + int size; + int max_size; +} HistoQueue; + +static int HistoQueueInit(HistoQueue* const histo_queue, const int max_size) { + histo_queue->size = 0; + histo_queue->max_size = max_size; + // We allocate max_size + 1 because the last element at index "size" is + // used as temporary data (and it could be up to max_size). + histo_queue->queue = (HistogramPair*)WebPSafeMalloc( + histo_queue->max_size + 1, sizeof(*histo_queue->queue)); + return histo_queue->queue != NULL; +} + +static void HistoQueueClear(HistoQueue* const histo_queue) { + assert(histo_queue != NULL); + WebPSafeFree(histo_queue->queue); + histo_queue->size = 0; + histo_queue->max_size = 0; +} + +// Pop a specific pair in the queue by replacing it with the last one +// and shrinking the queue. +static void HistoQueuePopPair(HistoQueue* const histo_queue, + HistogramPair* const pair) { + assert(pair >= histo_queue->queue && + pair < (histo_queue->queue + histo_queue->size)); + assert(histo_queue->size > 0); + *pair = histo_queue->queue[histo_queue->size - 1]; + --histo_queue->size; +} + +// Check whether a pair in the queue should be updated as head or not. +static void HistoQueueUpdateHead(HistoQueue* const histo_queue, + HistogramPair* const pair) { + assert(pair->cost_diff < 0.); + assert(pair >= histo_queue->queue && + pair < (histo_queue->queue + histo_queue->size)); + assert(histo_queue->size > 0); + if (pair->cost_diff < histo_queue->queue[0].cost_diff) { + // Replace the best pair. + const HistogramPair tmp = histo_queue->queue[0]; + histo_queue->queue[0] = *pair; + *pair = tmp; + } +} + +// Update the cost diff and combo of a pair of histograms. This needs to be +// called when the the histograms have been merged with a third one. +static void HistoQueueUpdatePair(const VP8LHistogram* const h1, + const VP8LHistogram* const h2, float threshold, + HistogramPair* const pair) { + const float sum_cost = h1->bit_cost_ + h2->bit_cost_; + pair->cost_combo = 0.; + GetCombinedHistogramEntropy(h1, h2, sum_cost + threshold, &pair->cost_combo); + pair->cost_diff = pair->cost_combo - sum_cost; +} + +// Create a pair from indices "idx1" and "idx2" provided its cost +// is inferior to "threshold", a negative entropy. +// It returns the cost of the pair, or 0. if it superior to threshold. +static float HistoQueuePush(HistoQueue* const histo_queue, + VP8LHistogram** const histograms, int idx1, + int idx2, float threshold) { + const VP8LHistogram* h1; + const VP8LHistogram* h2; + HistogramPair pair; + + // Stop here if the queue is full. + if (histo_queue->size == histo_queue->max_size) return 0.; + assert(threshold <= 0.); + if (idx1 > idx2) { + const int tmp = idx2; + idx2 = idx1; + idx1 = tmp; + } + pair.idx1 = idx1; + pair.idx2 = idx2; + h1 = histograms[idx1]; + h2 = histograms[idx2]; + + HistoQueueUpdatePair(h1, h2, threshold, &pair); + + // Do not even consider the pair if it does not improve the entropy. + if (pair.cost_diff >= threshold) return 0.; + + histo_queue->queue[histo_queue->size++] = pair; + HistoQueueUpdateHead(histo_queue, &histo_queue->queue[histo_queue->size - 1]); + + return pair.cost_diff; +} + +// ----------------------------------------------------------------------------- + +// Combines histograms by continuously choosing the one with the highest cost +// reduction. +static int HistogramCombineGreedy(VP8LHistogramSet* const image_histo, + int* const num_used) { + int ok = 0; + const int image_histo_size = image_histo->size; + int i, j; + VP8LHistogram** const histograms = image_histo->histograms; + // Priority queue of histogram pairs. + HistoQueue histo_queue; + + // image_histo_size^2 for the queue size is safe. If you look at + // HistogramCombineGreedy, and imagine that UpdateQueueFront always pushes + // data to the queue, you insert at most: + // - image_histo_size*(image_histo_size-1)/2 (the first two for loops) + // - image_histo_size - 1 in the last for loop at the first iteration of + // the while loop, image_histo_size - 2 at the second iteration ... + // therefore image_histo_size*(image_histo_size-1)/2 overall too + if (!HistoQueueInit(&histo_queue, image_histo_size * image_histo_size)) { + goto End; + } + + for (i = 0; i < image_histo_size; ++i) { + if (image_histo->histograms[i] == NULL) continue; + for (j = i + 1; j < image_histo_size; ++j) { + // Initialize queue. + if (image_histo->histograms[j] == NULL) continue; + HistoQueuePush(&histo_queue, histograms, i, j, 0.); + } + } + + while (histo_queue.size > 0) { + const int idx1 = histo_queue.queue[0].idx1; + const int idx2 = histo_queue.queue[0].idx2; + HistogramAdd(histograms[idx2], histograms[idx1], histograms[idx1]); + histograms[idx1]->bit_cost_ = histo_queue.queue[0].cost_combo; + + // Remove merged histogram. + HistogramSetRemoveHistogram(image_histo, idx2, num_used); + + // Remove pairs intersecting the just combined best pair. + for (i = 0; i < histo_queue.size;) { + HistogramPair* const p = histo_queue.queue + i; + if (p->idx1 == idx1 || p->idx2 == idx1 || + p->idx1 == idx2 || p->idx2 == idx2) { + HistoQueuePopPair(&histo_queue, p); + } else { + HistoQueueUpdateHead(&histo_queue, p); + ++i; + } + } + + // Push new pairs formed with combined histogram to the queue. + for (i = 0; i < image_histo->size; ++i) { + if (i == idx1 || image_histo->histograms[i] == NULL) continue; + HistoQueuePush(&histo_queue, image_histo->histograms, idx1, i, 0.); + } + } + + ok = 1; + + End: + HistoQueueClear(&histo_queue); + return ok; +} + +// Perform histogram aggregation using a stochastic approach. +// 'do_greedy' is set to 1 if a greedy approach needs to be performed +// afterwards, 0 otherwise. +static int PairComparison(const void* idx1, const void* idx2) { + // To be used with bsearch: <0 when *idx1<*idx2, >0 if >, 0 when ==. + return (*(int*) idx1 - *(int*) idx2); +} +static int HistogramCombineStochastic(VP8LHistogramSet* const image_histo, + int* const num_used, int min_cluster_size, + int* const do_greedy) { + int j, iter; + uint32_t seed = 1; + int tries_with_no_success = 0; + const int outer_iters = *num_used; + const int num_tries_no_success = outer_iters / 2; + VP8LHistogram** const histograms = image_histo->histograms; + // Priority queue of histogram pairs. Its size of 'kHistoQueueSize' + // impacts the quality of the compression and the speed: the smaller the + // faster but the worse for the compression. + HistoQueue histo_queue; + const int kHistoQueueSize = 9; + int ok = 0; + // mapping from an index in image_histo with no NULL histogram to the full + // blown image_histo. + int* mappings; + + if (*num_used < min_cluster_size) { + *do_greedy = 1; + return 1; + } + + mappings = (int*) WebPSafeMalloc(*num_used, sizeof(*mappings)); + if (mappings == NULL) return 0; + if (!HistoQueueInit(&histo_queue, kHistoQueueSize)) goto End; + // Fill the initial mapping. + for (j = 0, iter = 0; iter < image_histo->size; ++iter) { + if (histograms[iter] == NULL) continue; + mappings[j++] = iter; + } + assert(j == *num_used); + + // Collapse similar histograms in 'image_histo'. + for (iter = 0; + iter < outer_iters && *num_used >= min_cluster_size && + ++tries_with_no_success < num_tries_no_success; + ++iter) { + int* mapping_index; + float best_cost = + (histo_queue.size == 0) ? 0.f : histo_queue.queue[0].cost_diff; + int best_idx1 = -1, best_idx2 = 1; + const uint32_t rand_range = (*num_used - 1) * (*num_used); + // (*num_used) / 2 was chosen empirically. Less means faster but worse + // compression. + const int num_tries = (*num_used) / 2; + + // Pick random samples. + for (j = 0; *num_used >= 2 && j < num_tries; ++j) { + float curr_cost; + // Choose two different histograms at random and try to combine them. + const uint32_t tmp = MyRand(&seed) % rand_range; + uint32_t idx1 = tmp / (*num_used - 1); + uint32_t idx2 = tmp % (*num_used - 1); + if (idx2 >= idx1) ++idx2; + idx1 = mappings[idx1]; + idx2 = mappings[idx2]; + + // Calculate cost reduction on combination. + curr_cost = + HistoQueuePush(&histo_queue, histograms, idx1, idx2, best_cost); + if (curr_cost < 0) { // found a better pair? + best_cost = curr_cost; + // Empty the queue if we reached full capacity. + if (histo_queue.size == histo_queue.max_size) break; + } + } + if (histo_queue.size == 0) continue; + + // Get the best histograms. + best_idx1 = histo_queue.queue[0].idx1; + best_idx2 = histo_queue.queue[0].idx2; + assert(best_idx1 < best_idx2); + // Pop best_idx2 from mappings. + mapping_index = (int*) bsearch(&best_idx2, mappings, *num_used, + sizeof(best_idx2), &PairComparison); + assert(mapping_index != NULL); + memmove(mapping_index, mapping_index + 1, sizeof(*mapping_index) * + ((*num_used) - (mapping_index - mappings) - 1)); + // Merge the histograms and remove best_idx2 from the queue. + HistogramAdd(histograms[best_idx2], histograms[best_idx1], + histograms[best_idx1]); + histograms[best_idx1]->bit_cost_ = histo_queue.queue[0].cost_combo; + HistogramSetRemoveHistogram(image_histo, best_idx2, num_used); + // Parse the queue and update each pair that deals with best_idx1, + // best_idx2 or image_histo_size. + for (j = 0; j < histo_queue.size;) { + HistogramPair* const p = histo_queue.queue + j; + const int is_idx1_best = p->idx1 == best_idx1 || p->idx1 == best_idx2; + const int is_idx2_best = p->idx2 == best_idx1 || p->idx2 == best_idx2; + int do_eval = 0; + // The front pair could have been duplicated by a random pick so + // check for it all the time nevertheless. + if (is_idx1_best && is_idx2_best) { + HistoQueuePopPair(&histo_queue, p); + continue; + } + // Any pair containing one of the two best indices should only refer to + // best_idx1. Its cost should also be updated. + if (is_idx1_best) { + p->idx1 = best_idx1; + do_eval = 1; + } else if (is_idx2_best) { + p->idx2 = best_idx1; + do_eval = 1; + } + // Make sure the index order is respected. + if (p->idx1 > p->idx2) { + const int tmp = p->idx2; + p->idx2 = p->idx1; + p->idx1 = tmp; + } + if (do_eval) { + // Re-evaluate the cost of an updated pair. + HistoQueueUpdatePair(histograms[p->idx1], histograms[p->idx2], 0., p); + if (p->cost_diff >= 0.) { + HistoQueuePopPair(&histo_queue, p); + continue; + } + } + HistoQueueUpdateHead(&histo_queue, p); + ++j; + } + tries_with_no_success = 0; + } + *do_greedy = (*num_used <= min_cluster_size); + ok = 1; + + End: + HistoQueueClear(&histo_queue); + WebPSafeFree(mappings); + return ok; +} + +// ----------------------------------------------------------------------------- +// Histogram refinement + +// Find the best 'out' histogram for each of the 'in' histograms. +// At call-time, 'out' contains the histograms of the clusters. +// Note: we assume that out[]->bit_cost_ is already up-to-date. +static void HistogramRemap(const VP8LHistogramSet* const in, + VP8LHistogramSet* const out, + uint16_t* const symbols) { + int i; + VP8LHistogram** const in_histo = in->histograms; + VP8LHistogram** const out_histo = out->histograms; + const int in_size = out->max_size; + const int out_size = out->size; + if (out_size > 1) { + for (i = 0; i < in_size; ++i) { + int best_out = 0; + float best_bits = MAX_BIT_COST; + int k; + if (in_histo[i] == NULL) { + // Arbitrarily set to the previous value if unused to help future LZ77. + symbols[i] = symbols[i - 1]; + continue; + } + for (k = 0; k < out_size; ++k) { + float cur_bits; + cur_bits = HistogramAddThresh(out_histo[k], in_histo[i], best_bits); + if (k == 0 || cur_bits < best_bits) { + best_bits = cur_bits; + best_out = k; + } + } + symbols[i] = best_out; + } + } else { + assert(out_size == 1); + for (i = 0; i < in_size; ++i) { + symbols[i] = 0; + } + } + + // Recompute each out based on raw and symbols. + VP8LHistogramSetClear(out); + out->size = out_size; + + for (i = 0; i < in_size; ++i) { + int idx; + if (in_histo[i] == NULL) continue; + idx = symbols[i]; + HistogramAdd(in_histo[i], out_histo[idx], out_histo[idx]); + } +} + +static float GetCombineCostFactor(int histo_size, int quality) { + float combine_cost_factor = 0.16f; + if (quality < 90) { + if (histo_size > 256) combine_cost_factor /= 2.f; + if (histo_size > 512) combine_cost_factor /= 2.f; + if (histo_size > 1024) combine_cost_factor /= 2.f; + if (quality <= 50) combine_cost_factor /= 2.f; + } + return combine_cost_factor; +} + +// Given a HistogramSet 'set', the mapping of clusters 'cluster_mapping' and the +// current assignment of the cells in 'symbols', merge the clusters and +// assign the smallest possible clusters values. +static void OptimizeHistogramSymbols(const VP8LHistogramSet* const set, + uint16_t* const cluster_mappings, + int num_clusters, + uint16_t* const cluster_mappings_tmp, + uint16_t* const symbols) { + int i, cluster_max; + int do_continue = 1; + // First, assign the lowest cluster to each pixel. + while (do_continue) { + do_continue = 0; + for (i = 0; i < num_clusters; ++i) { + int k; + k = cluster_mappings[i]; + while (k != cluster_mappings[k]) { + cluster_mappings[k] = cluster_mappings[cluster_mappings[k]]; + k = cluster_mappings[k]; + } + if (k != cluster_mappings[i]) { + do_continue = 1; + cluster_mappings[i] = k; + } + } + } + // Create a mapping from a cluster id to its minimal version. + cluster_max = 0; + memset(cluster_mappings_tmp, 0, + set->max_size * sizeof(*cluster_mappings_tmp)); + assert(cluster_mappings[0] == 0); + // Re-map the ids. + for (i = 0; i < set->max_size; ++i) { + int cluster; + if (symbols[i] == kInvalidHistogramSymbol) continue; + cluster = cluster_mappings[symbols[i]]; + assert(symbols[i] < num_clusters); + if (cluster > 0 && cluster_mappings_tmp[cluster] == 0) { + ++cluster_max; + cluster_mappings_tmp[cluster] = cluster_max; + } + symbols[i] = cluster_mappings_tmp[cluster]; + } + + // Make sure all cluster values are used. + cluster_max = 0; + for (i = 0; i < set->max_size; ++i) { + if (symbols[i] == kInvalidHistogramSymbol) continue; + if (symbols[i] <= cluster_max) continue; + ++cluster_max; + assert(symbols[i] == cluster_max); + } +} + +static void RemoveEmptyHistograms(VP8LHistogramSet* const image_histo) { + uint32_t size; + int i; + for (i = 0, size = 0; i < image_histo->size; ++i) { + if (image_histo->histograms[i] == NULL) continue; + image_histo->histograms[size++] = image_histo->histograms[i]; + } + image_histo->size = size; +} + +int VP8LGetHistoImageSymbols(int xsize, int ysize, + const VP8LBackwardRefs* const refs, int quality, + int low_effort, int histogram_bits, int cache_bits, + VP8LHistogramSet* const image_histo, + VP8LHistogram* const tmp_histo, + uint16_t* const histogram_symbols, + const WebPPicture* const pic, int percent_range, + int* const percent) { + const int histo_xsize = + histogram_bits ? VP8LSubSampleSize(xsize, histogram_bits) : 1; + const int histo_ysize = + histogram_bits ? VP8LSubSampleSize(ysize, histogram_bits) : 1; + const int image_histo_raw_size = histo_xsize * histo_ysize; + VP8LHistogramSet* const orig_histo = + VP8LAllocateHistogramSet(image_histo_raw_size, cache_bits); + // Don't attempt linear bin-partition heuristic for + // histograms of small sizes (as bin_map will be very sparse) and + // maximum quality q==100 (to preserve the compression gains at that level). + const int entropy_combine_num_bins = low_effort ? NUM_PARTITIONS : BIN_SIZE; + int entropy_combine; + uint16_t* const map_tmp = + WebPSafeMalloc(2 * image_histo_raw_size, sizeof(*map_tmp)); + uint16_t* const cluster_mappings = map_tmp + image_histo_raw_size; + int num_used = image_histo_raw_size; + if (orig_histo == NULL || map_tmp == NULL) { + WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + + // Construct the histograms from backward references. + HistogramBuild(xsize, histogram_bits, refs, orig_histo); + // Copies the histograms and computes its bit_cost. + // histogram_symbols is optimized + HistogramCopyAndAnalyze(orig_histo, image_histo, &num_used, + histogram_symbols); + + entropy_combine = + (num_used > entropy_combine_num_bins * 2) && (quality < 100); + + if (entropy_combine) { + uint16_t* const bin_map = map_tmp; + const float combine_cost_factor = + GetCombineCostFactor(image_histo_raw_size, quality); + const uint32_t num_clusters = num_used; + + HistogramAnalyzeEntropyBin(image_histo, bin_map, low_effort); + // Collapse histograms with similar entropy. + HistogramCombineEntropyBin( + image_histo, &num_used, histogram_symbols, cluster_mappings, tmp_histo, + bin_map, entropy_combine_num_bins, combine_cost_factor, low_effort); + OptimizeHistogramSymbols(image_histo, cluster_mappings, num_clusters, + map_tmp, histogram_symbols); + } + + // Don't combine the histograms using stochastic and greedy heuristics for + // low-effort compression mode. + if (!low_effort || !entropy_combine) { + const float x = quality / 100.f; + // cubic ramp between 1 and MAX_HISTO_GREEDY: + const int threshold_size = (int)(1 + (x * x * x) * (MAX_HISTO_GREEDY - 1)); + int do_greedy; + if (!HistogramCombineStochastic(image_histo, &num_used, threshold_size, + &do_greedy)) { + WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + if (do_greedy) { + RemoveEmptyHistograms(image_histo); + if (!HistogramCombineGreedy(image_histo, &num_used)) { + WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + } + } + + // Find the optimal map from original histograms to the final ones. + RemoveEmptyHistograms(image_histo); + HistogramRemap(orig_histo, image_histo, histogram_symbols); + + if (!WebPReportProgress(pic, *percent + percent_range, percent)) { + goto Error; + } + + Error: + VP8LFreeHistogramSet(orig_histo); + WebPSafeFree(map_tmp); + return (pic->error_code == VP8_ENC_OK); +} diff --git a/third-party/webp/libwebp/src/enc/histogram_enc.h b/third-party/webp/libwebp/src/enc/histogram_enc.h new file mode 100644 index 0000000000..4c0bb97464 --- /dev/null +++ b/third-party/webp/libwebp/src/enc/histogram_enc.h @@ -0,0 +1,130 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Jyrki Alakuijala (jyrki@google.com) +// +// Models the histograms of literal and distance codes. + +#ifndef WEBP_ENC_HISTOGRAM_ENC_H_ +#define WEBP_ENC_HISTOGRAM_ENC_H_ + +#include + +#include "src/enc/backward_references_enc.h" +#include "src/webp/format_constants.h" +#include "src/webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Not a trivial literal symbol. +#define VP8L_NON_TRIVIAL_SYM (0xffffffff) + +// A simple container for histograms of data. +typedef struct { + // literal_ contains green literal, palette-code and + // copy-length-prefix histogram + uint32_t* literal_; // Pointer to the allocated buffer for literal. + uint32_t red_[NUM_LITERAL_CODES]; + uint32_t blue_[NUM_LITERAL_CODES]; + uint32_t alpha_[NUM_LITERAL_CODES]; + // Backward reference prefix-code histogram. + uint32_t distance_[NUM_DISTANCE_CODES]; + int palette_code_bits_; + uint32_t trivial_symbol_; // True, if histograms for Red, Blue & Alpha + // literal symbols are single valued. + float bit_cost_; // cached value of bit cost. + float literal_cost_; // Cached values of dominant entropy costs: + float red_cost_; // literal, red & blue. + float blue_cost_; + uint8_t is_used_[5]; // 5 for literal, red, blue, alpha, distance +} VP8LHistogram; + +// Collection of histograms with fixed capacity, allocated as one +// big memory chunk. Can be destroyed by calling WebPSafeFree(). +typedef struct { + int size; // number of slots currently in use + int max_size; // maximum capacity + VP8LHistogram** histograms; +} VP8LHistogramSet; + +// Create the histogram. +// +// The input data is the PixOrCopy data, which models the literals, stop +// codes and backward references (both distances and lengths). Also: if +// palette_code_bits is >= 0, initialize the histogram with this value. +void VP8LHistogramCreate(VP8LHistogram* const p, + const VP8LBackwardRefs* const refs, + int palette_code_bits); + +// Return the size of the histogram for a given cache_bits. +int VP8LGetHistogramSize(int cache_bits); + +// Set the palette_code_bits and reset the stats. +// If init_arrays is true, the arrays are also filled with 0's. +void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits, + int init_arrays); + +// Collect all the references into a histogram (without reset) +void VP8LHistogramStoreRefs(const VP8LBackwardRefs* const refs, + VP8LHistogram* const histo); + +// Free the memory allocated for the histogram. +void VP8LFreeHistogram(VP8LHistogram* const histo); + +// Free the memory allocated for the histogram set. +void VP8LFreeHistogramSet(VP8LHistogramSet* const histo); + +// Allocate an array of pointer to histograms, allocated and initialized +// using 'cache_bits'. Return NULL in case of memory error. +VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits); + +// Set the histograms in set to 0. +void VP8LHistogramSetClear(VP8LHistogramSet* const set); + +// Allocate and initialize histogram object with specified 'cache_bits'. +// Returns NULL in case of memory error. +// Special case of VP8LAllocateHistogramSet, with size equals 1. +VP8LHistogram* VP8LAllocateHistogram(int cache_bits); + +// Accumulate a token 'v' into a histogram. +void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo, + const PixOrCopy* const v, + int (*const distance_modifier)(int, int), + int distance_modifier_arg0); + +static WEBP_INLINE int VP8LHistogramNumCodes(int palette_code_bits) { + return NUM_LITERAL_CODES + NUM_LENGTH_CODES + + ((palette_code_bits > 0) ? (1 << palette_code_bits) : 0); +} + +// Builds the histogram image. pic and percent are for progress. +// Returns false in case of error (stored in pic->error_code). +int VP8LGetHistoImageSymbols(int xsize, int ysize, + const VP8LBackwardRefs* const refs, int quality, + int low_effort, int histogram_bits, int cache_bits, + VP8LHistogramSet* const image_histo, + VP8LHistogram* const tmp_histo, + uint16_t* const histogram_symbols, + const WebPPicture* const pic, int percent_range, + int* const percent); + +// Returns the entropy for the symbols in the input array. +float VP8LBitsEntropy(const uint32_t* const array, int n); + +// Estimate how many bits the combined entropy of literals and distance +// approximately maps to. +float VP8LHistogramEstimateBits(VP8LHistogram* const p); + +#ifdef __cplusplus +} +#endif + +#endif // WEBP_ENC_HISTOGRAM_ENC_H_ diff --git a/third-party/webp/libwebp/src/enc/iterator_enc.c b/third-party/webp/libwebp/src/enc/iterator_enc.c new file mode 100644 index 0000000000..29f91d8315 --- /dev/null +++ b/third-party/webp/libwebp/src/enc/iterator_enc.c @@ -0,0 +1,459 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// VP8Iterator: block iterator +// +// Author: Skal (pascal.massimino@gmail.com) + +#include + +#include "src/enc/vp8i_enc.h" + +//------------------------------------------------------------------------------ +// VP8Iterator +//------------------------------------------------------------------------------ + +static void InitLeft(VP8EncIterator* const it) { + it->y_left_[-1] = it->u_left_[-1] = it->v_left_[-1] = + (it->y_ > 0) ? 129 : 127; + memset(it->y_left_, 129, 16); + memset(it->u_left_, 129, 8); + memset(it->v_left_, 129, 8); + it->left_nz_[8] = 0; + if (it->top_derr_ != NULL) { + memset(&it->left_derr_, 0, sizeof(it->left_derr_)); + } +} + +static void InitTop(VP8EncIterator* const it) { + const VP8Encoder* const enc = it->enc_; + const size_t top_size = enc->mb_w_ * 16; + memset(enc->y_top_, 127, 2 * top_size); + memset(enc->nz_, 0, enc->mb_w_ * sizeof(*enc->nz_)); + if (enc->top_derr_ != NULL) { + memset(enc->top_derr_, 0, enc->mb_w_ * sizeof(*enc->top_derr_)); + } +} + +void VP8IteratorSetRow(VP8EncIterator* const it, int y) { + VP8Encoder* const enc = it->enc_; + it->x_ = 0; + it->y_ = y; + it->bw_ = &enc->parts_[y & (enc->num_parts_ - 1)]; + it->preds_ = enc->preds_ + y * 4 * enc->preds_w_; + it->nz_ = enc->nz_; + it->mb_ = enc->mb_info_ + y * enc->mb_w_; + it->y_top_ = enc->y_top_; + it->uv_top_ = enc->uv_top_; + InitLeft(it); +} + +void VP8IteratorReset(VP8EncIterator* const it) { + VP8Encoder* const enc = it->enc_; + VP8IteratorSetRow(it, 0); + VP8IteratorSetCountDown(it, enc->mb_w_ * enc->mb_h_); // default + InitTop(it); + memset(it->bit_count_, 0, sizeof(it->bit_count_)); + it->do_trellis_ = 0; +} + +void VP8IteratorSetCountDown(VP8EncIterator* const it, int count_down) { + it->count_down_ = it->count_down0_ = count_down; +} + +int VP8IteratorIsDone(const VP8EncIterator* const it) { + return (it->count_down_ <= 0); +} + +void VP8IteratorInit(VP8Encoder* const enc, VP8EncIterator* const it) { + it->enc_ = enc; + it->yuv_in_ = (uint8_t*)WEBP_ALIGN(it->yuv_mem_); + it->yuv_out_ = it->yuv_in_ + YUV_SIZE_ENC; + it->yuv_out2_ = it->yuv_out_ + YUV_SIZE_ENC; + it->yuv_p_ = it->yuv_out2_ + YUV_SIZE_ENC; + it->lf_stats_ = enc->lf_stats_; + it->percent0_ = enc->percent_; + it->y_left_ = (uint8_t*)WEBP_ALIGN(it->yuv_left_mem_ + 1); + it->u_left_ = it->y_left_ + 16 + 16; + it->v_left_ = it->u_left_ + 16; + it->top_derr_ = enc->top_derr_; + VP8IteratorReset(it); +} + +int VP8IteratorProgress(const VP8EncIterator* const it, int delta) { + VP8Encoder* const enc = it->enc_; + if (delta && enc->pic_->progress_hook != NULL) { + const int done = it->count_down0_ - it->count_down_; + const int percent = (it->count_down0_ <= 0) + ? it->percent0_ + : it->percent0_ + delta * done / it->count_down0_; + return WebPReportProgress(enc->pic_, percent, &enc->percent_); + } + return 1; +} + +//------------------------------------------------------------------------------ +// Import the source samples into the cache. Takes care of replicating +// boundary pixels if necessary. + +static WEBP_INLINE int MinSize(int a, int b) { return (a < b) ? a : b; } + +static void ImportBlock(const uint8_t* src, int src_stride, + uint8_t* dst, int w, int h, int size) { + int i; + for (i = 0; i < h; ++i) { + memcpy(dst, src, w); + if (w < size) { + memset(dst + w, dst[w - 1], size - w); + } + dst += BPS; + src += src_stride; + } + for (i = h; i < size; ++i) { + memcpy(dst, dst - BPS, size); + dst += BPS; + } +} + +static void ImportLine(const uint8_t* src, int src_stride, + uint8_t* dst, int len, int total_len) { + int i; + for (i = 0; i < len; ++i, src += src_stride) dst[i] = *src; + for (; i < total_len; ++i) dst[i] = dst[len - 1]; +} + +void VP8IteratorImport(VP8EncIterator* const it, uint8_t* const tmp_32) { + const VP8Encoder* const enc = it->enc_; + const int x = it->x_, y = it->y_; + const WebPPicture* const pic = enc->pic_; + const uint8_t* const ysrc = pic->y + (y * pic->y_stride + x) * 16; + const uint8_t* const usrc = pic->u + (y * pic->uv_stride + x) * 8; + const uint8_t* const vsrc = pic->v + (y * pic->uv_stride + x) * 8; + const int w = MinSize(pic->width - x * 16, 16); + const int h = MinSize(pic->height - y * 16, 16); + const int uv_w = (w + 1) >> 1; + const int uv_h = (h + 1) >> 1; + + ImportBlock(ysrc, pic->y_stride, it->yuv_in_ + Y_OFF_ENC, w, h, 16); + ImportBlock(usrc, pic->uv_stride, it->yuv_in_ + U_OFF_ENC, uv_w, uv_h, 8); + ImportBlock(vsrc, pic->uv_stride, it->yuv_in_ + V_OFF_ENC, uv_w, uv_h, 8); + + if (tmp_32 == NULL) return; + + // Import source (uncompressed) samples into boundary. + if (x == 0) { + InitLeft(it); + } else { + if (y == 0) { + it->y_left_[-1] = it->u_left_[-1] = it->v_left_[-1] = 127; + } else { + it->y_left_[-1] = ysrc[- 1 - pic->y_stride]; + it->u_left_[-1] = usrc[- 1 - pic->uv_stride]; + it->v_left_[-1] = vsrc[- 1 - pic->uv_stride]; + } + ImportLine(ysrc - 1, pic->y_stride, it->y_left_, h, 16); + ImportLine(usrc - 1, pic->uv_stride, it->u_left_, uv_h, 8); + ImportLine(vsrc - 1, pic->uv_stride, it->v_left_, uv_h, 8); + } + + it->y_top_ = tmp_32 + 0; + it->uv_top_ = tmp_32 + 16; + if (y == 0) { + memset(tmp_32, 127, 32 * sizeof(*tmp_32)); + } else { + ImportLine(ysrc - pic->y_stride, 1, tmp_32, w, 16); + ImportLine(usrc - pic->uv_stride, 1, tmp_32 + 16, uv_w, 8); + ImportLine(vsrc - pic->uv_stride, 1, tmp_32 + 16 + 8, uv_w, 8); + } +} + +//------------------------------------------------------------------------------ +// Copy back the compressed samples into user space if requested. + +static void ExportBlock(const uint8_t* src, uint8_t* dst, int dst_stride, + int w, int h) { + while (h-- > 0) { + memcpy(dst, src, w); + dst += dst_stride; + src += BPS; + } +} + +void VP8IteratorExport(const VP8EncIterator* const it) { + const VP8Encoder* const enc = it->enc_; + if (enc->config_->show_compressed) { + const int x = it->x_, y = it->y_; + const uint8_t* const ysrc = it->yuv_out_ + Y_OFF_ENC; + const uint8_t* const usrc = it->yuv_out_ + U_OFF_ENC; + const uint8_t* const vsrc = it->yuv_out_ + V_OFF_ENC; + const WebPPicture* const pic = enc->pic_; + uint8_t* const ydst = pic->y + (y * pic->y_stride + x) * 16; + uint8_t* const udst = pic->u + (y * pic->uv_stride + x) * 8; + uint8_t* const vdst = pic->v + (y * pic->uv_stride + x) * 8; + int w = (pic->width - x * 16); + int h = (pic->height - y * 16); + + if (w > 16) w = 16; + if (h > 16) h = 16; + + // Luma plane + ExportBlock(ysrc, ydst, pic->y_stride, w, h); + + { // U/V planes + const int uv_w = (w + 1) >> 1; + const int uv_h = (h + 1) >> 1; + ExportBlock(usrc, udst, pic->uv_stride, uv_w, uv_h); + ExportBlock(vsrc, vdst, pic->uv_stride, uv_w, uv_h); + } + } +} + +//------------------------------------------------------------------------------ +// Non-zero contexts setup/teardown + +// Nz bits: +// 0 1 2 3 Y +// 4 5 6 7 +// 8 9 10 11 +// 12 13 14 15 +// 16 17 U +// 18 19 +// 20 21 V +// 22 23 +// 24 DC-intra16 + +// Convert packed context to byte array +#define BIT(nz, n) (!!((nz) & (1 << (n)))) + +void VP8IteratorNzToBytes(VP8EncIterator* const it) { + const int tnz = it->nz_[0], lnz = it->nz_[-1]; + int* const top_nz = it->top_nz_; + int* const left_nz = it->left_nz_; + + // Top-Y + top_nz[0] = BIT(tnz, 12); + top_nz[1] = BIT(tnz, 13); + top_nz[2] = BIT(tnz, 14); + top_nz[3] = BIT(tnz, 15); + // Top-U + top_nz[4] = BIT(tnz, 18); + top_nz[5] = BIT(tnz, 19); + // Top-V + top_nz[6] = BIT(tnz, 22); + top_nz[7] = BIT(tnz, 23); + // DC + top_nz[8] = BIT(tnz, 24); + + // left-Y + left_nz[0] = BIT(lnz, 3); + left_nz[1] = BIT(lnz, 7); + left_nz[2] = BIT(lnz, 11); + left_nz[3] = BIT(lnz, 15); + // left-U + left_nz[4] = BIT(lnz, 17); + left_nz[5] = BIT(lnz, 19); + // left-V + left_nz[6] = BIT(lnz, 21); + left_nz[7] = BIT(lnz, 23); + // left-DC is special, iterated separately +} + +void VP8IteratorBytesToNz(VP8EncIterator* const it) { + uint32_t nz = 0; + const int* const top_nz = it->top_nz_; + const int* const left_nz = it->left_nz_; + // top + nz |= (top_nz[0] << 12) | (top_nz[1] << 13); + nz |= (top_nz[2] << 14) | (top_nz[3] << 15); + nz |= (top_nz[4] << 18) | (top_nz[5] << 19); + nz |= (top_nz[6] << 22) | (top_nz[7] << 23); + nz |= (top_nz[8] << 24); // we propagate the _top_ bit, esp. for intra4 + // left + nz |= (left_nz[0] << 3) | (left_nz[1] << 7); + nz |= (left_nz[2] << 11); + nz |= (left_nz[4] << 17) | (left_nz[6] << 21); + + *it->nz_ = nz; +} + +#undef BIT + +//------------------------------------------------------------------------------ +// Advance to the next position, doing the bookkeeping. + +void VP8IteratorSaveBoundary(VP8EncIterator* const it) { + VP8Encoder* const enc = it->enc_; + const int x = it->x_, y = it->y_; + const uint8_t* const ysrc = it->yuv_out_ + Y_OFF_ENC; + const uint8_t* const uvsrc = it->yuv_out_ + U_OFF_ENC; + if (x < enc->mb_w_ - 1) { // left + int i; + for (i = 0; i < 16; ++i) { + it->y_left_[i] = ysrc[15 + i * BPS]; + } + for (i = 0; i < 8; ++i) { + it->u_left_[i] = uvsrc[7 + i * BPS]; + it->v_left_[i] = uvsrc[15 + i * BPS]; + } + // top-left (before 'top'!) + it->y_left_[-1] = it->y_top_[15]; + it->u_left_[-1] = it->uv_top_[0 + 7]; + it->v_left_[-1] = it->uv_top_[8 + 7]; + } + if (y < enc->mb_h_ - 1) { // top + memcpy(it->y_top_, ysrc + 15 * BPS, 16); + memcpy(it->uv_top_, uvsrc + 7 * BPS, 8 + 8); + } +} + +int VP8IteratorNext(VP8EncIterator* const it) { + if (++it->x_ == it->enc_->mb_w_) { + VP8IteratorSetRow(it, ++it->y_); + } else { + it->preds_ += 4; + it->mb_ += 1; + it->nz_ += 1; + it->y_top_ += 16; + it->uv_top_ += 16; + } + return (0 < --it->count_down_); +} + +//------------------------------------------------------------------------------ +// Helper function to set mode properties + +void VP8SetIntra16Mode(const VP8EncIterator* const it, int mode) { + uint8_t* preds = it->preds_; + int y; + for (y = 0; y < 4; ++y) { + memset(preds, mode, 4); + preds += it->enc_->preds_w_; + } + it->mb_->type_ = 1; +} + +void VP8SetIntra4Mode(const VP8EncIterator* const it, const uint8_t* modes) { + uint8_t* preds = it->preds_; + int y; + for (y = 4; y > 0; --y) { + memcpy(preds, modes, 4 * sizeof(*modes)); + preds += it->enc_->preds_w_; + modes += 4; + } + it->mb_->type_ = 0; +} + +void VP8SetIntraUVMode(const VP8EncIterator* const it, int mode) { + it->mb_->uv_mode_ = mode; +} + +void VP8SetSkip(const VP8EncIterator* const it, int skip) { + it->mb_->skip_ = skip; +} + +void VP8SetSegment(const VP8EncIterator* const it, int segment) { + it->mb_->segment_ = segment; +} + +//------------------------------------------------------------------------------ +// Intra4x4 sub-blocks iteration +// +// We store and update the boundary samples into an array of 37 pixels. They +// are updated as we iterate and reconstructs each intra4x4 blocks in turn. +// The position of the samples has the following snake pattern: +// +// 16|17 18 19 20|21 22 23 24|25 26 27 28|29 30 31 32|33 34 35 36 <- Top-right +// --+-----------+-----------+-----------+-----------+ +// 15| 19| 23| 27| 31| +// 14| 18| 22| 26| 30| +// 13| 17| 21| 25| 29| +// 12|13 14 15 16|17 18 19 20|21 22 23 24|25 26 27 28| +// --+-----------+-----------+-----------+-----------+ +// 11| 15| 19| 23| 27| +// 10| 14| 18| 22| 26| +// 9| 13| 17| 21| 25| +// 8| 9 10 11 12|13 14 15 16|17 18 19 20|21 22 23 24| +// --+-----------+-----------+-----------+-----------+ +// 7| 11| 15| 19| 23| +// 6| 10| 14| 18| 22| +// 5| 9| 13| 17| 21| +// 4| 5 6 7 8| 9 10 11 12|13 14 15 16|17 18 19 20| +// --+-----------+-----------+-----------+-----------+ +// 3| 7| 11| 15| 19| +// 2| 6| 10| 14| 18| +// 1| 5| 9| 13| 17| +// 0| 1 2 3 4| 5 6 7 8| 9 10 11 12|13 14 15 16| +// --+-----------+-----------+-----------+-----------+ + +// Array to record the position of the top sample to pass to the prediction +// functions in dsp.c. +static const uint8_t VP8TopLeftI4[16] = { + 17, 21, 25, 29, + 13, 17, 21, 25, + 9, 13, 17, 21, + 5, 9, 13, 17 +}; + +void VP8IteratorStartI4(VP8EncIterator* const it) { + const VP8Encoder* const enc = it->enc_; + int i; + + it->i4_ = 0; // first 4x4 sub-block + it->i4_top_ = it->i4_boundary_ + VP8TopLeftI4[0]; + + // Import the boundary samples + for (i = 0; i < 17; ++i) { // left + it->i4_boundary_[i] = it->y_left_[15 - i]; + } + for (i = 0; i < 16; ++i) { // top + it->i4_boundary_[17 + i] = it->y_top_[i]; + } + // top-right samples have a special case on the far right of the picture + if (it->x_ < enc->mb_w_ - 1) { + for (i = 16; i < 16 + 4; ++i) { + it->i4_boundary_[17 + i] = it->y_top_[i]; + } + } else { // else, replicate the last valid pixel four times + for (i = 16; i < 16 + 4; ++i) { + it->i4_boundary_[17 + i] = it->i4_boundary_[17 + 15]; + } + } + VP8IteratorNzToBytes(it); // import the non-zero context +} + +int VP8IteratorRotateI4(VP8EncIterator* const it, + const uint8_t* const yuv_out) { + const uint8_t* const blk = yuv_out + VP8Scan[it->i4_]; + uint8_t* const top = it->i4_top_; + int i; + + // Update the cache with 7 fresh samples + for (i = 0; i <= 3; ++i) { + top[-4 + i] = blk[i + 3 * BPS]; // store future top samples + } + if ((it->i4_ & 3) != 3) { // if not on the right sub-blocks #3, #7, #11, #15 + for (i = 0; i <= 2; ++i) { // store future left samples + top[i] = blk[3 + (2 - i) * BPS]; + } + } else { // else replicate top-right samples, as says the specs. + for (i = 0; i <= 3; ++i) { + top[i] = top[i + 4]; + } + } + // move pointers to next sub-block + ++it->i4_; + if (it->i4_ == 16) { // we're done + return 0; + } + + it->i4_top_ = it->i4_boundary_ + VP8TopLeftI4[it->i4_]; + return 1; +} + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/src/enc/near_lossless_enc.c b/third-party/webp/libwebp/src/enc/near_lossless_enc.c new file mode 100644 index 0000000000..5517a7e271 --- /dev/null +++ b/third-party/webp/libwebp/src/enc/near_lossless_enc.c @@ -0,0 +1,151 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Near-lossless image preprocessing adjusts pixel values to help +// compressibility with a guarantee of maximum deviation between original and +// resulting pixel values. +// +// Author: Jyrki Alakuijala (jyrki@google.com) +// Converted to C by Aleksander Kramarz (akramarz@google.com) + +#include +#include + +#include "src/dsp/lossless_common.h" +#include "src/utils/utils.h" +#include "src/enc/vp8li_enc.h" + +#if (WEBP_NEAR_LOSSLESS == 1) + +#define MIN_DIM_FOR_NEAR_LOSSLESS 64 +#define MAX_LIMIT_BITS 5 + +// Quantizes the value up or down to a multiple of 1<> 1) + ((a >> bits) & 1); + assert(bits > 0); + if (biased > 0xff) return 0xff; + return biased & ~mask; +} + +// Applies FindClosestDiscretized to all channels of pixel. +static uint32_t ClosestDiscretizedArgb(uint32_t a, int bits) { + return + (FindClosestDiscretized(a >> 24, bits) << 24) | + (FindClosestDiscretized((a >> 16) & 0xff, bits) << 16) | + (FindClosestDiscretized((a >> 8) & 0xff, bits) << 8) | + (FindClosestDiscretized(a & 0xff, bits)); +} + +// Checks if distance between corresponding channel values of pixels a and b +// is within the given limit. +static int IsNear(uint32_t a, uint32_t b, int limit) { + int k; + for (k = 0; k < 4; ++k) { + const int delta = + (int)((a >> (k * 8)) & 0xff) - (int)((b >> (k * 8)) & 0xff); + if (delta >= limit || delta <= -limit) { + return 0; + } + } + return 1; +} + +static int IsSmooth(const uint32_t* const prev_row, + const uint32_t* const curr_row, + const uint32_t* const next_row, + int ix, int limit) { + // Check that all pixels in 4-connected neighborhood are smooth. + return (IsNear(curr_row[ix], curr_row[ix - 1], limit) && + IsNear(curr_row[ix], curr_row[ix + 1], limit) && + IsNear(curr_row[ix], prev_row[ix], limit) && + IsNear(curr_row[ix], next_row[ix], limit)); +} + +// Adjusts pixel values of image with given maximum error. +static void NearLossless(int xsize, int ysize, const uint32_t* argb_src, + int stride, int limit_bits, uint32_t* copy_buffer, + uint32_t* argb_dst) { + int x, y; + const int limit = 1 << limit_bits; + uint32_t* prev_row = copy_buffer; + uint32_t* curr_row = prev_row + xsize; + uint32_t* next_row = curr_row + xsize; + memcpy(curr_row, argb_src, xsize * sizeof(argb_src[0])); + memcpy(next_row, argb_src + stride, xsize * sizeof(argb_src[0])); + + for (y = 0; y < ysize; ++y, argb_src += stride, argb_dst += xsize) { + if (y == 0 || y == ysize - 1) { + memcpy(argb_dst, argb_src, xsize * sizeof(argb_src[0])); + } else { + memcpy(next_row, argb_src + stride, xsize * sizeof(argb_src[0])); + argb_dst[0] = argb_src[0]; + argb_dst[xsize - 1] = argb_src[xsize - 1]; + for (x = 1; x < xsize - 1; ++x) { + if (IsSmooth(prev_row, curr_row, next_row, x, limit)) { + argb_dst[x] = curr_row[x]; + } else { + argb_dst[x] = ClosestDiscretizedArgb(curr_row[x], limit_bits); + } + } + } + { + // Three-way swap. + uint32_t* const temp = prev_row; + prev_row = curr_row; + curr_row = next_row; + next_row = temp; + } + } +} + +int VP8ApplyNearLossless(const WebPPicture* const picture, int quality, + uint32_t* const argb_dst) { + int i; + const int xsize = picture->width; + const int ysize = picture->height; + const int stride = picture->argb_stride; + uint32_t* const copy_buffer = + (uint32_t*)WebPSafeMalloc(xsize * 3, sizeof(*copy_buffer)); + const int limit_bits = VP8LNearLosslessBits(quality); + assert(argb_dst != NULL); + assert(limit_bits > 0); + assert(limit_bits <= MAX_LIMIT_BITS); + if (copy_buffer == NULL) { + return 0; + } + // For small icon images, don't attempt to apply near-lossless compression. + if ((xsize < MIN_DIM_FOR_NEAR_LOSSLESS && + ysize < MIN_DIM_FOR_NEAR_LOSSLESS) || + ysize < 3) { + for (i = 0; i < ysize; ++i) { + memcpy(argb_dst + i * xsize, picture->argb + i * picture->argb_stride, + xsize * sizeof(*argb_dst)); + } + WebPSafeFree(copy_buffer); + return 1; + } + + NearLossless(xsize, ysize, picture->argb, stride, limit_bits, copy_buffer, + argb_dst); + for (i = limit_bits - 1; i != 0; --i) { + NearLossless(xsize, ysize, argb_dst, xsize, i, copy_buffer, argb_dst); + } + WebPSafeFree(copy_buffer); + return 1; +} +#else // (WEBP_NEAR_LOSSLESS == 1) + +// Define a stub to suppress compiler warnings. +extern void VP8LNearLosslessStub(void); +void VP8LNearLosslessStub(void) {} + +#endif // (WEBP_NEAR_LOSSLESS == 1) diff --git a/third-party/webp/libwebp/src/enc/picture_csp_enc.c b/third-party/webp/libwebp/src/enc/picture_csp_enc.c new file mode 100644 index 0000000000..a9280e6c30 --- /dev/null +++ b/third-party/webp/libwebp/src/enc/picture_csp_enc.c @@ -0,0 +1,846 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// WebPPicture utils for colorspace conversion +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include +#include + +#include "sharpyuv/sharpyuv.h" +#include "sharpyuv/sharpyuv_csp.h" +#include "src/enc/vp8i_enc.h" +#include "src/utils/random_utils.h" +#include "src/utils/utils.h" +#include "src/dsp/dsp.h" +#include "src/dsp/lossless.h" +#include "src/dsp/yuv.h" +#include "src/dsp/cpu.h" + +#if defined(WEBP_USE_THREAD) && !defined(_WIN32) +#include +#endif + +// Uncomment to disable gamma-compression during RGB->U/V averaging +#define USE_GAMMA_COMPRESSION + +// If defined, use table to compute x / alpha. +#define USE_INVERSE_ALPHA_TABLE + +#ifdef WORDS_BIGENDIAN +// uint32_t 0xff000000 is 0xff,00,00,00 in memory +#define CHANNEL_OFFSET(i) (i) +#else +// uint32_t 0xff000000 is 0x00,00,00,ff in memory +#define CHANNEL_OFFSET(i) (3-(i)) +#endif + +#define ALPHA_OFFSET CHANNEL_OFFSET(0) + +//------------------------------------------------------------------------------ +// Detection of non-trivial transparency + +// Returns true if alpha[] has non-0xff values. +static int CheckNonOpaque(const uint8_t* alpha, int width, int height, + int x_step, int y_step) { + if (alpha == NULL) return 0; + WebPInitAlphaProcessing(); + if (x_step == 1) { + for (; height-- > 0; alpha += y_step) { + if (WebPHasAlpha8b(alpha, width)) return 1; + } + } else { + for (; height-- > 0; alpha += y_step) { + if (WebPHasAlpha32b(alpha, width)) return 1; + } + } + return 0; +} + +// Checking for the presence of non-opaque alpha. +int WebPPictureHasTransparency(const WebPPicture* picture) { + if (picture == NULL) return 0; + if (picture->use_argb) { + if (picture->argb != NULL) { + return CheckNonOpaque((const uint8_t*)picture->argb + ALPHA_OFFSET, + picture->width, picture->height, + 4, picture->argb_stride * sizeof(*picture->argb)); + } + return 0; + } + return CheckNonOpaque(picture->a, picture->width, picture->height, + 1, picture->a_stride); +} + +//------------------------------------------------------------------------------ +// Code for gamma correction + +#if defined(USE_GAMMA_COMPRESSION) + +// Gamma correction compensates loss of resolution during chroma subsampling. +#define GAMMA_FIX 12 // fixed-point precision for linear values +#define GAMMA_TAB_FIX 7 // fixed-point fractional bits precision +#define GAMMA_TAB_SIZE (1 << (GAMMA_FIX - GAMMA_TAB_FIX)) +static const double kGamma = 0.80; +static const int kGammaScale = ((1 << GAMMA_FIX) - 1); +static const int kGammaTabScale = (1 << GAMMA_TAB_FIX); +static const int kGammaTabRounder = (1 << GAMMA_TAB_FIX >> 1); + +static int kLinearToGammaTab[GAMMA_TAB_SIZE + 1]; +static uint16_t kGammaToLinearTab[256]; +static volatile int kGammaTablesOk = 0; +static void InitGammaTables(void); +extern VP8CPUInfo VP8GetCPUInfo; + +WEBP_DSP_INIT_FUNC(InitGammaTables) { + if (!kGammaTablesOk) { + int v; + const double scale = (double)(1 << GAMMA_TAB_FIX) / kGammaScale; + const double norm = 1. / 255.; + for (v = 0; v <= 255; ++v) { + kGammaToLinearTab[v] = + (uint16_t)(pow(norm * v, kGamma) * kGammaScale + .5); + } + for (v = 0; v <= GAMMA_TAB_SIZE; ++v) { + kLinearToGammaTab[v] = (int)(255. * pow(scale * v, 1. / kGamma) + .5); + } + kGammaTablesOk = 1; + } +} + +static WEBP_INLINE uint32_t GammaToLinear(uint8_t v) { + return kGammaToLinearTab[v]; +} + +static WEBP_INLINE int Interpolate(int v) { + const int tab_pos = v >> (GAMMA_TAB_FIX + 2); // integer part + const int x = v & ((kGammaTabScale << 2) - 1); // fractional part + const int v0 = kLinearToGammaTab[tab_pos]; + const int v1 = kLinearToGammaTab[tab_pos + 1]; + const int y = v1 * x + v0 * ((kGammaTabScale << 2) - x); // interpolate + assert(tab_pos + 1 < GAMMA_TAB_SIZE + 1); + return y; +} + +// Convert a linear value 'v' to YUV_FIX+2 fixed-point precision +// U/V value, suitable for RGBToU/V calls. +static WEBP_INLINE int LinearToGamma(uint32_t base_value, int shift) { + const int y = Interpolate(base_value << shift); // final uplifted value + return (y + kGammaTabRounder) >> GAMMA_TAB_FIX; // descale +} + +#else + +static void InitGammaTables(void) {} +static WEBP_INLINE uint32_t GammaToLinear(uint8_t v) { return v; } +static WEBP_INLINE int LinearToGamma(uint32_t base_value, int shift) { + return (int)(base_value << shift); +} + +#endif // USE_GAMMA_COMPRESSION + +//------------------------------------------------------------------------------ +// RGB -> YUV conversion + +static int RGBToY(int r, int g, int b, VP8Random* const rg) { + return (rg == NULL) ? VP8RGBToY(r, g, b, YUV_HALF) + : VP8RGBToY(r, g, b, VP8RandomBits(rg, YUV_FIX)); +} + +static int RGBToU(int r, int g, int b, VP8Random* const rg) { + return (rg == NULL) ? VP8RGBToU(r, g, b, YUV_HALF << 2) + : VP8RGBToU(r, g, b, VP8RandomBits(rg, YUV_FIX + 2)); +} + +static int RGBToV(int r, int g, int b, VP8Random* const rg) { + return (rg == NULL) ? VP8RGBToV(r, g, b, YUV_HALF << 2) + : VP8RGBToV(r, g, b, VP8RandomBits(rg, YUV_FIX + 2)); +} + +//------------------------------------------------------------------------------ +// Sharp RGB->YUV conversion + +static const int kMinDimensionIterativeConversion = 4; + +//------------------------------------------------------------------------------ +// Main function + +static int PreprocessARGB(const uint8_t* r_ptr, + const uint8_t* g_ptr, + const uint8_t* b_ptr, + int step, int rgb_stride, + WebPPicture* const picture) { + const int ok = SharpYuvConvert( + r_ptr, g_ptr, b_ptr, step, rgb_stride, /*rgb_bit_depth=*/8, + picture->y, picture->y_stride, picture->u, picture->uv_stride, picture->v, + picture->uv_stride, /*yuv_bit_depth=*/8, picture->width, + picture->height, SharpYuvGetConversionMatrix(kSharpYuvMatrixWebp)); + if (!ok) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + return ok; +} + +//------------------------------------------------------------------------------ +// "Fast" regular RGB->YUV + +#define SUM4(ptr, step) LinearToGamma( \ + GammaToLinear((ptr)[0]) + \ + GammaToLinear((ptr)[(step)]) + \ + GammaToLinear((ptr)[rgb_stride]) + \ + GammaToLinear((ptr)[rgb_stride + (step)]), 0) \ + +#define SUM2(ptr) \ + LinearToGamma(GammaToLinear((ptr)[0]) + GammaToLinear((ptr)[rgb_stride]), 1) + +#define SUM2ALPHA(ptr) ((ptr)[0] + (ptr)[rgb_stride]) +#define SUM4ALPHA(ptr) (SUM2ALPHA(ptr) + SUM2ALPHA((ptr) + 4)) + +#if defined(USE_INVERSE_ALPHA_TABLE) + +static const int kAlphaFix = 19; +// Following table is (1 << kAlphaFix) / a. The (v * kInvAlpha[a]) >> kAlphaFix +// formula is then equal to v / a in most (99.6%) cases. Note that this table +// and constant are adjusted very tightly to fit 32b arithmetic. +// In particular, they use the fact that the operands for 'v / a' are actually +// derived as v = (a0.p0 + a1.p1 + a2.p2 + a3.p3) and a = a0 + a1 + a2 + a3 +// with ai in [0..255] and pi in [0..1<> (kAlphaFix - 2)) + +#else + +#define DIVIDE_BY_ALPHA(sum, a) (4 * (sum) / (a)) + +#endif // USE_INVERSE_ALPHA_TABLE + +static WEBP_INLINE int LinearToGammaWeighted(const uint8_t* src, + const uint8_t* a_ptr, + uint32_t total_a, int step, + int rgb_stride) { + const uint32_t sum = + a_ptr[0] * GammaToLinear(src[0]) + + a_ptr[step] * GammaToLinear(src[step]) + + a_ptr[rgb_stride] * GammaToLinear(src[rgb_stride]) + + a_ptr[rgb_stride + step] * GammaToLinear(src[rgb_stride + step]); + assert(total_a > 0 && total_a <= 4 * 0xff); +#if defined(USE_INVERSE_ALPHA_TABLE) + assert((uint64_t)sum * kInvAlpha[total_a] < ((uint64_t)1 << 32)); +#endif + return LinearToGamma(DIVIDE_BY_ALPHA(sum, total_a), 0); +} + +static WEBP_INLINE void ConvertRowToY(const uint8_t* const r_ptr, + const uint8_t* const g_ptr, + const uint8_t* const b_ptr, + int step, + uint8_t* const dst_y, + int width, + VP8Random* const rg) { + int i, j; + for (i = 0, j = 0; i < width; i += 1, j += step) { + dst_y[i] = RGBToY(r_ptr[j], g_ptr[j], b_ptr[j], rg); + } +} + +static WEBP_INLINE void AccumulateRGBA(const uint8_t* const r_ptr, + const uint8_t* const g_ptr, + const uint8_t* const b_ptr, + const uint8_t* const a_ptr, + int rgb_stride, + uint16_t* dst, int width) { + int i, j; + // we loop over 2x2 blocks and produce one R/G/B/A value for each. + for (i = 0, j = 0; i < (width >> 1); i += 1, j += 2 * 4, dst += 4) { + const uint32_t a = SUM4ALPHA(a_ptr + j); + int r, g, b; + if (a == 4 * 0xff || a == 0) { + r = SUM4(r_ptr + j, 4); + g = SUM4(g_ptr + j, 4); + b = SUM4(b_ptr + j, 4); + } else { + r = LinearToGammaWeighted(r_ptr + j, a_ptr + j, a, 4, rgb_stride); + g = LinearToGammaWeighted(g_ptr + j, a_ptr + j, a, 4, rgb_stride); + b = LinearToGammaWeighted(b_ptr + j, a_ptr + j, a, 4, rgb_stride); + } + dst[0] = r; + dst[1] = g; + dst[2] = b; + dst[3] = a; + } + if (width & 1) { + const uint32_t a = 2u * SUM2ALPHA(a_ptr + j); + int r, g, b; + if (a == 4 * 0xff || a == 0) { + r = SUM2(r_ptr + j); + g = SUM2(g_ptr + j); + b = SUM2(b_ptr + j); + } else { + r = LinearToGammaWeighted(r_ptr + j, a_ptr + j, a, 0, rgb_stride); + g = LinearToGammaWeighted(g_ptr + j, a_ptr + j, a, 0, rgb_stride); + b = LinearToGammaWeighted(b_ptr + j, a_ptr + j, a, 0, rgb_stride); + } + dst[0] = r; + dst[1] = g; + dst[2] = b; + dst[3] = a; + } +} + +static WEBP_INLINE void AccumulateRGB(const uint8_t* const r_ptr, + const uint8_t* const g_ptr, + const uint8_t* const b_ptr, + int step, int rgb_stride, + uint16_t* dst, int width) { + int i, j; + for (i = 0, j = 0; i < (width >> 1); i += 1, j += 2 * step, dst += 4) { + dst[0] = SUM4(r_ptr + j, step); + dst[1] = SUM4(g_ptr + j, step); + dst[2] = SUM4(b_ptr + j, step); + // MemorySanitizer may raise false positives with data that passes through + // RGBA32PackedToPlanar_16b_SSE41() due to incorrect modeling of shuffles. + // See https://crbug.com/webp/573. +#ifdef WEBP_MSAN + dst[3] = 0; +#endif + } + if (width & 1) { + dst[0] = SUM2(r_ptr + j); + dst[1] = SUM2(g_ptr + j); + dst[2] = SUM2(b_ptr + j); +#ifdef WEBP_MSAN + dst[3] = 0; +#endif + } +} + +static WEBP_INLINE void ConvertRowsToUV(const uint16_t* rgb, + uint8_t* const dst_u, + uint8_t* const dst_v, + int width, + VP8Random* const rg) { + int i; + for (i = 0; i < width; i += 1, rgb += 4) { + const int r = rgb[0], g = rgb[1], b = rgb[2]; + dst_u[i] = RGBToU(r, g, b, rg); + dst_v[i] = RGBToV(r, g, b, rg); + } +} + +extern void SharpYuvInit(VP8CPUInfo cpu_info_func); + +static int ImportYUVAFromRGBA(const uint8_t* r_ptr, + const uint8_t* g_ptr, + const uint8_t* b_ptr, + const uint8_t* a_ptr, + int step, // bytes per pixel + int rgb_stride, // bytes per scanline + float dithering, + int use_iterative_conversion, + WebPPicture* const picture) { + int y; + const int width = picture->width; + const int height = picture->height; + const int has_alpha = CheckNonOpaque(a_ptr, width, height, step, rgb_stride); + const int is_rgb = (r_ptr < b_ptr); // otherwise it's bgr + + picture->colorspace = has_alpha ? WEBP_YUV420A : WEBP_YUV420; + picture->use_argb = 0; + + // disable smart conversion if source is too small (overkill). + if (width < kMinDimensionIterativeConversion || + height < kMinDimensionIterativeConversion) { + use_iterative_conversion = 0; + } + + if (!WebPPictureAllocYUVA(picture)) { + return 0; + } + if (has_alpha) { + assert(step == 4); +#if defined(USE_GAMMA_COMPRESSION) && defined(USE_INVERSE_ALPHA_TABLE) + assert(kAlphaFix + GAMMA_FIX <= 31); +#endif + } + + if (use_iterative_conversion) { + SharpYuvInit(VP8GetCPUInfo); + if (!PreprocessARGB(r_ptr, g_ptr, b_ptr, step, rgb_stride, picture)) { + return 0; + } + if (has_alpha) { + WebPExtractAlpha(a_ptr, rgb_stride, width, height, + picture->a, picture->a_stride); + } + } else { + const int uv_width = (width + 1) >> 1; + int use_dsp = (step == 3); // use special function in this case + // temporary storage for accumulated R/G/B values during conversion to U/V + uint16_t* const tmp_rgb = + (uint16_t*)WebPSafeMalloc(4 * uv_width, sizeof(*tmp_rgb)); + uint8_t* dst_y = picture->y; + uint8_t* dst_u = picture->u; + uint8_t* dst_v = picture->v; + uint8_t* dst_a = picture->a; + + VP8Random base_rg; + VP8Random* rg = NULL; + if (dithering > 0.) { + VP8InitRandom(&base_rg, dithering); + rg = &base_rg; + use_dsp = 0; // can't use dsp in this case + } + WebPInitConvertARGBToYUV(); + InitGammaTables(); + + if (tmp_rgb == NULL) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + + // Downsample Y/U/V planes, two rows at a time + for (y = 0; y < (height >> 1); ++y) { + int rows_have_alpha = has_alpha; + if (use_dsp) { + if (is_rgb) { + WebPConvertRGB24ToY(r_ptr, dst_y, width); + WebPConvertRGB24ToY(r_ptr + rgb_stride, + dst_y + picture->y_stride, width); + } else { + WebPConvertBGR24ToY(b_ptr, dst_y, width); + WebPConvertBGR24ToY(b_ptr + rgb_stride, + dst_y + picture->y_stride, width); + } + } else { + ConvertRowToY(r_ptr, g_ptr, b_ptr, step, dst_y, width, rg); + ConvertRowToY(r_ptr + rgb_stride, + g_ptr + rgb_stride, + b_ptr + rgb_stride, step, + dst_y + picture->y_stride, width, rg); + } + dst_y += 2 * picture->y_stride; + if (has_alpha) { + rows_have_alpha &= !WebPExtractAlpha(a_ptr, rgb_stride, width, 2, + dst_a, picture->a_stride); + dst_a += 2 * picture->a_stride; + } + // Collect averaged R/G/B(/A) + if (!rows_have_alpha) { + AccumulateRGB(r_ptr, g_ptr, b_ptr, step, rgb_stride, tmp_rgb, width); + } else { + AccumulateRGBA(r_ptr, g_ptr, b_ptr, a_ptr, rgb_stride, tmp_rgb, width); + } + // Convert to U/V + if (rg == NULL) { + WebPConvertRGBA32ToUV(tmp_rgb, dst_u, dst_v, uv_width); + } else { + ConvertRowsToUV(tmp_rgb, dst_u, dst_v, uv_width, rg); + } + dst_u += picture->uv_stride; + dst_v += picture->uv_stride; + r_ptr += 2 * rgb_stride; + b_ptr += 2 * rgb_stride; + g_ptr += 2 * rgb_stride; + if (has_alpha) a_ptr += 2 * rgb_stride; + } + if (height & 1) { // extra last row + int row_has_alpha = has_alpha; + if (use_dsp) { + if (r_ptr < b_ptr) { + WebPConvertRGB24ToY(r_ptr, dst_y, width); + } else { + WebPConvertBGR24ToY(b_ptr, dst_y, width); + } + } else { + ConvertRowToY(r_ptr, g_ptr, b_ptr, step, dst_y, width, rg); + } + if (row_has_alpha) { + row_has_alpha &= !WebPExtractAlpha(a_ptr, 0, width, 1, dst_a, 0); + } + // Collect averaged R/G/B(/A) + if (!row_has_alpha) { + // Collect averaged R/G/B + AccumulateRGB(r_ptr, g_ptr, b_ptr, step, /* rgb_stride = */ 0, + tmp_rgb, width); + } else { + AccumulateRGBA(r_ptr, g_ptr, b_ptr, a_ptr, /* rgb_stride = */ 0, + tmp_rgb, width); + } + if (rg == NULL) { + WebPConvertRGBA32ToUV(tmp_rgb, dst_u, dst_v, uv_width); + } else { + ConvertRowsToUV(tmp_rgb, dst_u, dst_v, uv_width, rg); + } + } + WebPSafeFree(tmp_rgb); + } + return 1; +} + +#undef SUM4 +#undef SUM2 +#undef SUM4ALPHA +#undef SUM2ALPHA + +//------------------------------------------------------------------------------ +// call for ARGB->YUVA conversion + +static int PictureARGBToYUVA(WebPPicture* picture, WebPEncCSP colorspace, + float dithering, int use_iterative_conversion) { + if (picture == NULL) return 0; + if (picture->argb == NULL) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER); + } else if ((colorspace & WEBP_CSP_UV_MASK) != WEBP_YUV420) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION); + } else { + const uint8_t* const argb = (const uint8_t*)picture->argb; + const uint8_t* const a = argb + CHANNEL_OFFSET(0); + const uint8_t* const r = argb + CHANNEL_OFFSET(1); + const uint8_t* const g = argb + CHANNEL_OFFSET(2); + const uint8_t* const b = argb + CHANNEL_OFFSET(3); + + picture->colorspace = WEBP_YUV420; + return ImportYUVAFromRGBA(r, g, b, a, 4, 4 * picture->argb_stride, + dithering, use_iterative_conversion, picture); + } +} + +int WebPPictureARGBToYUVADithered(WebPPicture* picture, WebPEncCSP colorspace, + float dithering) { + return PictureARGBToYUVA(picture, colorspace, dithering, 0); +} + +int WebPPictureARGBToYUVA(WebPPicture* picture, WebPEncCSP colorspace) { + return PictureARGBToYUVA(picture, colorspace, 0.f, 0); +} + +int WebPPictureSharpARGBToYUVA(WebPPicture* picture) { + return PictureARGBToYUVA(picture, WEBP_YUV420, 0.f, 1); +} +// for backward compatibility +int WebPPictureSmartARGBToYUVA(WebPPicture* picture) { + return WebPPictureSharpARGBToYUVA(picture); +} + +//------------------------------------------------------------------------------ +// call for YUVA -> ARGB conversion + +int WebPPictureYUVAToARGB(WebPPicture* picture) { + if (picture == NULL) return 0; + if (picture->y == NULL || picture->u == NULL || picture->v == NULL) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER); + } + if ((picture->colorspace & WEBP_CSP_ALPHA_BIT) && picture->a == NULL) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER); + } + if ((picture->colorspace & WEBP_CSP_UV_MASK) != WEBP_YUV420) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION); + } + // Allocate a new argb buffer (discarding the previous one). + if (!WebPPictureAllocARGB(picture)) return 0; + picture->use_argb = 1; + + // Convert + { + int y; + const int width = picture->width; + const int height = picture->height; + const int argb_stride = 4 * picture->argb_stride; + uint8_t* dst = (uint8_t*)picture->argb; + const uint8_t* cur_u = picture->u, *cur_v = picture->v, *cur_y = picture->y; + WebPUpsampleLinePairFunc upsample = + WebPGetLinePairConverter(ALPHA_OFFSET > 0); + + // First row, with replicated top samples. + upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, width); + cur_y += picture->y_stride; + dst += argb_stride; + // Center rows. + for (y = 1; y + 1 < height; y += 2) { + const uint8_t* const top_u = cur_u; + const uint8_t* const top_v = cur_v; + cur_u += picture->uv_stride; + cur_v += picture->uv_stride; + upsample(cur_y, cur_y + picture->y_stride, top_u, top_v, cur_u, cur_v, + dst, dst + argb_stride, width); + cur_y += 2 * picture->y_stride; + dst += 2 * argb_stride; + } + // Last row (if needed), with replicated bottom samples. + if (height > 1 && !(height & 1)) { + upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, width); + } + // Insert alpha values if needed, in replacement for the default 0xff ones. + if (picture->colorspace & WEBP_CSP_ALPHA_BIT) { + for (y = 0; y < height; ++y) { + uint32_t* const argb_dst = picture->argb + y * picture->argb_stride; + const uint8_t* const src = picture->a + y * picture->a_stride; + int x; + for (x = 0; x < width; ++x) { + argb_dst[x] = (argb_dst[x] & 0x00ffffffu) | ((uint32_t)src[x] << 24); + } + } + } + } + return 1; +} + +//------------------------------------------------------------------------------ +// automatic import / conversion + +static int Import(WebPPicture* const picture, + const uint8_t* rgb, int rgb_stride, + int step, int swap_rb, int import_alpha) { + int y; + // swap_rb -> b,g,r,a , !swap_rb -> r,g,b,a + const uint8_t* r_ptr = rgb + (swap_rb ? 2 : 0); + const uint8_t* g_ptr = rgb + 1; + const uint8_t* b_ptr = rgb + (swap_rb ? 0 : 2); + const int width = picture->width; + const int height = picture->height; + + if (abs(rgb_stride) < (import_alpha ? 4 : 3) * width) return 0; + + if (!picture->use_argb) { + const uint8_t* a_ptr = import_alpha ? rgb + 3 : NULL; + return ImportYUVAFromRGBA(r_ptr, g_ptr, b_ptr, a_ptr, step, rgb_stride, + 0.f /* no dithering */, 0, picture); + } + if (!WebPPictureAlloc(picture)) return 0; + + VP8LDspInit(); + WebPInitAlphaProcessing(); + + if (import_alpha) { + // dst[] byte order is {a,r,g,b} for big-endian, {b,g,r,a} for little endian + uint32_t* dst = picture->argb; + const int do_copy = (ALPHA_OFFSET == 3) && swap_rb; + assert(step == 4); + if (do_copy) { + for (y = 0; y < height; ++y) { + memcpy(dst, rgb, width * 4); + rgb += rgb_stride; + dst += picture->argb_stride; + } + } else { + for (y = 0; y < height; ++y) { +#ifdef WORDS_BIGENDIAN + // BGRA or RGBA input order. + const uint8_t* a_ptr = rgb + 3; + WebPPackARGB(a_ptr, r_ptr, g_ptr, b_ptr, width, dst); + r_ptr += rgb_stride; + g_ptr += rgb_stride; + b_ptr += rgb_stride; +#else + // RGBA input order. Need to swap R and B. + VP8LConvertBGRAToRGBA((const uint32_t*)rgb, width, (uint8_t*)dst); +#endif + rgb += rgb_stride; + dst += picture->argb_stride; + } + } + } else { + uint32_t* dst = picture->argb; + assert(step >= 3); + for (y = 0; y < height; ++y) { + WebPPackRGB(r_ptr, g_ptr, b_ptr, width, step, dst); + r_ptr += rgb_stride; + g_ptr += rgb_stride; + b_ptr += rgb_stride; + dst += picture->argb_stride; + } + } + return 1; +} + +// Public API + +#if !defined(WEBP_REDUCE_CSP) + +int WebPPictureImportBGR(WebPPicture* picture, + const uint8_t* bgr, int bgr_stride) { + return (picture != NULL && bgr != NULL) + ? Import(picture, bgr, bgr_stride, 3, 1, 0) + : 0; +} + +int WebPPictureImportBGRA(WebPPicture* picture, + const uint8_t* bgra, int bgra_stride) { + return (picture != NULL && bgra != NULL) + ? Import(picture, bgra, bgra_stride, 4, 1, 1) + : 0; +} + + +int WebPPictureImportBGRX(WebPPicture* picture, + const uint8_t* bgrx, int bgrx_stride) { + return (picture != NULL && bgrx != NULL) + ? Import(picture, bgrx, bgrx_stride, 4, 1, 0) + : 0; +} + +#endif // WEBP_REDUCE_CSP + +int WebPPictureImportRGB(WebPPicture* picture, + const uint8_t* rgb, int rgb_stride) { + return (picture != NULL && rgb != NULL) + ? Import(picture, rgb, rgb_stride, 3, 0, 0) + : 0; +} + +int WebPPictureImportRGBA(WebPPicture* picture, + const uint8_t* rgba, int rgba_stride) { + return (picture != NULL && rgba != NULL) + ? Import(picture, rgba, rgba_stride, 4, 0, 1) + : 0; +} + +int WebPPictureImportRGBX(WebPPicture* picture, + const uint8_t* rgbx, int rgbx_stride) { + return (picture != NULL && rgbx != NULL) + ? Import(picture, rgbx, rgbx_stride, 4, 0, 0) + : 0; +} + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/src/enc/picture_enc.c b/third-party/webp/libwebp/src/enc/picture_enc.c new file mode 100644 index 0000000000..5a2703541f --- /dev/null +++ b/third-party/webp/libwebp/src/enc/picture_enc.c @@ -0,0 +1,304 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// WebPPicture class basis +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include +#include + +#include "src/enc/vp8i_enc.h" +#include "src/utils/utils.h" + +//------------------------------------------------------------------------------ +// WebPPicture +//------------------------------------------------------------------------------ + +static int DummyWriter(const uint8_t* data, size_t data_size, + const WebPPicture* const picture) { + // The following are to prevent 'unused variable' error message. + (void)data; + (void)data_size; + (void)picture; + return 1; +} + +int WebPPictureInitInternal(WebPPicture* picture, int version) { + if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_ENCODER_ABI_VERSION)) { + return 0; // caller/system version mismatch! + } + if (picture != NULL) { + memset(picture, 0, sizeof(*picture)); + picture->writer = DummyWriter; + WebPEncodingSetError(picture, VP8_ENC_OK); + } + return 1; +} + +//------------------------------------------------------------------------------ + +int WebPValidatePicture(const WebPPicture* const picture) { + if (picture == NULL) return 0; + if (picture->width <= 0 || picture->height <= 0) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION); + } + if (picture->width <= 0 || picture->width / 4 > INT_MAX / 4 || + picture->height <= 0 || picture->height / 4 > INT_MAX / 4) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION); + } + if (picture->colorspace != WEBP_YUV420 && + picture->colorspace != WEBP_YUV420A) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION); + } + return 1; +} + +static void WebPPictureResetBufferARGB(WebPPicture* const picture) { + picture->memory_argb_ = NULL; + picture->argb = NULL; + picture->argb_stride = 0; +} + +static void WebPPictureResetBufferYUVA(WebPPicture* const picture) { + picture->memory_ = NULL; + picture->y = picture->u = picture->v = picture->a = NULL; + picture->y_stride = picture->uv_stride = 0; + picture->a_stride = 0; +} + +void WebPPictureResetBuffers(WebPPicture* const picture) { + WebPPictureResetBufferARGB(picture); + WebPPictureResetBufferYUVA(picture); +} + +int WebPPictureAllocARGB(WebPPicture* const picture) { + void* memory; + const int width = picture->width; + const int height = picture->height; + const uint64_t argb_size = (uint64_t)width * height; + + if (!WebPValidatePicture(picture)) return 0; + + WebPSafeFree(picture->memory_argb_); + WebPPictureResetBufferARGB(picture); + + // allocate a new buffer. + memory = WebPSafeMalloc(argb_size + WEBP_ALIGN_CST, sizeof(*picture->argb)); + if (memory == NULL) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + picture->memory_argb_ = memory; + picture->argb = (uint32_t*)WEBP_ALIGN(memory); + picture->argb_stride = width; + return 1; +} + +int WebPPictureAllocYUVA(WebPPicture* const picture) { + const int has_alpha = (int)picture->colorspace & WEBP_CSP_ALPHA_BIT; + const int width = picture->width; + const int height = picture->height; + const int y_stride = width; + const int uv_width = (int)(((int64_t)width + 1) >> 1); + const int uv_height = (int)(((int64_t)height + 1) >> 1); + const int uv_stride = uv_width; + int a_width, a_stride; + uint64_t y_size, uv_size, a_size, total_size; + uint8_t* mem; + + if (!WebPValidatePicture(picture)) return 0; + + WebPSafeFree(picture->memory_); + WebPPictureResetBufferYUVA(picture); + + // alpha + a_width = has_alpha ? width : 0; + a_stride = a_width; + y_size = (uint64_t)y_stride * height; + uv_size = (uint64_t)uv_stride * uv_height; + a_size = (uint64_t)a_stride * height; + + total_size = y_size + a_size + 2 * uv_size; + + // Security and validation checks + if (width <= 0 || height <= 0 || // luma/alpha param error + uv_width <= 0 || uv_height <= 0) { // u/v param error + return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION); + } + // allocate a new buffer. + mem = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*mem)); + if (mem == NULL) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + + // From now on, we're in the clear, we can no longer fail... + picture->memory_ = (void*)mem; + picture->y_stride = y_stride; + picture->uv_stride = uv_stride; + picture->a_stride = a_stride; + + // TODO(skal): we could align the y/u/v planes and adjust stride. + picture->y = mem; + mem += y_size; + + picture->u = mem; + mem += uv_size; + picture->v = mem; + mem += uv_size; + + if (a_size > 0) { + picture->a = mem; + mem += a_size; + } + (void)mem; // makes the static analyzer happy + return 1; +} + +int WebPPictureAlloc(WebPPicture* picture) { + if (picture != NULL) { + WebPPictureFree(picture); // erase previous buffer + + if (!picture->use_argb) { + return WebPPictureAllocYUVA(picture); + } else { + return WebPPictureAllocARGB(picture); + } + } + return 1; +} + +void WebPPictureFree(WebPPicture* picture) { + if (picture != NULL) { + WebPSafeFree(picture->memory_); + WebPSafeFree(picture->memory_argb_); + WebPPictureResetBuffers(picture); + } +} + +//------------------------------------------------------------------------------ +// WebPMemoryWriter: Write-to-memory + +void WebPMemoryWriterInit(WebPMemoryWriter* writer) { + writer->mem = NULL; + writer->size = 0; + writer->max_size = 0; +} + +int WebPMemoryWrite(const uint8_t* data, size_t data_size, + const WebPPicture* picture) { + WebPMemoryWriter* const w = (WebPMemoryWriter*)picture->custom_ptr; + uint64_t next_size; + if (w == NULL) { + return 1; + } + next_size = (uint64_t)w->size + data_size; + if (next_size > w->max_size) { + uint8_t* new_mem; + uint64_t next_max_size = 2ULL * w->max_size; + if (next_max_size < next_size) next_max_size = next_size; + if (next_max_size < 8192ULL) next_max_size = 8192ULL; + new_mem = (uint8_t*)WebPSafeMalloc(next_max_size, 1); + if (new_mem == NULL) { + return 0; + } + if (w->size > 0) { + memcpy(new_mem, w->mem, w->size); + } + WebPSafeFree(w->mem); + w->mem = new_mem; + // down-cast is ok, thanks to WebPSafeMalloc + w->max_size = (size_t)next_max_size; + } + if (data_size > 0) { + memcpy(w->mem + w->size, data, data_size); + w->size += data_size; + } + return 1; +} + +void WebPMemoryWriterClear(WebPMemoryWriter* writer) { + if (writer != NULL) { + WebPSafeFree(writer->mem); + writer->mem = NULL; + writer->size = 0; + writer->max_size = 0; + } +} + +//------------------------------------------------------------------------------ +// Simplest high-level calls: + +typedef int (*Importer)(WebPPicture* const, const uint8_t* const, int); + +static size_t Encode(const uint8_t* rgba, int width, int height, int stride, + Importer import, float quality_factor, int lossless, + uint8_t** output) { + WebPPicture pic; + WebPConfig config; + WebPMemoryWriter wrt; + int ok; + + if (output == NULL) return 0; + + if (!WebPConfigPreset(&config, WEBP_PRESET_DEFAULT, quality_factor) || + !WebPPictureInit(&pic)) { + return 0; // shouldn't happen, except if system installation is broken + } + + config.lossless = !!lossless; + pic.use_argb = !!lossless; + pic.width = width; + pic.height = height; + pic.writer = WebPMemoryWrite; + pic.custom_ptr = &wrt; + WebPMemoryWriterInit(&wrt); + + ok = import(&pic, rgba, stride) && WebPEncode(&config, &pic); + WebPPictureFree(&pic); + if (!ok) { + WebPMemoryWriterClear(&wrt); + *output = NULL; + return 0; + } + *output = wrt.mem; + return wrt.size; +} + +#define ENCODE_FUNC(NAME, IMPORTER) \ +size_t NAME(const uint8_t* in, int w, int h, int bps, float q, \ + uint8_t** out) { \ + return Encode(in, w, h, bps, IMPORTER, q, 0, out); \ +} + +ENCODE_FUNC(WebPEncodeRGB, WebPPictureImportRGB) +ENCODE_FUNC(WebPEncodeRGBA, WebPPictureImportRGBA) +#if !defined(WEBP_REDUCE_CSP) +ENCODE_FUNC(WebPEncodeBGR, WebPPictureImportBGR) +ENCODE_FUNC(WebPEncodeBGRA, WebPPictureImportBGRA) +#endif // WEBP_REDUCE_CSP + +#undef ENCODE_FUNC + +#define LOSSLESS_DEFAULT_QUALITY 70. +#define LOSSLESS_ENCODE_FUNC(NAME, IMPORTER) \ +size_t NAME(const uint8_t* in, int w, int h, int bps, uint8_t** out) { \ + return Encode(in, w, h, bps, IMPORTER, LOSSLESS_DEFAULT_QUALITY, 1, out); \ +} + +LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessRGB, WebPPictureImportRGB) +LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessRGBA, WebPPictureImportRGBA) +#if !defined(WEBP_REDUCE_CSP) +LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessBGR, WebPPictureImportBGR) +LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessBGRA, WebPPictureImportBGRA) +#endif // WEBP_REDUCE_CSP + +#undef LOSSLESS_ENCODE_FUNC + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/src/enc/picture_psnr_enc.c b/third-party/webp/libwebp/src/enc/picture_psnr_enc.c new file mode 100644 index 0000000000..1a2f0bef3e --- /dev/null +++ b/third-party/webp/libwebp/src/enc/picture_psnr_enc.c @@ -0,0 +1,258 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// WebPPicture tools for measuring distortion +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/webp/encode.h" + +#if !(defined(WEBP_DISABLE_STATS) || defined(WEBP_REDUCE_SIZE)) + +#include +#include + +#include "src/dsp/dsp.h" +#include "src/enc/vp8i_enc.h" +#include "src/utils/utils.h" + +typedef double (*AccumulateFunc)(const uint8_t* src, int src_stride, + const uint8_t* ref, int ref_stride, + int w, int h); + +//------------------------------------------------------------------------------ +// local-min distortion +// +// For every pixel in the *reference* picture, we search for the local best +// match in the compressed image. This is not a symmetrical measure. + +#define RADIUS 2 // search radius. Shouldn't be too large. + +static double AccumulateLSIM(const uint8_t* src, int src_stride, + const uint8_t* ref, int ref_stride, + int w, int h) { + int x, y; + double total_sse = 0.; + for (y = 0; y < h; ++y) { + const int y_0 = (y - RADIUS < 0) ? 0 : y - RADIUS; + const int y_1 = (y + RADIUS + 1 >= h) ? h : y + RADIUS + 1; + for (x = 0; x < w; ++x) { + const int x_0 = (x - RADIUS < 0) ? 0 : x - RADIUS; + const int x_1 = (x + RADIUS + 1 >= w) ? w : x + RADIUS + 1; + double best_sse = 255. * 255.; + const double value = (double)ref[y * ref_stride + x]; + int i, j; + for (j = y_0; j < y_1; ++j) { + const uint8_t* const s = src + j * src_stride; + for (i = x_0; i < x_1; ++i) { + const double diff = s[i] - value; + const double sse = diff * diff; + if (sse < best_sse) best_sse = sse; + } + } + total_sse += best_sse; + } + } + return total_sse; +} +#undef RADIUS + +static double AccumulateSSE(const uint8_t* src, int src_stride, + const uint8_t* ref, int ref_stride, + int w, int h) { + int y; + double total_sse = 0.; + for (y = 0; y < h; ++y) { + total_sse += VP8AccumulateSSE(src, ref, w); + src += src_stride; + ref += ref_stride; + } + return total_sse; +} + +//------------------------------------------------------------------------------ + +static double AccumulateSSIM(const uint8_t* src, int src_stride, + const uint8_t* ref, int ref_stride, + int w, int h) { + const int w0 = (w < VP8_SSIM_KERNEL) ? w : VP8_SSIM_KERNEL; + const int w1 = w - VP8_SSIM_KERNEL - 1; + const int h0 = (h < VP8_SSIM_KERNEL) ? h : VP8_SSIM_KERNEL; + const int h1 = h - VP8_SSIM_KERNEL - 1; + int x, y; + double sum = 0.; + for (y = 0; y < h0; ++y) { + for (x = 0; x < w; ++x) { + sum += VP8SSIMGetClipped(src, src_stride, ref, ref_stride, x, y, w, h); + } + } + for (; y < h1; ++y) { + for (x = 0; x < w0; ++x) { + sum += VP8SSIMGetClipped(src, src_stride, ref, ref_stride, x, y, w, h); + } + for (; x < w1; ++x) { + const int off1 = x - VP8_SSIM_KERNEL + (y - VP8_SSIM_KERNEL) * src_stride; + const int off2 = x - VP8_SSIM_KERNEL + (y - VP8_SSIM_KERNEL) * ref_stride; + sum += VP8SSIMGet(src + off1, src_stride, ref + off2, ref_stride); + } + for (; x < w; ++x) { + sum += VP8SSIMGetClipped(src, src_stride, ref, ref_stride, x, y, w, h); + } + } + for (; y < h; ++y) { + for (x = 0; x < w; ++x) { + sum += VP8SSIMGetClipped(src, src_stride, ref, ref_stride, x, y, w, h); + } + } + return sum; +} + +//------------------------------------------------------------------------------ +// Distortion + +// Max value returned in case of exact similarity. +static const double kMinDistortion_dB = 99.; + +static double GetPSNR(double v, double size) { + return (v > 0. && size > 0.) ? -4.3429448 * log(v / (size * 255 * 255.)) + : kMinDistortion_dB; +} + +static double GetLogSSIM(double v, double size) { + v = (size > 0.) ? v / size : 1.; + return (v < 1.) ? -10.0 * log10(1. - v) : kMinDistortion_dB; +} + +int WebPPlaneDistortion(const uint8_t* src, size_t src_stride, + const uint8_t* ref, size_t ref_stride, + int width, int height, size_t x_step, + int type, float* distortion, float* result) { + uint8_t* allocated = NULL; + const AccumulateFunc metric = (type == 0) ? AccumulateSSE : + (type == 1) ? AccumulateSSIM : + AccumulateLSIM; + if (src == NULL || ref == NULL || + src_stride < x_step * width || ref_stride < x_step * width || + result == NULL || distortion == NULL) { + return 0; + } + + VP8SSIMDspInit(); + if (x_step != 1) { // extract a packed plane if needed + int x, y; + uint8_t* tmp1; + uint8_t* tmp2; + allocated = + (uint8_t*)WebPSafeMalloc(2ULL * width * height, sizeof(*allocated)); + if (allocated == NULL) return 0; + tmp1 = allocated; + tmp2 = tmp1 + (size_t)width * height; + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + tmp1[x + y * width] = src[x * x_step + y * src_stride]; + tmp2[x + y * width] = ref[x * x_step + y * ref_stride]; + } + } + src = tmp1; + ref = tmp2; + } + *distortion = (float)metric(src, width, ref, width, width, height); + WebPSafeFree(allocated); + + *result = (type == 1) ? (float)GetLogSSIM(*distortion, (double)width * height) + : (float)GetPSNR(*distortion, (double)width * height); + return 1; +} + +#ifdef WORDS_BIGENDIAN +#define BLUE_OFFSET 3 // uint32_t 0x000000ff is 0x00,00,00,ff in memory +#else +#define BLUE_OFFSET 0 // uint32_t 0x000000ff is 0xff,00,00,00 in memory +#endif + +int WebPPictureDistortion(const WebPPicture* src, const WebPPicture* ref, + int type, float results[5]) { + int w, h, c; + int ok = 0; + WebPPicture p0, p1; + double total_size = 0., total_distortion = 0.; + if (src == NULL || ref == NULL || + src->width != ref->width || src->height != ref->height || + results == NULL) { + return 0; + } + + VP8SSIMDspInit(); + if (!WebPPictureInit(&p0) || !WebPPictureInit(&p1)) return 0; + w = src->width; + h = src->height; + if (!WebPPictureView(src, 0, 0, w, h, &p0)) goto Error; + if (!WebPPictureView(ref, 0, 0, w, h, &p1)) goto Error; + + // We always measure distortion in ARGB space. + if (p0.use_argb == 0 && !WebPPictureYUVAToARGB(&p0)) goto Error; + if (p1.use_argb == 0 && !WebPPictureYUVAToARGB(&p1)) goto Error; + for (c = 0; c < 4; ++c) { + float distortion; + const size_t stride0 = 4 * (size_t)p0.argb_stride; + const size_t stride1 = 4 * (size_t)p1.argb_stride; + // results are reported as BGRA + const int offset = c ^ BLUE_OFFSET; + if (!WebPPlaneDistortion((const uint8_t*)p0.argb + offset, stride0, + (const uint8_t*)p1.argb + offset, stride1, + w, h, 4, type, &distortion, results + c)) { + goto Error; + } + total_distortion += distortion; + total_size += w * h; + } + + results[4] = (type == 1) ? (float)GetLogSSIM(total_distortion, total_size) + : (float)GetPSNR(total_distortion, total_size); + ok = 1; + + Error: + WebPPictureFree(&p0); + WebPPictureFree(&p1); + return ok; +} + +#undef BLUE_OFFSET + +#else // defined(WEBP_DISABLE_STATS) +int WebPPlaneDistortion(const uint8_t* src, size_t src_stride, + const uint8_t* ref, size_t ref_stride, + int width, int height, size_t x_step, + int type, float* distortion, float* result) { + (void)src; + (void)src_stride; + (void)ref; + (void)ref_stride; + (void)width; + (void)height; + (void)x_step; + (void)type; + if (distortion == NULL || result == NULL) return 0; + *distortion = 0.f; + *result = 0.f; + return 1; +} + +int WebPPictureDistortion(const WebPPicture* src, const WebPPicture* ref, + int type, float results[5]) { + int i; + (void)src; + (void)ref; + (void)type; + if (results == NULL) return 0; + for (i = 0; i < 5; ++i) results[i] = 0.f; + return 1; +} + +#endif // !defined(WEBP_DISABLE_STATS) diff --git a/third-party/webp/libwebp/src/enc/picture_rescale_enc.c b/third-party/webp/libwebp/src/enc/picture_rescale_enc.c new file mode 100644 index 0000000000..ea90d82548 --- /dev/null +++ b/third-party/webp/libwebp/src/enc/picture_rescale_enc.c @@ -0,0 +1,304 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// WebPPicture tools: copy, crop, rescaling and view. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/webp/encode.h" + +#include +#include + +#include "src/enc/vp8i_enc.h" + +#if !defined(WEBP_REDUCE_SIZE) +#include "src/utils/rescaler_utils.h" +#include "src/utils/utils.h" +#endif // !defined(WEBP_REDUCE_SIZE) + +#define HALVE(x) (((x) + 1) >> 1) + +// Grab the 'specs' (writer, *opaque, width, height...) from 'src' and copy them +// into 'dst'. Mark 'dst' as not owning any memory. +static void PictureGrabSpecs(const WebPPicture* const src, + WebPPicture* const dst) { + assert(src != NULL && dst != NULL); + *dst = *src; + WebPPictureResetBuffers(dst); +} + +//------------------------------------------------------------------------------ + +// Adjust top-left corner to chroma sample position. +static void SnapTopLeftPosition(const WebPPicture* const pic, + int* const left, int* const top) { + if (!pic->use_argb) { + *left &= ~1; + *top &= ~1; + } +} + +// Adjust top-left corner and verify that the sub-rectangle is valid. +static int AdjustAndCheckRectangle(const WebPPicture* const pic, + int* const left, int* const top, + int width, int height) { + SnapTopLeftPosition(pic, left, top); + if ((*left) < 0 || (*top) < 0) return 0; + if (width <= 0 || height <= 0) return 0; + if ((*left) + width > pic->width) return 0; + if ((*top) + height > pic->height) return 0; + return 1; +} + +#if !defined(WEBP_REDUCE_SIZE) +int WebPPictureCopy(const WebPPicture* src, WebPPicture* dst) { + if (src == NULL || dst == NULL) return 0; + if (src == dst) return 1; + + PictureGrabSpecs(src, dst); + if (!WebPPictureAlloc(dst)) return 0; + + if (!src->use_argb) { + WebPCopyPlane(src->y, src->y_stride, + dst->y, dst->y_stride, dst->width, dst->height); + WebPCopyPlane(src->u, src->uv_stride, dst->u, dst->uv_stride, + HALVE(dst->width), HALVE(dst->height)); + WebPCopyPlane(src->v, src->uv_stride, dst->v, dst->uv_stride, + HALVE(dst->width), HALVE(dst->height)); + if (dst->a != NULL) { + WebPCopyPlane(src->a, src->a_stride, + dst->a, dst->a_stride, dst->width, dst->height); + } + } else { + WebPCopyPlane((const uint8_t*)src->argb, 4 * src->argb_stride, + (uint8_t*)dst->argb, 4 * dst->argb_stride, + 4 * dst->width, dst->height); + } + return 1; +} +#endif // !defined(WEBP_REDUCE_SIZE) + +int WebPPictureIsView(const WebPPicture* picture) { + if (picture == NULL) return 0; + if (picture->use_argb) { + return (picture->memory_argb_ == NULL); + } + return (picture->memory_ == NULL); +} + +int WebPPictureView(const WebPPicture* src, + int left, int top, int width, int height, + WebPPicture* dst) { + if (src == NULL || dst == NULL) return 0; + + // verify rectangle position. + if (!AdjustAndCheckRectangle(src, &left, &top, width, height)) return 0; + + if (src != dst) { // beware of aliasing! We don't want to leak 'memory_'. + PictureGrabSpecs(src, dst); + } + dst->width = width; + dst->height = height; + if (!src->use_argb) { + dst->y = src->y + top * src->y_stride + left; + dst->u = src->u + (top >> 1) * src->uv_stride + (left >> 1); + dst->v = src->v + (top >> 1) * src->uv_stride + (left >> 1); + dst->y_stride = src->y_stride; + dst->uv_stride = src->uv_stride; + if (src->a != NULL) { + dst->a = src->a + top * src->a_stride + left; + dst->a_stride = src->a_stride; + } + } else { + dst->argb = src->argb + top * src->argb_stride + left; + dst->argb_stride = src->argb_stride; + } + return 1; +} + +#if !defined(WEBP_REDUCE_SIZE) +//------------------------------------------------------------------------------ +// Picture cropping + +int WebPPictureCrop(WebPPicture* pic, + int left, int top, int width, int height) { + WebPPicture tmp; + + if (pic == NULL) return 0; + if (!AdjustAndCheckRectangle(pic, &left, &top, width, height)) return 0; + + PictureGrabSpecs(pic, &tmp); + tmp.width = width; + tmp.height = height; + if (!WebPPictureAlloc(&tmp)) { + return WebPEncodingSetError(pic, tmp.error_code); + } + + if (!pic->use_argb) { + const int y_offset = top * pic->y_stride + left; + const int uv_offset = (top / 2) * pic->uv_stride + left / 2; + WebPCopyPlane(pic->y + y_offset, pic->y_stride, + tmp.y, tmp.y_stride, width, height); + WebPCopyPlane(pic->u + uv_offset, pic->uv_stride, + tmp.u, tmp.uv_stride, HALVE(width), HALVE(height)); + WebPCopyPlane(pic->v + uv_offset, pic->uv_stride, + tmp.v, tmp.uv_stride, HALVE(width), HALVE(height)); + + if (tmp.a != NULL) { + const int a_offset = top * pic->a_stride + left; + WebPCopyPlane(pic->a + a_offset, pic->a_stride, + tmp.a, tmp.a_stride, width, height); + } + } else { + const uint8_t* const src = + (const uint8_t*)(pic->argb + top * pic->argb_stride + left); + WebPCopyPlane(src, pic->argb_stride * 4, (uint8_t*)tmp.argb, + tmp.argb_stride * 4, width * 4, height); + } + WebPPictureFree(pic); + *pic = tmp; + return 1; +} + +//------------------------------------------------------------------------------ +// Simple picture rescaler + +static int RescalePlane(const uint8_t* src, + int src_width, int src_height, int src_stride, + uint8_t* dst, + int dst_width, int dst_height, int dst_stride, + rescaler_t* const work, + int num_channels) { + WebPRescaler rescaler; + int y = 0; + if (!WebPRescalerInit(&rescaler, src_width, src_height, + dst, dst_width, dst_height, dst_stride, + num_channels, work)) { + return 0; + } + while (y < src_height) { + y += WebPRescalerImport(&rescaler, src_height - y, + src + y * src_stride, src_stride); + WebPRescalerExport(&rescaler); + } + return 1; +} + +static void AlphaMultiplyARGB(WebPPicture* const pic, int inverse) { + assert(pic->argb != NULL); + WebPMultARGBRows((uint8_t*)pic->argb, pic->argb_stride * sizeof(*pic->argb), + pic->width, pic->height, inverse); +} + +static void AlphaMultiplyY(WebPPicture* const pic, int inverse) { + if (pic->a != NULL) { + WebPMultRows(pic->y, pic->y_stride, pic->a, pic->a_stride, + pic->width, pic->height, inverse); + } +} + +int WebPPictureRescale(WebPPicture* picture, int width, int height) { + WebPPicture tmp; + int prev_width, prev_height; + rescaler_t* work; + + if (picture == NULL) return 0; + prev_width = picture->width; + prev_height = picture->height; + if (!WebPRescalerGetScaledDimensions( + prev_width, prev_height, &width, &height)) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION); + } + + PictureGrabSpecs(picture, &tmp); + tmp.width = width; + tmp.height = height; + if (!WebPPictureAlloc(&tmp)) { + return WebPEncodingSetError(picture, tmp.error_code); + } + + if (!picture->use_argb) { + work = (rescaler_t*)WebPSafeMalloc(2ULL * width, sizeof(*work)); + if (work == NULL) { + WebPPictureFree(&tmp); + return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + // If present, we need to rescale alpha first (for AlphaMultiplyY). + if (picture->a != NULL) { + WebPInitAlphaProcessing(); + if (!RescalePlane(picture->a, prev_width, prev_height, picture->a_stride, + tmp.a, width, height, tmp.a_stride, work, 1)) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION); + } + } + + // We take transparency into account on the luma plane only. That's not + // totally exact blending, but still is a good approximation. + AlphaMultiplyY(picture, 0); + if (!RescalePlane(picture->y, prev_width, prev_height, picture->y_stride, + tmp.y, width, height, tmp.y_stride, work, 1) || + !RescalePlane(picture->u, HALVE(prev_width), HALVE(prev_height), + picture->uv_stride, tmp.u, HALVE(width), HALVE(height), + tmp.uv_stride, work, 1) || + !RescalePlane(picture->v, HALVE(prev_width), HALVE(prev_height), + picture->uv_stride, tmp.v, HALVE(width), HALVE(height), + tmp.uv_stride, work, 1)) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION); + } + AlphaMultiplyY(&tmp, 1); + } else { + work = (rescaler_t*)WebPSafeMalloc(2ULL * width * 4, sizeof(*work)); + if (work == NULL) { + WebPPictureFree(&tmp); + return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + // In order to correctly interpolate colors, we need to apply the alpha + // weighting first (black-matting), scale the RGB values, and remove + // the premultiplication afterward (while preserving the alpha channel). + WebPInitAlphaProcessing(); + AlphaMultiplyARGB(picture, 0); + if (!RescalePlane((const uint8_t*)picture->argb, prev_width, prev_height, + picture->argb_stride * 4, (uint8_t*)tmp.argb, width, + height, tmp.argb_stride * 4, work, 4)) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION); + } + AlphaMultiplyARGB(&tmp, 1); + } + WebPPictureFree(picture); + WebPSafeFree(work); + *picture = tmp; + return 1; +} + +#else // defined(WEBP_REDUCE_SIZE) + +int WebPPictureCopy(const WebPPicture* src, WebPPicture* dst) { + (void)src; + (void)dst; + return 0; +} + +int WebPPictureCrop(WebPPicture* pic, + int left, int top, int width, int height) { + (void)pic; + (void)left; + (void)top; + (void)width; + (void)height; + return 0; +} + +int WebPPictureRescale(WebPPicture* pic, int width, int height) { + (void)pic; + (void)width; + (void)height; + return 0; +} +#endif // !defined(WEBP_REDUCE_SIZE) diff --git a/third-party/webp/libwebp/src/enc/picture_tools_enc.c b/third-party/webp/libwebp/src/enc/picture_tools_enc.c new file mode 100644 index 0000000000..147cc18608 --- /dev/null +++ b/third-party/webp/libwebp/src/enc/picture_tools_enc.c @@ -0,0 +1,274 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// WebPPicture tools: alpha handling, etc. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include + +#include "src/enc/vp8i_enc.h" +#include "src/dsp/yuv.h" + +//------------------------------------------------------------------------------ +// Helper: clean up fully transparent area to help compressibility. + +#define SIZE 8 +#define SIZE2 (SIZE / 2) +static int IsTransparentARGBArea(const uint32_t* ptr, int stride, int size) { + int y, x; + for (y = 0; y < size; ++y) { + for (x = 0; x < size; ++x) { + if (ptr[x] & 0xff000000u) { + return 0; + } + } + ptr += stride; + } + return 1; +} + +static void Flatten(uint8_t* ptr, int v, int stride, int size) { + int y; + for (y = 0; y < size; ++y) { + memset(ptr, v, size); + ptr += stride; + } +} + +static void FlattenARGB(uint32_t* ptr, uint32_t v, int stride, int size) { + int x, y; + for (y = 0; y < size; ++y) { + for (x = 0; x < size; ++x) ptr[x] = v; + ptr += stride; + } +} + +// Smoothen the luma components of transparent pixels. Return true if the whole +// block is transparent. +static int SmoothenBlock(const uint8_t* a_ptr, int a_stride, uint8_t* y_ptr, + int y_stride, int width, int height) { + int sum = 0, count = 0; + int x, y; + const uint8_t* alpha_ptr = a_ptr; + uint8_t* luma_ptr = y_ptr; + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + if (alpha_ptr[x] != 0) { + ++count; + sum += luma_ptr[x]; + } + } + alpha_ptr += a_stride; + luma_ptr += y_stride; + } + if (count > 0 && count < width * height) { + const uint8_t avg_u8 = (uint8_t)(sum / count); + alpha_ptr = a_ptr; + luma_ptr = y_ptr; + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + if (alpha_ptr[x] == 0) luma_ptr[x] = avg_u8; + } + alpha_ptr += a_stride; + luma_ptr += y_stride; + } + } + return (count == 0); +} + +void WebPReplaceTransparentPixels(WebPPicture* const pic, uint32_t color) { + if (pic != NULL && pic->use_argb) { + int y = pic->height; + uint32_t* argb = pic->argb; + color &= 0xffffffu; // force alpha=0 + WebPInitAlphaProcessing(); + while (y-- > 0) { + WebPAlphaReplace(argb, pic->width, color); + argb += pic->argb_stride; + } + } +} + +void WebPCleanupTransparentArea(WebPPicture* pic) { + int x, y, w, h; + if (pic == NULL) return; + w = pic->width / SIZE; + h = pic->height / SIZE; + + // note: we ignore the left-overs on right/bottom, except for SmoothenBlock(). + if (pic->use_argb) { + uint32_t argb_value = 0; + for (y = 0; y < h; ++y) { + int need_reset = 1; + for (x = 0; x < w; ++x) { + const int off = (y * pic->argb_stride + x) * SIZE; + if (IsTransparentARGBArea(pic->argb + off, pic->argb_stride, SIZE)) { + if (need_reset) { + argb_value = pic->argb[off]; + need_reset = 0; + } + FlattenARGB(pic->argb + off, argb_value, pic->argb_stride, SIZE); + } else { + need_reset = 1; + } + } + } + } else { + const int width = pic->width; + const int height = pic->height; + const int y_stride = pic->y_stride; + const int uv_stride = pic->uv_stride; + const int a_stride = pic->a_stride; + uint8_t* y_ptr = pic->y; + uint8_t* u_ptr = pic->u; + uint8_t* v_ptr = pic->v; + const uint8_t* a_ptr = pic->a; + int values[3] = { 0 }; + if (a_ptr == NULL || y_ptr == NULL || u_ptr == NULL || v_ptr == NULL) { + return; + } + for (y = 0; y + SIZE <= height; y += SIZE) { + int need_reset = 1; + for (x = 0; x + SIZE <= width; x += SIZE) { + if (SmoothenBlock(a_ptr + x, a_stride, y_ptr + x, y_stride, + SIZE, SIZE)) { + if (need_reset) { + values[0] = y_ptr[x]; + values[1] = u_ptr[x >> 1]; + values[2] = v_ptr[x >> 1]; + need_reset = 0; + } + Flatten(y_ptr + x, values[0], y_stride, SIZE); + Flatten(u_ptr + (x >> 1), values[1], uv_stride, SIZE2); + Flatten(v_ptr + (x >> 1), values[2], uv_stride, SIZE2); + } else { + need_reset = 1; + } + } + if (x < width) { + SmoothenBlock(a_ptr + x, a_stride, y_ptr + x, y_stride, + width - x, SIZE); + } + a_ptr += SIZE * a_stride; + y_ptr += SIZE * y_stride; + u_ptr += SIZE2 * uv_stride; + v_ptr += SIZE2 * uv_stride; + } + if (y < height) { + const int sub_height = height - y; + for (x = 0; x + SIZE <= width; x += SIZE) { + SmoothenBlock(a_ptr + x, a_stride, y_ptr + x, y_stride, + SIZE, sub_height); + } + if (x < width) { + SmoothenBlock(a_ptr + x, a_stride, y_ptr + x, y_stride, + width - x, sub_height); + } + } + } +} + +#undef SIZE +#undef SIZE2 + +//------------------------------------------------------------------------------ +// Blend color and remove transparency info + +#define BLEND(V0, V1, ALPHA) \ + ((((V0) * (255 - (ALPHA)) + (V1) * (ALPHA)) * 0x101 + 256) >> 16) +#define BLEND_10BIT(V0, V1, ALPHA) \ + ((((V0) * (1020 - (ALPHA)) + (V1) * (ALPHA)) * 0x101 + 1024) >> 18) + +static WEBP_INLINE uint32_t MakeARGB32(int r, int g, int b) { + return (0xff000000u | (r << 16) | (g << 8) | b); +} + +void WebPBlendAlpha(WebPPicture* picture, uint32_t background_rgb) { + const int red = (background_rgb >> 16) & 0xff; + const int green = (background_rgb >> 8) & 0xff; + const int blue = (background_rgb >> 0) & 0xff; + int x, y; + if (picture == NULL) return; + if (!picture->use_argb) { + // omit last pixel during u/v loop + const int uv_width = (picture->width >> 1); + const int Y0 = VP8RGBToY(red, green, blue, YUV_HALF); + // VP8RGBToU/V expects the u/v values summed over four pixels + const int U0 = VP8RGBToU(4 * red, 4 * green, 4 * blue, 4 * YUV_HALF); + const int V0 = VP8RGBToV(4 * red, 4 * green, 4 * blue, 4 * YUV_HALF); + const int has_alpha = picture->colorspace & WEBP_CSP_ALPHA_BIT; + uint8_t* y_ptr = picture->y; + uint8_t* u_ptr = picture->u; + uint8_t* v_ptr = picture->v; + uint8_t* a_ptr = picture->a; + if (!has_alpha || a_ptr == NULL) return; // nothing to do + for (y = 0; y < picture->height; ++y) { + // Luma blending + for (x = 0; x < picture->width; ++x) { + const uint8_t alpha = a_ptr[x]; + if (alpha < 0xff) { + y_ptr[x] = BLEND(Y0, y_ptr[x], alpha); + } + } + // Chroma blending every even line + if ((y & 1) == 0) { + uint8_t* const a_ptr2 = + (y + 1 == picture->height) ? a_ptr : a_ptr + picture->a_stride; + for (x = 0; x < uv_width; ++x) { + // Average four alpha values into a single blending weight. + // TODO(skal): might lead to visible contouring. Can we do better? + const uint32_t alpha = + a_ptr[2 * x + 0] + a_ptr[2 * x + 1] + + a_ptr2[2 * x + 0] + a_ptr2[2 * x + 1]; + u_ptr[x] = BLEND_10BIT(U0, u_ptr[x], alpha); + v_ptr[x] = BLEND_10BIT(V0, v_ptr[x], alpha); + } + if (picture->width & 1) { // rightmost pixel + const uint32_t alpha = 2 * (a_ptr[2 * x + 0] + a_ptr2[2 * x + 0]); + u_ptr[x] = BLEND_10BIT(U0, u_ptr[x], alpha); + v_ptr[x] = BLEND_10BIT(V0, v_ptr[x], alpha); + } + } else { + u_ptr += picture->uv_stride; + v_ptr += picture->uv_stride; + } + memset(a_ptr, 0xff, picture->width); // reset alpha value to opaque + a_ptr += picture->a_stride; + y_ptr += picture->y_stride; + } + } else { + uint32_t* argb = picture->argb; + const uint32_t background = MakeARGB32(red, green, blue); + for (y = 0; y < picture->height; ++y) { + for (x = 0; x < picture->width; ++x) { + const int alpha = (argb[x] >> 24) & 0xff; + if (alpha != 0xff) { + if (alpha > 0) { + int r = (argb[x] >> 16) & 0xff; + int g = (argb[x] >> 8) & 0xff; + int b = (argb[x] >> 0) & 0xff; + r = BLEND(red, r, alpha); + g = BLEND(green, g, alpha); + b = BLEND(blue, b, alpha); + argb[x] = MakeARGB32(r, g, b); + } else { + argb[x] = background; + } + } + } + argb += picture->argb_stride; + } + } +} + +#undef BLEND +#undef BLEND_10BIT + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/src/enc/predictor_enc.c b/third-party/webp/libwebp/src/enc/predictor_enc.c new file mode 100644 index 0000000000..b3d44b59d5 --- /dev/null +++ b/third-party/webp/libwebp/src/enc/predictor_enc.c @@ -0,0 +1,792 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Image transform methods for lossless encoder. +// +// Authors: Vikas Arora (vikaas.arora@gmail.com) +// Jyrki Alakuijala (jyrki@google.com) +// Urvang Joshi (urvang@google.com) +// Vincent Rabaud (vrabaud@google.com) + +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" +#include "src/enc/vp8i_enc.h" +#include "src/enc/vp8li_enc.h" + +#define MAX_DIFF_COST (1e30f) + +static const float kSpatialPredictorBias = 15.f; +static const int kPredLowEffort = 11; +static const uint32_t kMaskAlpha = 0xff000000; + +// Mostly used to reduce code size + readability +static WEBP_INLINE int GetMin(int a, int b) { return (a > b) ? b : a; } + +//------------------------------------------------------------------------------ +// Methods to calculate Entropy (Shannon). + +static float PredictionCostSpatial(const int counts[256], int weight_0, + float exp_val) { + const int significant_symbols = 256 >> 4; + const float exp_decay_factor = 0.6f; + float bits = (float)weight_0 * counts[0]; + int i; + for (i = 1; i < significant_symbols; ++i) { + bits += exp_val * (counts[i] + counts[256 - i]); + exp_val *= exp_decay_factor; + } + return (float)(-0.1 * bits); +} + +static float PredictionCostSpatialHistogram(const int accumulated[4][256], + const int tile[4][256]) { + int i; + float retval = 0.f; + for (i = 0; i < 4; ++i) { + const float kExpValue = 0.94f; + retval += PredictionCostSpatial(tile[i], 1, kExpValue); + retval += VP8LCombinedShannonEntropy(tile[i], accumulated[i]); + } + return (float)retval; +} + +static WEBP_INLINE void UpdateHisto(int histo_argb[4][256], uint32_t argb) { + ++histo_argb[0][argb >> 24]; + ++histo_argb[1][(argb >> 16) & 0xff]; + ++histo_argb[2][(argb >> 8) & 0xff]; + ++histo_argb[3][argb & 0xff]; +} + +//------------------------------------------------------------------------------ +// Spatial transform functions. + +static WEBP_INLINE void PredictBatch(int mode, int x_start, int y, + int num_pixels, const uint32_t* current, + const uint32_t* upper, uint32_t* out) { + if (x_start == 0) { + if (y == 0) { + // ARGB_BLACK. + VP8LPredictorsSub[0](current, NULL, 1, out); + } else { + // Top one. + VP8LPredictorsSub[2](current, upper, 1, out); + } + ++x_start; + ++out; + --num_pixels; + } + if (y == 0) { + // Left one. + VP8LPredictorsSub[1](current + x_start, NULL, num_pixels, out); + } else { + VP8LPredictorsSub[mode](current + x_start, upper + x_start, num_pixels, + out); + } +} + +#if (WEBP_NEAR_LOSSLESS == 1) +static WEBP_INLINE int GetMax(int a, int b) { return (a < b) ? b : a; } + +static int MaxDiffBetweenPixels(uint32_t p1, uint32_t p2) { + const int diff_a = abs((int)(p1 >> 24) - (int)(p2 >> 24)); + const int diff_r = abs((int)((p1 >> 16) & 0xff) - (int)((p2 >> 16) & 0xff)); + const int diff_g = abs((int)((p1 >> 8) & 0xff) - (int)((p2 >> 8) & 0xff)); + const int diff_b = abs((int)(p1 & 0xff) - (int)(p2 & 0xff)); + return GetMax(GetMax(diff_a, diff_r), GetMax(diff_g, diff_b)); +} + +static int MaxDiffAroundPixel(uint32_t current, uint32_t up, uint32_t down, + uint32_t left, uint32_t right) { + const int diff_up = MaxDiffBetweenPixels(current, up); + const int diff_down = MaxDiffBetweenPixels(current, down); + const int diff_left = MaxDiffBetweenPixels(current, left); + const int diff_right = MaxDiffBetweenPixels(current, right); + return GetMax(GetMax(diff_up, diff_down), GetMax(diff_left, diff_right)); +} + +static uint32_t AddGreenToBlueAndRed(uint32_t argb) { + const uint32_t green = (argb >> 8) & 0xff; + uint32_t red_blue = argb & 0x00ff00ffu; + red_blue += (green << 16) | green; + red_blue &= 0x00ff00ffu; + return (argb & 0xff00ff00u) | red_blue; +} + +static void MaxDiffsForRow(int width, int stride, const uint32_t* const argb, + uint8_t* const max_diffs, int used_subtract_green) { + uint32_t current, up, down, left, right; + int x; + if (width <= 2) return; + current = argb[0]; + right = argb[1]; + if (used_subtract_green) { + current = AddGreenToBlueAndRed(current); + right = AddGreenToBlueAndRed(right); + } + // max_diffs[0] and max_diffs[width - 1] are never used. + for (x = 1; x < width - 1; ++x) { + up = argb[-stride + x]; + down = argb[stride + x]; + left = current; + current = right; + right = argb[x + 1]; + if (used_subtract_green) { + up = AddGreenToBlueAndRed(up); + down = AddGreenToBlueAndRed(down); + right = AddGreenToBlueAndRed(right); + } + max_diffs[x] = MaxDiffAroundPixel(current, up, down, left, right); + } +} + +// Quantize the difference between the actual component value and its prediction +// to a multiple of quantization, working modulo 256, taking care not to cross +// a boundary (inclusive upper limit). +static uint8_t NearLosslessComponent(uint8_t value, uint8_t predict, + uint8_t boundary, int quantization) { + const int residual = (value - predict) & 0xff; + const int boundary_residual = (boundary - predict) & 0xff; + const int lower = residual & ~(quantization - 1); + const int upper = lower + quantization; + // Resolve ties towards a value closer to the prediction (i.e. towards lower + // if value comes after prediction and towards upper otherwise). + const int bias = ((boundary - value) & 0xff) < boundary_residual; + if (residual - lower < upper - residual + bias) { + // lower is closer to residual than upper. + if (residual > boundary_residual && lower <= boundary_residual) { + // Halve quantization step to avoid crossing boundary. This midpoint is + // on the same side of boundary as residual because midpoint >= residual + // (since lower is closer than upper) and residual is above the boundary. + return lower + (quantization >> 1); + } + return lower; + } else { + // upper is closer to residual than lower. + if (residual <= boundary_residual && upper > boundary_residual) { + // Halve quantization step to avoid crossing boundary. This midpoint is + // on the same side of boundary as residual because midpoint <= residual + // (since upper is closer than lower) and residual is below the boundary. + return lower + (quantization >> 1); + } + return upper & 0xff; + } +} + +static WEBP_INLINE uint8_t NearLosslessDiff(uint8_t a, uint8_t b) { + return (uint8_t)((((int)(a) - (int)(b))) & 0xff); +} + +// Quantize every component of the difference between the actual pixel value and +// its prediction to a multiple of a quantization (a power of 2, not larger than +// max_quantization which is a power of 2, smaller than max_diff). Take care if +// value and predict have undergone subtract green, which means that red and +// blue are represented as offsets from green. +static uint32_t NearLossless(uint32_t value, uint32_t predict, + int max_quantization, int max_diff, + int used_subtract_green) { + int quantization; + uint8_t new_green = 0; + uint8_t green_diff = 0; + uint8_t a, r, g, b; + if (max_diff <= 2) { + return VP8LSubPixels(value, predict); + } + quantization = max_quantization; + while (quantization >= max_diff) { + quantization >>= 1; + } + if ((value >> 24) == 0 || (value >> 24) == 0xff) { + // Preserve transparency of fully transparent or fully opaque pixels. + a = NearLosslessDiff((value >> 24) & 0xff, (predict >> 24) & 0xff); + } else { + a = NearLosslessComponent(value >> 24, predict >> 24, 0xff, quantization); + } + g = NearLosslessComponent((value >> 8) & 0xff, (predict >> 8) & 0xff, 0xff, + quantization); + if (used_subtract_green) { + // The green offset will be added to red and blue components during decoding + // to obtain the actual red and blue values. + new_green = ((predict >> 8) + g) & 0xff; + // The amount by which green has been adjusted during quantization. It is + // subtracted from red and blue for compensation, to avoid accumulating two + // quantization errors in them. + green_diff = NearLosslessDiff(new_green, (value >> 8) & 0xff); + } + r = NearLosslessComponent(NearLosslessDiff((value >> 16) & 0xff, green_diff), + (predict >> 16) & 0xff, 0xff - new_green, + quantization); + b = NearLosslessComponent(NearLosslessDiff(value & 0xff, green_diff), + predict & 0xff, 0xff - new_green, quantization); + return ((uint32_t)a << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | b; +} +#endif // (WEBP_NEAR_LOSSLESS == 1) + +// Stores the difference between the pixel and its prediction in "out". +// In case of a lossy encoding, updates the source image to avoid propagating +// the deviation further to pixels which depend on the current pixel for their +// predictions. +static WEBP_INLINE void GetResidual( + int width, int height, uint32_t* const upper_row, + uint32_t* const current_row, const uint8_t* const max_diffs, int mode, + int x_start, int x_end, int y, int max_quantization, int exact, + int used_subtract_green, uint32_t* const out) { + if (exact) { + PredictBatch(mode, x_start, y, x_end - x_start, current_row, upper_row, + out); + } else { + const VP8LPredictorFunc pred_func = VP8LPredictors[mode]; + int x; + for (x = x_start; x < x_end; ++x) { + uint32_t predict; + uint32_t residual; + if (y == 0) { + predict = (x == 0) ? ARGB_BLACK : current_row[x - 1]; // Left. + } else if (x == 0) { + predict = upper_row[x]; // Top. + } else { + predict = pred_func(¤t_row[x - 1], upper_row + x); + } +#if (WEBP_NEAR_LOSSLESS == 1) + if (max_quantization == 1 || mode == 0 || y == 0 || y == height - 1 || + x == 0 || x == width - 1) { + residual = VP8LSubPixels(current_row[x], predict); + } else { + residual = NearLossless(current_row[x], predict, max_quantization, + max_diffs[x], used_subtract_green); + // Update the source image. + current_row[x] = VP8LAddPixels(predict, residual); + // x is never 0 here so we do not need to update upper_row like below. + } +#else + (void)max_diffs; + (void)height; + (void)max_quantization; + (void)used_subtract_green; + residual = VP8LSubPixels(current_row[x], predict); +#endif + if ((current_row[x] & kMaskAlpha) == 0) { + // If alpha is 0, cleanup RGB. We can choose the RGB values of the + // residual for best compression. The prediction of alpha itself can be + // non-zero and must be kept though. We choose RGB of the residual to be + // 0. + residual &= kMaskAlpha; + // Update the source image. + current_row[x] = predict & ~kMaskAlpha; + // The prediction for the rightmost pixel in a row uses the leftmost + // pixel + // in that row as its top-right context pixel. Hence if we change the + // leftmost pixel of current_row, the corresponding change must be + // applied + // to upper_row as well where top-right context is being read from. + if (x == 0 && y != 0) upper_row[width] = current_row[0]; + } + out[x - x_start] = residual; + } + } +} + +// Returns best predictor and updates the accumulated histogram. +// If max_quantization > 1, assumes that near lossless processing will be +// applied, quantizing residuals to multiples of quantization levels up to +// max_quantization (the actual quantization level depends on smoothness near +// the given pixel). +static int GetBestPredictorForTile(int width, int height, + int tile_x, int tile_y, int bits, + int accumulated[4][256], + uint32_t* const argb_scratch, + const uint32_t* const argb, + int max_quantization, + int exact, int used_subtract_green, + const uint32_t* const modes) { + const int kNumPredModes = 14; + const int start_x = tile_x << bits; + const int start_y = tile_y << bits; + const int tile_size = 1 << bits; + const int max_y = GetMin(tile_size, height - start_y); + const int max_x = GetMin(tile_size, width - start_x); + // Whether there exist columns just outside the tile. + const int have_left = (start_x > 0); + // Position and size of the strip covering the tile and adjacent columns if + // they exist. + const int context_start_x = start_x - have_left; +#if (WEBP_NEAR_LOSSLESS == 1) + const int context_width = max_x + have_left + (max_x < width - start_x); +#endif + const int tiles_per_row = VP8LSubSampleSize(width, bits); + // Prediction modes of the left and above neighbor tiles. + const int left_mode = (tile_x > 0) ? + (modes[tile_y * tiles_per_row + tile_x - 1] >> 8) & 0xff : 0xff; + const int above_mode = (tile_y > 0) ? + (modes[(tile_y - 1) * tiles_per_row + tile_x] >> 8) & 0xff : 0xff; + // The width of upper_row and current_row is one pixel larger than image width + // to allow the top right pixel to point to the leftmost pixel of the next row + // when at the right edge. + uint32_t* upper_row = argb_scratch; + uint32_t* current_row = upper_row + width + 1; + uint8_t* const max_diffs = (uint8_t*)(current_row + width + 1); + float best_diff = MAX_DIFF_COST; + int best_mode = 0; + int mode; + int histo_stack_1[4][256]; + int histo_stack_2[4][256]; + // Need pointers to be able to swap arrays. + int (*histo_argb)[256] = histo_stack_1; + int (*best_histo)[256] = histo_stack_2; + int i, j; + uint32_t residuals[1 << MAX_TRANSFORM_BITS]; + assert(bits <= MAX_TRANSFORM_BITS); + assert(max_x <= (1 << MAX_TRANSFORM_BITS)); + + for (mode = 0; mode < kNumPredModes; ++mode) { + float cur_diff; + int relative_y; + memset(histo_argb, 0, sizeof(histo_stack_1)); + if (start_y > 0) { + // Read the row above the tile which will become the first upper_row. + // Include a pixel to the left if it exists; include a pixel to the right + // in all cases (wrapping to the leftmost pixel of the next row if it does + // not exist). + memcpy(current_row + context_start_x, + argb + (start_y - 1) * width + context_start_x, + sizeof(*argb) * (max_x + have_left + 1)); + } + for (relative_y = 0; relative_y < max_y; ++relative_y) { + const int y = start_y + relative_y; + int relative_x; + uint32_t* tmp = upper_row; + upper_row = current_row; + current_row = tmp; + // Read current_row. Include a pixel to the left if it exists; include a + // pixel to the right in all cases except at the bottom right corner of + // the image (wrapping to the leftmost pixel of the next row if it does + // not exist in the current row). + memcpy(current_row + context_start_x, + argb + y * width + context_start_x, + sizeof(*argb) * (max_x + have_left + (y + 1 < height))); +#if (WEBP_NEAR_LOSSLESS == 1) + if (max_quantization > 1 && y >= 1 && y + 1 < height) { + MaxDiffsForRow(context_width, width, argb + y * width + context_start_x, + max_diffs + context_start_x, used_subtract_green); + } +#endif + + GetResidual(width, height, upper_row, current_row, max_diffs, mode, + start_x, start_x + max_x, y, max_quantization, exact, + used_subtract_green, residuals); + for (relative_x = 0; relative_x < max_x; ++relative_x) { + UpdateHisto(histo_argb, residuals[relative_x]); + } + } + cur_diff = PredictionCostSpatialHistogram( + (const int (*)[256])accumulated, (const int (*)[256])histo_argb); + // Favor keeping the areas locally similar. + if (mode == left_mode) cur_diff -= kSpatialPredictorBias; + if (mode == above_mode) cur_diff -= kSpatialPredictorBias; + + if (cur_diff < best_diff) { + int (*tmp)[256] = histo_argb; + histo_argb = best_histo; + best_histo = tmp; + best_diff = cur_diff; + best_mode = mode; + } + } + + for (i = 0; i < 4; i++) { + for (j = 0; j < 256; j++) { + accumulated[i][j] += best_histo[i][j]; + } + } + + return best_mode; +} + +// Converts pixels of the image to residuals with respect to predictions. +// If max_quantization > 1, applies near lossless processing, quantizing +// residuals to multiples of quantization levels up to max_quantization +// (the actual quantization level depends on smoothness near the given pixel). +static void CopyImageWithPrediction(int width, int height, + int bits, uint32_t* const modes, + uint32_t* const argb_scratch, + uint32_t* const argb, + int low_effort, int max_quantization, + int exact, int used_subtract_green) { + const int tiles_per_row = VP8LSubSampleSize(width, bits); + // The width of upper_row and current_row is one pixel larger than image width + // to allow the top right pixel to point to the leftmost pixel of the next row + // when at the right edge. + uint32_t* upper_row = argb_scratch; + uint32_t* current_row = upper_row + width + 1; + uint8_t* current_max_diffs = (uint8_t*)(current_row + width + 1); +#if (WEBP_NEAR_LOSSLESS == 1) + uint8_t* lower_max_diffs = current_max_diffs + width; +#endif + int y; + + for (y = 0; y < height; ++y) { + int x; + uint32_t* const tmp32 = upper_row; + upper_row = current_row; + current_row = tmp32; + memcpy(current_row, argb + y * width, + sizeof(*argb) * (width + (y + 1 < height))); + + if (low_effort) { + PredictBatch(kPredLowEffort, 0, y, width, current_row, upper_row, + argb + y * width); + } else { +#if (WEBP_NEAR_LOSSLESS == 1) + if (max_quantization > 1) { + // Compute max_diffs for the lower row now, because that needs the + // contents of argb for the current row, which we will overwrite with + // residuals before proceeding with the next row. + uint8_t* const tmp8 = current_max_diffs; + current_max_diffs = lower_max_diffs; + lower_max_diffs = tmp8; + if (y + 2 < height) { + MaxDiffsForRow(width, width, argb + (y + 1) * width, lower_max_diffs, + used_subtract_green); + } + } +#endif + for (x = 0; x < width;) { + const int mode = + (modes[(y >> bits) * tiles_per_row + (x >> bits)] >> 8) & 0xff; + int x_end = x + (1 << bits); + if (x_end > width) x_end = width; + GetResidual(width, height, upper_row, current_row, current_max_diffs, + mode, x, x_end, y, max_quantization, exact, + used_subtract_green, argb + y * width + x); + x = x_end; + } + } + } +} + +// Finds the best predictor for each tile, and converts the image to residuals +// with respect to predictions. If near_lossless_quality < 100, applies +// near lossless processing, shaving off more bits of residuals for lower +// qualities. +int VP8LResidualImage(int width, int height, int bits, int low_effort, + uint32_t* const argb, uint32_t* const argb_scratch, + uint32_t* const image, int near_lossless_quality, + int exact, int used_subtract_green, + const WebPPicture* const pic, int percent_range, + int* const percent) { + const int tiles_per_row = VP8LSubSampleSize(width, bits); + const int tiles_per_col = VP8LSubSampleSize(height, bits); + int percent_start = *percent; + int tile_y; + int histo[4][256]; + const int max_quantization = 1 << VP8LNearLosslessBits(near_lossless_quality); + if (low_effort) { + int i; + for (i = 0; i < tiles_per_row * tiles_per_col; ++i) { + image[i] = ARGB_BLACK | (kPredLowEffort << 8); + } + } else { + memset(histo, 0, sizeof(histo)); + for (tile_y = 0; tile_y < tiles_per_col; ++tile_y) { + int tile_x; + for (tile_x = 0; tile_x < tiles_per_row; ++tile_x) { + const int pred = GetBestPredictorForTile( + width, height, tile_x, tile_y, bits, histo, argb_scratch, argb, + max_quantization, exact, used_subtract_green, image); + image[tile_y * tiles_per_row + tile_x] = ARGB_BLACK | (pred << 8); + } + + if (!WebPReportProgress( + pic, percent_start + percent_range * tile_y / tiles_per_col, + percent)) { + return 0; + } + } + } + + CopyImageWithPrediction(width, height, bits, image, argb_scratch, argb, + low_effort, max_quantization, exact, + used_subtract_green); + return WebPReportProgress(pic, percent_start + percent_range, percent); +} + +//------------------------------------------------------------------------------ +// Color transform functions. + +static WEBP_INLINE void MultipliersClear(VP8LMultipliers* const m) { + m->green_to_red_ = 0; + m->green_to_blue_ = 0; + m->red_to_blue_ = 0; +} + +static WEBP_INLINE void ColorCodeToMultipliers(uint32_t color_code, + VP8LMultipliers* const m) { + m->green_to_red_ = (color_code >> 0) & 0xff; + m->green_to_blue_ = (color_code >> 8) & 0xff; + m->red_to_blue_ = (color_code >> 16) & 0xff; +} + +static WEBP_INLINE uint32_t MultipliersToColorCode( + const VP8LMultipliers* const m) { + return 0xff000000u | + ((uint32_t)(m->red_to_blue_) << 16) | + ((uint32_t)(m->green_to_blue_) << 8) | + m->green_to_red_; +} + +static float PredictionCostCrossColor(const int accumulated[256], + const int counts[256]) { + // Favor low entropy, locally and globally. + // Favor small absolute values for PredictionCostSpatial + static const float kExpValue = 2.4f; + return VP8LCombinedShannonEntropy(counts, accumulated) + + PredictionCostSpatial(counts, 3, kExpValue); +} + +static float GetPredictionCostCrossColorRed( + const uint32_t* argb, int stride, int tile_width, int tile_height, + VP8LMultipliers prev_x, VP8LMultipliers prev_y, int green_to_red, + const int accumulated_red_histo[256]) { + int histo[256] = { 0 }; + float cur_diff; + + VP8LCollectColorRedTransforms(argb, stride, tile_width, tile_height, + green_to_red, histo); + + cur_diff = PredictionCostCrossColor(accumulated_red_histo, histo); + if ((uint8_t)green_to_red == prev_x.green_to_red_) { + cur_diff -= 3; // favor keeping the areas locally similar + } + if ((uint8_t)green_to_red == prev_y.green_to_red_) { + cur_diff -= 3; // favor keeping the areas locally similar + } + if (green_to_red == 0) { + cur_diff -= 3; + } + return cur_diff; +} + +static void GetBestGreenToRed( + const uint32_t* argb, int stride, int tile_width, int tile_height, + VP8LMultipliers prev_x, VP8LMultipliers prev_y, int quality, + const int accumulated_red_histo[256], VP8LMultipliers* const best_tx) { + const int kMaxIters = 4 + ((7 * quality) >> 8); // in range [4..6] + int green_to_red_best = 0; + int iter, offset; + float best_diff = GetPredictionCostCrossColorRed( + argb, stride, tile_width, tile_height, prev_x, prev_y, + green_to_red_best, accumulated_red_histo); + for (iter = 0; iter < kMaxIters; ++iter) { + // ColorTransformDelta is a 3.5 bit fixed point, so 32 is equal to + // one in color computation. Having initial delta here as 1 is sufficient + // to explore the range of (-2, 2). + const int delta = 32 >> iter; + // Try a negative and a positive delta from the best known value. + for (offset = -delta; offset <= delta; offset += 2 * delta) { + const int green_to_red_cur = offset + green_to_red_best; + const float cur_diff = GetPredictionCostCrossColorRed( + argb, stride, tile_width, tile_height, prev_x, prev_y, + green_to_red_cur, accumulated_red_histo); + if (cur_diff < best_diff) { + best_diff = cur_diff; + green_to_red_best = green_to_red_cur; + } + } + } + best_tx->green_to_red_ = (green_to_red_best & 0xff); +} + +static float GetPredictionCostCrossColorBlue( + const uint32_t* argb, int stride, int tile_width, int tile_height, + VP8LMultipliers prev_x, VP8LMultipliers prev_y, + int green_to_blue, int red_to_blue, const int accumulated_blue_histo[256]) { + int histo[256] = { 0 }; + float cur_diff; + + VP8LCollectColorBlueTransforms(argb, stride, tile_width, tile_height, + green_to_blue, red_to_blue, histo); + + cur_diff = PredictionCostCrossColor(accumulated_blue_histo, histo); + if ((uint8_t)green_to_blue == prev_x.green_to_blue_) { + cur_diff -= 3; // favor keeping the areas locally similar + } + if ((uint8_t)green_to_blue == prev_y.green_to_blue_) { + cur_diff -= 3; // favor keeping the areas locally similar + } + if ((uint8_t)red_to_blue == prev_x.red_to_blue_) { + cur_diff -= 3; // favor keeping the areas locally similar + } + if ((uint8_t)red_to_blue == prev_y.red_to_blue_) { + cur_diff -= 3; // favor keeping the areas locally similar + } + if (green_to_blue == 0) { + cur_diff -= 3; + } + if (red_to_blue == 0) { + cur_diff -= 3; + } + return cur_diff; +} + +#define kGreenRedToBlueNumAxis 8 +#define kGreenRedToBlueMaxIters 7 +static void GetBestGreenRedToBlue( + const uint32_t* argb, int stride, int tile_width, int tile_height, + VP8LMultipliers prev_x, VP8LMultipliers prev_y, int quality, + const int accumulated_blue_histo[256], + VP8LMultipliers* const best_tx) { + const int8_t offset[kGreenRedToBlueNumAxis][2] = + {{0, -1}, {0, 1}, {-1, 0}, {1, 0}, {-1, -1}, {-1, 1}, {1, -1}, {1, 1}}; + const int8_t delta_lut[kGreenRedToBlueMaxIters] = { 16, 16, 8, 4, 2, 2, 2 }; + const int iters = + (quality < 25) ? 1 : (quality > 50) ? kGreenRedToBlueMaxIters : 4; + int green_to_blue_best = 0; + int red_to_blue_best = 0; + int iter; + // Initial value at origin: + float best_diff = GetPredictionCostCrossColorBlue( + argb, stride, tile_width, tile_height, prev_x, prev_y, + green_to_blue_best, red_to_blue_best, accumulated_blue_histo); + for (iter = 0; iter < iters; ++iter) { + const int delta = delta_lut[iter]; + int axis; + for (axis = 0; axis < kGreenRedToBlueNumAxis; ++axis) { + const int green_to_blue_cur = + offset[axis][0] * delta + green_to_blue_best; + const int red_to_blue_cur = offset[axis][1] * delta + red_to_blue_best; + const float cur_diff = GetPredictionCostCrossColorBlue( + argb, stride, tile_width, tile_height, prev_x, prev_y, + green_to_blue_cur, red_to_blue_cur, accumulated_blue_histo); + if (cur_diff < best_diff) { + best_diff = cur_diff; + green_to_blue_best = green_to_blue_cur; + red_to_blue_best = red_to_blue_cur; + } + if (quality < 25 && iter == 4) { + // Only axis aligned diffs for lower quality. + break; // next iter. + } + } + if (delta == 2 && green_to_blue_best == 0 && red_to_blue_best == 0) { + // Further iterations would not help. + break; // out of iter-loop. + } + } + best_tx->green_to_blue_ = green_to_blue_best & 0xff; + best_tx->red_to_blue_ = red_to_blue_best & 0xff; +} +#undef kGreenRedToBlueMaxIters +#undef kGreenRedToBlueNumAxis + +static VP8LMultipliers GetBestColorTransformForTile( + int tile_x, int tile_y, int bits, + VP8LMultipliers prev_x, + VP8LMultipliers prev_y, + int quality, int xsize, int ysize, + const int accumulated_red_histo[256], + const int accumulated_blue_histo[256], + const uint32_t* const argb) { + const int max_tile_size = 1 << bits; + const int tile_y_offset = tile_y * max_tile_size; + const int tile_x_offset = tile_x * max_tile_size; + const int all_x_max = GetMin(tile_x_offset + max_tile_size, xsize); + const int all_y_max = GetMin(tile_y_offset + max_tile_size, ysize); + const int tile_width = all_x_max - tile_x_offset; + const int tile_height = all_y_max - tile_y_offset; + const uint32_t* const tile_argb = argb + tile_y_offset * xsize + + tile_x_offset; + VP8LMultipliers best_tx; + MultipliersClear(&best_tx); + + GetBestGreenToRed(tile_argb, xsize, tile_width, tile_height, + prev_x, prev_y, quality, accumulated_red_histo, &best_tx); + GetBestGreenRedToBlue(tile_argb, xsize, tile_width, tile_height, + prev_x, prev_y, quality, accumulated_blue_histo, + &best_tx); + return best_tx; +} + +static void CopyTileWithColorTransform(int xsize, int ysize, + int tile_x, int tile_y, + int max_tile_size, + VP8LMultipliers color_transform, + uint32_t* argb) { + const int xscan = GetMin(max_tile_size, xsize - tile_x); + int yscan = GetMin(max_tile_size, ysize - tile_y); + argb += tile_y * xsize + tile_x; + while (yscan-- > 0) { + VP8LTransformColor(&color_transform, argb, xscan); + argb += xsize; + } +} + +int VP8LColorSpaceTransform(int width, int height, int bits, int quality, + uint32_t* const argb, uint32_t* image, + const WebPPicture* const pic, int percent_range, + int* const percent) { + const int max_tile_size = 1 << bits; + const int tile_xsize = VP8LSubSampleSize(width, bits); + const int tile_ysize = VP8LSubSampleSize(height, bits); + int percent_start = *percent; + int accumulated_red_histo[256] = { 0 }; + int accumulated_blue_histo[256] = { 0 }; + int tile_x, tile_y; + VP8LMultipliers prev_x, prev_y; + MultipliersClear(&prev_y); + MultipliersClear(&prev_x); + for (tile_y = 0; tile_y < tile_ysize; ++tile_y) { + for (tile_x = 0; tile_x < tile_xsize; ++tile_x) { + int y; + const int tile_x_offset = tile_x * max_tile_size; + const int tile_y_offset = tile_y * max_tile_size; + const int all_x_max = GetMin(tile_x_offset + max_tile_size, width); + const int all_y_max = GetMin(tile_y_offset + max_tile_size, height); + const int offset = tile_y * tile_xsize + tile_x; + if (tile_y != 0) { + ColorCodeToMultipliers(image[offset - tile_xsize], &prev_y); + } + prev_x = GetBestColorTransformForTile(tile_x, tile_y, bits, + prev_x, prev_y, + quality, width, height, + accumulated_red_histo, + accumulated_blue_histo, + argb); + image[offset] = MultipliersToColorCode(&prev_x); + CopyTileWithColorTransform(width, height, tile_x_offset, tile_y_offset, + max_tile_size, prev_x, argb); + + // Gather accumulated histogram data. + for (y = tile_y_offset; y < all_y_max; ++y) { + int ix = y * width + tile_x_offset; + const int ix_end = ix + all_x_max - tile_x_offset; + for (; ix < ix_end; ++ix) { + const uint32_t pix = argb[ix]; + if (ix >= 2 && + pix == argb[ix - 2] && + pix == argb[ix - 1]) { + continue; // repeated pixels are handled by backward references + } + if (ix >= width + 2 && + argb[ix - 2] == argb[ix - width - 2] && + argb[ix - 1] == argb[ix - width - 1] && + pix == argb[ix - width]) { + continue; // repeated pixels are handled by backward references + } + ++accumulated_red_histo[(pix >> 16) & 0xff]; + ++accumulated_blue_histo[(pix >> 0) & 0xff]; + } + } + } + if (!WebPReportProgress( + pic, percent_start + percent_range * tile_y / tile_ysize, + percent)) { + return 0; + } + } + return 1; +} diff --git a/third-party/webp/libwebp/src/enc/quant_enc.c b/third-party/webp/libwebp/src/enc/quant_enc.c new file mode 100644 index 0000000000..6d8202d277 --- /dev/null +++ b/third-party/webp/libwebp/src/enc/quant_enc.c @@ -0,0 +1,1398 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Quantization +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include +#include // for abs() + +#include "src/dsp/quant.h" +#include "src/enc/vp8i_enc.h" +#include "src/enc/cost_enc.h" + +#define DO_TRELLIS_I4 1 +#define DO_TRELLIS_I16 1 // not a huge gain, but ok at low bitrate. +#define DO_TRELLIS_UV 0 // disable trellis for UV. Risky. Not worth. +#define USE_TDISTO 1 + +#define MID_ALPHA 64 // neutral value for susceptibility +#define MIN_ALPHA 30 // lowest usable value for susceptibility +#define MAX_ALPHA 100 // higher meaningful value for susceptibility + +#define SNS_TO_DQ 0.9 // Scaling constant between the sns value and the QP + // power-law modulation. Must be strictly less than 1. + +// number of non-zero coeffs below which we consider the block very flat +// (and apply a penalty to complex predictions) +#define FLATNESS_LIMIT_I16 0 // I16 mode (special case) +#define FLATNESS_LIMIT_I4 3 // I4 mode +#define FLATNESS_LIMIT_UV 2 // UV mode +#define FLATNESS_PENALTY 140 // roughly ~1bit per block + +#define MULT_8B(a, b) (((a) * (b) + 128) >> 8) + +#define RD_DISTO_MULT 256 // distortion multiplier (equivalent of lambda) + +// #define DEBUG_BLOCK + +//------------------------------------------------------------------------------ + +#if defined(DEBUG_BLOCK) + +#include +#include + +static void PrintBlockInfo(const VP8EncIterator* const it, + const VP8ModeScore* const rd) { + int i, j; + const int is_i16 = (it->mb_->type_ == 1); + const uint8_t* const y_in = it->yuv_in_ + Y_OFF_ENC; + const uint8_t* const y_out = it->yuv_out_ + Y_OFF_ENC; + const uint8_t* const uv_in = it->yuv_in_ + U_OFF_ENC; + const uint8_t* const uv_out = it->yuv_out_ + U_OFF_ENC; + printf("SOURCE / OUTPUT / ABS DELTA\n"); + for (j = 0; j < 16; ++j) { + for (i = 0; i < 16; ++i) printf("%3d ", y_in[i + j * BPS]); + printf(" "); + for (i = 0; i < 16; ++i) printf("%3d ", y_out[i + j * BPS]); + printf(" "); + for (i = 0; i < 16; ++i) { + printf("%1d ", abs(y_in[i + j * BPS] - y_out[i + j * BPS])); + } + printf("\n"); + } + printf("\n"); // newline before the U/V block + for (j = 0; j < 8; ++j) { + for (i = 0; i < 8; ++i) printf("%3d ", uv_in[i + j * BPS]); + printf(" "); + for (i = 8; i < 16; ++i) printf("%3d ", uv_in[i + j * BPS]); + printf(" "); + for (i = 0; i < 8; ++i) printf("%3d ", uv_out[i + j * BPS]); + printf(" "); + for (i = 8; i < 16; ++i) printf("%3d ", uv_out[i + j * BPS]); + printf(" "); + for (i = 0; i < 8; ++i) { + printf("%1d ", abs(uv_out[i + j * BPS] - uv_in[i + j * BPS])); + } + printf(" "); + for (i = 8; i < 16; ++i) { + printf("%1d ", abs(uv_out[i + j * BPS] - uv_in[i + j * BPS])); + } + printf("\n"); + } + printf("\nD:%d SD:%d R:%d H:%d nz:0x%x score:%d\n", + (int)rd->D, (int)rd->SD, (int)rd->R, (int)rd->H, (int)rd->nz, + (int)rd->score); + if (is_i16) { + printf("Mode: %d\n", rd->mode_i16); + printf("y_dc_levels:"); + for (i = 0; i < 16; ++i) printf("%3d ", rd->y_dc_levels[i]); + printf("\n"); + } else { + printf("Modes[16]: "); + for (i = 0; i < 16; ++i) printf("%d ", rd->modes_i4[i]); + printf("\n"); + } + printf("y_ac_levels:\n"); + for (j = 0; j < 16; ++j) { + for (i = is_i16 ? 1 : 0; i < 16; ++i) { + printf("%4d ", rd->y_ac_levels[j][i]); + } + printf("\n"); + } + printf("\n"); + printf("uv_levels (mode=%d):\n", rd->mode_uv); + for (j = 0; j < 8; ++j) { + for (i = 0; i < 16; ++i) { + printf("%4d ", rd->uv_levels[j][i]); + } + printf("\n"); + } +} + +#endif // DEBUG_BLOCK + +//------------------------------------------------------------------------------ + +static WEBP_INLINE int clip(int v, int m, int M) { + return v < m ? m : v > M ? M : v; +} + +static const uint8_t kZigzag[16] = { + 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15 +}; + +static const uint8_t kDcTable[128] = { + 4, 5, 6, 7, 8, 9, 10, 10, + 11, 12, 13, 14, 15, 16, 17, 17, + 18, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 25, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, + 37, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 76, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, 88, 89, + 91, 93, 95, 96, 98, 100, 101, 102, + 104, 106, 108, 110, 112, 114, 116, 118, + 122, 124, 126, 128, 130, 132, 134, 136, + 138, 140, 143, 145, 148, 151, 154, 157 +}; + +static const uint16_t kAcTable[128] = { + 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 60, + 62, 64, 66, 68, 70, 72, 74, 76, + 78, 80, 82, 84, 86, 88, 90, 92, + 94, 96, 98, 100, 102, 104, 106, 108, + 110, 112, 114, 116, 119, 122, 125, 128, + 131, 134, 137, 140, 143, 146, 149, 152, + 155, 158, 161, 164, 167, 170, 173, 177, + 181, 185, 189, 193, 197, 201, 205, 209, + 213, 217, 221, 225, 229, 234, 239, 245, + 249, 254, 259, 264, 269, 274, 279, 284 +}; + +static const uint16_t kAcTable2[128] = { + 8, 8, 9, 10, 12, 13, 15, 17, + 18, 20, 21, 23, 24, 26, 27, 29, + 31, 32, 34, 35, 37, 38, 40, 41, + 43, 44, 46, 48, 49, 51, 52, 54, + 55, 57, 58, 60, 62, 63, 65, 66, + 68, 69, 71, 72, 74, 75, 77, 79, + 80, 82, 83, 85, 86, 88, 89, 93, + 96, 99, 102, 105, 108, 111, 114, 117, + 120, 124, 127, 130, 133, 136, 139, 142, + 145, 148, 151, 155, 158, 161, 164, 167, + 170, 173, 176, 179, 184, 189, 193, 198, + 203, 207, 212, 217, 221, 226, 230, 235, + 240, 244, 249, 254, 258, 263, 268, 274, + 280, 286, 292, 299, 305, 311, 317, 323, + 330, 336, 342, 348, 354, 362, 370, 379, + 385, 393, 401, 409, 416, 424, 432, 440 +}; + +static const uint8_t kBiasMatrices[3][2] = { // [luma-ac,luma-dc,chroma][dc,ac] + { 96, 110 }, { 96, 108 }, { 110, 115 } +}; + +// Sharpening by (slightly) raising the hi-frequency coeffs. +// Hack-ish but helpful for mid-bitrate range. Use with care. +#define SHARPEN_BITS 11 // number of descaling bits for sharpening bias +static const uint8_t kFreqSharpening[16] = { + 0, 30, 60, 90, + 30, 60, 90, 90, + 60, 90, 90, 90, + 90, 90, 90, 90 +}; + +//------------------------------------------------------------------------------ +// Initialize quantization parameters in VP8Matrix + +// Returns the average quantizer +static int ExpandMatrix(VP8Matrix* const m, int type) { + int i, sum; + for (i = 0; i < 2; ++i) { + const int is_ac_coeff = (i > 0); + const int bias = kBiasMatrices[type][is_ac_coeff]; + m->iq_[i] = (1 << QFIX) / m->q_[i]; + m->bias_[i] = BIAS(bias); + // zthresh_ is the exact value such that QUANTDIV(coeff, iQ, B) is: + // * zero if coeff <= zthresh + // * non-zero if coeff > zthresh + m->zthresh_[i] = ((1 << QFIX) - 1 - m->bias_[i]) / m->iq_[i]; + } + for (i = 2; i < 16; ++i) { + m->q_[i] = m->q_[1]; + m->iq_[i] = m->iq_[1]; + m->bias_[i] = m->bias_[1]; + m->zthresh_[i] = m->zthresh_[1]; + } + for (sum = 0, i = 0; i < 16; ++i) { + if (type == 0) { // we only use sharpening for AC luma coeffs + m->sharpen_[i] = (kFreqSharpening[i] * m->q_[i]) >> SHARPEN_BITS; + } else { + m->sharpen_[i] = 0; + } + sum += m->q_[i]; + } + return (sum + 8) >> 4; +} + +static void CheckLambdaValue(int* const v) { if (*v < 1) *v = 1; } + +static void SetupMatrices(VP8Encoder* enc) { + int i; + const int tlambda_scale = + (enc->method_ >= 4) ? enc->config_->sns_strength + : 0; + const int num_segments = enc->segment_hdr_.num_segments_; + for (i = 0; i < num_segments; ++i) { + VP8SegmentInfo* const m = &enc->dqm_[i]; + const int q = m->quant_; + int q_i4, q_i16, q_uv; + m->y1_.q_[0] = kDcTable[clip(q + enc->dq_y1_dc_, 0, 127)]; + m->y1_.q_[1] = kAcTable[clip(q, 0, 127)]; + + m->y2_.q_[0] = kDcTable[ clip(q + enc->dq_y2_dc_, 0, 127)] * 2; + m->y2_.q_[1] = kAcTable2[clip(q + enc->dq_y2_ac_, 0, 127)]; + + m->uv_.q_[0] = kDcTable[clip(q + enc->dq_uv_dc_, 0, 117)]; + m->uv_.q_[1] = kAcTable[clip(q + enc->dq_uv_ac_, 0, 127)]; + + q_i4 = ExpandMatrix(&m->y1_, 0); + q_i16 = ExpandMatrix(&m->y2_, 1); + q_uv = ExpandMatrix(&m->uv_, 2); + + m->lambda_i4_ = (3 * q_i4 * q_i4) >> 7; + m->lambda_i16_ = (3 * q_i16 * q_i16); + m->lambda_uv_ = (3 * q_uv * q_uv) >> 6; + m->lambda_mode_ = (1 * q_i4 * q_i4) >> 7; + m->lambda_trellis_i4_ = (7 * q_i4 * q_i4) >> 3; + m->lambda_trellis_i16_ = (q_i16 * q_i16) >> 2; + m->lambda_trellis_uv_ = (q_uv * q_uv) << 1; + m->tlambda_ = (tlambda_scale * q_i4) >> 5; + + // none of these constants should be < 1 + CheckLambdaValue(&m->lambda_i4_); + CheckLambdaValue(&m->lambda_i16_); + CheckLambdaValue(&m->lambda_uv_); + CheckLambdaValue(&m->lambda_mode_); + CheckLambdaValue(&m->lambda_trellis_i4_); + CheckLambdaValue(&m->lambda_trellis_i16_); + CheckLambdaValue(&m->lambda_trellis_uv_); + CheckLambdaValue(&m->tlambda_); + + m->min_disto_ = 20 * m->y1_.q_[0]; // quantization-aware min disto + m->max_edge_ = 0; + + m->i4_penalty_ = 1000 * q_i4 * q_i4; + } +} + +//------------------------------------------------------------------------------ +// Initialize filtering parameters + +// Very small filter-strength values have close to no visual effect. So we can +// save a little decoding-CPU by turning filtering off for these. +#define FSTRENGTH_CUTOFF 2 + +static void SetupFilterStrength(VP8Encoder* const enc) { + int i; + // level0 is in [0..500]. Using '-f 50' as filter_strength is mid-filtering. + const int level0 = 5 * enc->config_->filter_strength; + for (i = 0; i < NUM_MB_SEGMENTS; ++i) { + VP8SegmentInfo* const m = &enc->dqm_[i]; + // We focus on the quantization of AC coeffs. + const int qstep = kAcTable[clip(m->quant_, 0, 127)] >> 2; + const int base_strength = + VP8FilterStrengthFromDelta(enc->filter_hdr_.sharpness_, qstep); + // Segments with lower complexity ('beta') will be less filtered. + const int f = base_strength * level0 / (256 + m->beta_); + m->fstrength_ = (f < FSTRENGTH_CUTOFF) ? 0 : (f > 63) ? 63 : f; + } + // We record the initial strength (mainly for the case of 1-segment only). + enc->filter_hdr_.level_ = enc->dqm_[0].fstrength_; + enc->filter_hdr_.simple_ = (enc->config_->filter_type == 0); + enc->filter_hdr_.sharpness_ = enc->config_->filter_sharpness; +} + +//------------------------------------------------------------------------------ + +// Note: if you change the values below, remember that the max range +// allowed by the syntax for DQ_UV is [-16,16]. +#define MAX_DQ_UV (6) +#define MIN_DQ_UV (-4) + +// We want to emulate jpeg-like behaviour where the expected "good" quality +// is around q=75. Internally, our "good" middle is around c=50. So we +// map accordingly using linear piece-wise function +static double QualityToCompression(double c) { + const double linear_c = (c < 0.75) ? c * (2. / 3.) : 2. * c - 1.; + // The file size roughly scales as pow(quantizer, 3.). Actually, the + // exponent is somewhere between 2.8 and 3.2, but we're mostly interested + // in the mid-quant range. So we scale the compressibility inversely to + // this power-law: quant ~= compression ^ 1/3. This law holds well for + // low quant. Finer modeling for high-quant would make use of kAcTable[] + // more explicitly. + const double v = pow(linear_c, 1 / 3.); + return v; +} + +static double QualityToJPEGCompression(double c, double alpha) { + // We map the complexity 'alpha' and quality setting 'c' to a compression + // exponent empirically matched to the compression curve of libjpeg6b. + // On average, the WebP output size will be roughly similar to that of a + // JPEG file compressed with same quality factor. + const double amin = 0.30; + const double amax = 0.85; + const double exp_min = 0.4; + const double exp_max = 0.9; + const double slope = (exp_min - exp_max) / (amax - amin); + // Linearly interpolate 'expn' from exp_min to exp_max + // in the [amin, amax] range. + const double expn = (alpha > amax) ? exp_min + : (alpha < amin) ? exp_max + : exp_max + slope * (alpha - amin); + const double v = pow(c, expn); + return v; +} + +static int SegmentsAreEquivalent(const VP8SegmentInfo* const S1, + const VP8SegmentInfo* const S2) { + return (S1->quant_ == S2->quant_) && (S1->fstrength_ == S2->fstrength_); +} + +static void SimplifySegments(VP8Encoder* const enc) { + int map[NUM_MB_SEGMENTS] = { 0, 1, 2, 3 }; + // 'num_segments_' is previously validated and <= NUM_MB_SEGMENTS, but an + // explicit check is needed to avoid a spurious warning about 'i' exceeding + // array bounds of 'dqm_' with some compilers (noticed with gcc-4.9). + const int num_segments = (enc->segment_hdr_.num_segments_ < NUM_MB_SEGMENTS) + ? enc->segment_hdr_.num_segments_ + : NUM_MB_SEGMENTS; + int num_final_segments = 1; + int s1, s2; + for (s1 = 1; s1 < num_segments; ++s1) { // find similar segments + const VP8SegmentInfo* const S1 = &enc->dqm_[s1]; + int found = 0; + // check if we already have similar segment + for (s2 = 0; s2 < num_final_segments; ++s2) { + const VP8SegmentInfo* const S2 = &enc->dqm_[s2]; + if (SegmentsAreEquivalent(S1, S2)) { + found = 1; + break; + } + } + map[s1] = s2; + if (!found) { + if (num_final_segments != s1) { + enc->dqm_[num_final_segments] = enc->dqm_[s1]; + } + ++num_final_segments; + } + } + if (num_final_segments < num_segments) { // Remap + int i = enc->mb_w_ * enc->mb_h_; + while (i-- > 0) enc->mb_info_[i].segment_ = map[enc->mb_info_[i].segment_]; + enc->segment_hdr_.num_segments_ = num_final_segments; + // Replicate the trailing segment infos (it's mostly cosmetics) + for (i = num_final_segments; i < num_segments; ++i) { + enc->dqm_[i] = enc->dqm_[num_final_segments - 1]; + } + } +} + +void VP8SetSegmentParams(VP8Encoder* const enc, float quality) { + int i; + int dq_uv_ac, dq_uv_dc; + const int num_segments = enc->segment_hdr_.num_segments_; + const double amp = SNS_TO_DQ * enc->config_->sns_strength / 100. / 128.; + const double Q = quality / 100.; + const double c_base = enc->config_->emulate_jpeg_size ? + QualityToJPEGCompression(Q, enc->alpha_ / 255.) : + QualityToCompression(Q); + for (i = 0; i < num_segments; ++i) { + // We modulate the base coefficient to accommodate for the quantization + // susceptibility and allow denser segments to be quantized more. + const double expn = 1. - amp * enc->dqm_[i].alpha_; + const double c = pow(c_base, expn); + const int q = (int)(127. * (1. - c)); + assert(expn > 0.); + enc->dqm_[i].quant_ = clip(q, 0, 127); + } + + // purely indicative in the bitstream (except for the 1-segment case) + enc->base_quant_ = enc->dqm_[0].quant_; + + // fill-in values for the unused segments (required by the syntax) + for (i = num_segments; i < NUM_MB_SEGMENTS; ++i) { + enc->dqm_[i].quant_ = enc->base_quant_; + } + + // uv_alpha_ is normally spread around ~60. The useful range is + // typically ~30 (quite bad) to ~100 (ok to decimate UV more). + // We map it to the safe maximal range of MAX/MIN_DQ_UV for dq_uv. + dq_uv_ac = (enc->uv_alpha_ - MID_ALPHA) * (MAX_DQ_UV - MIN_DQ_UV) + / (MAX_ALPHA - MIN_ALPHA); + // we rescale by the user-defined strength of adaptation + dq_uv_ac = dq_uv_ac * enc->config_->sns_strength / 100; + // and make it safe. + dq_uv_ac = clip(dq_uv_ac, MIN_DQ_UV, MAX_DQ_UV); + // We also boost the dc-uv-quant a little, based on sns-strength, since + // U/V channels are quite more reactive to high quants (flat DC-blocks + // tend to appear, and are unpleasant). + dq_uv_dc = -4 * enc->config_->sns_strength / 100; + dq_uv_dc = clip(dq_uv_dc, -15, 15); // 4bit-signed max allowed + + enc->dq_y1_dc_ = 0; // TODO(skal): dq-lum + enc->dq_y2_dc_ = 0; + enc->dq_y2_ac_ = 0; + enc->dq_uv_dc_ = dq_uv_dc; + enc->dq_uv_ac_ = dq_uv_ac; + + SetupFilterStrength(enc); // initialize segments' filtering, eventually + + if (num_segments > 1) SimplifySegments(enc); + + SetupMatrices(enc); // finalize quantization matrices +} + +//------------------------------------------------------------------------------ +// Form the predictions in cache + +// Must be ordered using {DC_PRED, TM_PRED, V_PRED, H_PRED} as index +const uint16_t VP8I16ModeOffsets[4] = { I16DC16, I16TM16, I16VE16, I16HE16 }; +const uint16_t VP8UVModeOffsets[4] = { C8DC8, C8TM8, C8VE8, C8HE8 }; + +// Must be indexed using {B_DC_PRED -> B_HU_PRED} as index +const uint16_t VP8I4ModeOffsets[NUM_BMODES] = { + I4DC4, I4TM4, I4VE4, I4HE4, I4RD4, I4VR4, I4LD4, I4VL4, I4HD4, I4HU4 +}; + +void VP8MakeLuma16Preds(const VP8EncIterator* const it) { + const uint8_t* const left = it->x_ ? it->y_left_ : NULL; + const uint8_t* const top = it->y_ ? it->y_top_ : NULL; + VP8EncPredLuma16(it->yuv_p_, left, top); +} + +void VP8MakeChroma8Preds(const VP8EncIterator* const it) { + const uint8_t* const left = it->x_ ? it->u_left_ : NULL; + const uint8_t* const top = it->y_ ? it->uv_top_ : NULL; + VP8EncPredChroma8(it->yuv_p_, left, top); +} + +void VP8MakeIntra4Preds(const VP8EncIterator* const it) { + VP8EncPredLuma4(it->yuv_p_, it->i4_top_); +} + +//------------------------------------------------------------------------------ +// Quantize + +// Layout: +// +----+----+ +// |YYYY|UUVV| 0 +// |YYYY|UUVV| 4 +// |YYYY|....| 8 +// |YYYY|....| 12 +// +----+----+ + +const uint16_t VP8Scan[16] = { // Luma + 0 + 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS, + 0 + 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS, + 0 + 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS, + 0 + 12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS, +}; + +static const uint16_t VP8ScanUV[4 + 4] = { + 0 + 0 * BPS, 4 + 0 * BPS, 0 + 4 * BPS, 4 + 4 * BPS, // U + 8 + 0 * BPS, 12 + 0 * BPS, 8 + 4 * BPS, 12 + 4 * BPS // V +}; + +//------------------------------------------------------------------------------ +// Distortion measurement + +static const uint16_t kWeightY[16] = { + 38, 32, 20, 9, 32, 28, 17, 7, 20, 17, 10, 4, 9, 7, 4, 2 +}; + +static const uint16_t kWeightTrellis[16] = { +#if USE_TDISTO == 0 + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 +#else + 30, 27, 19, 11, + 27, 24, 17, 10, + 19, 17, 12, 8, + 11, 10, 8, 6 +#endif +}; + +// Init/Copy the common fields in score. +static void InitScore(VP8ModeScore* const rd) { + rd->D = 0; + rd->SD = 0; + rd->R = 0; + rd->H = 0; + rd->nz = 0; + rd->score = MAX_COST; +} + +static void CopyScore(VP8ModeScore* WEBP_RESTRICT const dst, + const VP8ModeScore* WEBP_RESTRICT const src) { + dst->D = src->D; + dst->SD = src->SD; + dst->R = src->R; + dst->H = src->H; + dst->nz = src->nz; // note that nz is not accumulated, but just copied. + dst->score = src->score; +} + +static void AddScore(VP8ModeScore* WEBP_RESTRICT const dst, + const VP8ModeScore* WEBP_RESTRICT const src) { + dst->D += src->D; + dst->SD += src->SD; + dst->R += src->R; + dst->H += src->H; + dst->nz |= src->nz; // here, new nz bits are accumulated. + dst->score += src->score; +} + +//------------------------------------------------------------------------------ +// Performs trellis-optimized quantization. + +// Trellis node +typedef struct { + int8_t prev; // best previous node + int8_t sign; // sign of coeff_i + int16_t level; // level +} Node; + +// Score state +typedef struct { + score_t score; // partial RD score + const uint16_t* costs; // shortcut to cost tables +} ScoreState; + +// If a coefficient was quantized to a value Q (using a neutral bias), +// we test all alternate possibilities between [Q-MIN_DELTA, Q+MAX_DELTA] +// We don't test negative values though. +#define MIN_DELTA 0 // how much lower level to try +#define MAX_DELTA 1 // how much higher +#define NUM_NODES (MIN_DELTA + 1 + MAX_DELTA) +#define NODE(n, l) (nodes[(n)][(l) + MIN_DELTA]) +#define SCORE_STATE(n, l) (score_states[n][(l) + MIN_DELTA]) + +static WEBP_INLINE void SetRDScore(int lambda, VP8ModeScore* const rd) { + rd->score = (rd->R + rd->H) * lambda + RD_DISTO_MULT * (rd->D + rd->SD); +} + +static WEBP_INLINE score_t RDScoreTrellis(int lambda, score_t rate, + score_t distortion) { + return rate * lambda + RD_DISTO_MULT * distortion; +} + +// Coefficient type. +enum { TYPE_I16_AC = 0, TYPE_I16_DC = 1, TYPE_CHROMA_A = 2, TYPE_I4_AC = 3 }; + +static int TrellisQuantizeBlock(const VP8Encoder* WEBP_RESTRICT const enc, + int16_t in[16], int16_t out[16], + int ctx0, int coeff_type, + const VP8Matrix* WEBP_RESTRICT const mtx, + int lambda) { + const ProbaArray* const probas = enc->proba_.coeffs_[coeff_type]; + CostArrayPtr const costs = + (CostArrayPtr)enc->proba_.remapped_costs_[coeff_type]; + const int first = (coeff_type == TYPE_I16_AC) ? 1 : 0; + Node nodes[16][NUM_NODES]; + ScoreState score_states[2][NUM_NODES]; + ScoreState* ss_cur = &SCORE_STATE(0, MIN_DELTA); + ScoreState* ss_prev = &SCORE_STATE(1, MIN_DELTA); + int best_path[3] = {-1, -1, -1}; // store best-last/best-level/best-previous + score_t best_score; + int n, m, p, last; + + { + score_t cost; + const int thresh = mtx->q_[1] * mtx->q_[1] / 4; + const int last_proba = probas[VP8EncBands[first]][ctx0][0]; + + // compute the position of the last interesting coefficient + last = first - 1; + for (n = 15; n >= first; --n) { + const int j = kZigzag[n]; + const int err = in[j] * in[j]; + if (err > thresh) { + last = n; + break; + } + } + // we don't need to go inspect up to n = 16 coeffs. We can just go up + // to last + 1 (inclusive) without losing much. + if (last < 15) ++last; + + // compute 'skip' score. This is the max score one can do. + cost = VP8BitCost(0, last_proba); + best_score = RDScoreTrellis(lambda, cost, 0); + + // initialize source node. + for (m = -MIN_DELTA; m <= MAX_DELTA; ++m) { + const score_t rate = (ctx0 == 0) ? VP8BitCost(1, last_proba) : 0; + ss_cur[m].score = RDScoreTrellis(lambda, rate, 0); + ss_cur[m].costs = costs[first][ctx0]; + } + } + + // traverse trellis. + for (n = first; n <= last; ++n) { + const int j = kZigzag[n]; + const uint32_t Q = mtx->q_[j]; + const uint32_t iQ = mtx->iq_[j]; + const uint32_t B = BIAS(0x00); // neutral bias + // note: it's important to take sign of the _original_ coeff, + // so we don't have to consider level < 0 afterward. + const int sign = (in[j] < 0); + const uint32_t coeff0 = (sign ? -in[j] : in[j]) + mtx->sharpen_[j]; + int level0 = QUANTDIV(coeff0, iQ, B); + int thresh_level = QUANTDIV(coeff0, iQ, BIAS(0x80)); + if (thresh_level > MAX_LEVEL) thresh_level = MAX_LEVEL; + if (level0 > MAX_LEVEL) level0 = MAX_LEVEL; + + { // Swap current and previous score states + ScoreState* const tmp = ss_cur; + ss_cur = ss_prev; + ss_prev = tmp; + } + + // test all alternate level values around level0. + for (m = -MIN_DELTA; m <= MAX_DELTA; ++m) { + Node* const cur = &NODE(n, m); + const int level = level0 + m; + const int ctx = (level > 2) ? 2 : level; + const int band = VP8EncBands[n + 1]; + score_t base_score; + score_t best_cur_score; + int best_prev; + score_t cost, score; + + ss_cur[m].costs = costs[n + 1][ctx]; + if (level < 0 || level > thresh_level) { + ss_cur[m].score = MAX_COST; + // Node is dead. + continue; + } + + { + // Compute delta_error = how much coding this level will + // subtract to max_error as distortion. + // Here, distortion = sum of (|coeff_i| - level_i * Q_i)^2 + const int new_error = coeff0 - level * Q; + const int delta_error = + kWeightTrellis[j] * (new_error * new_error - coeff0 * coeff0); + base_score = RDScoreTrellis(lambda, 0, delta_error); + } + + // Inspect all possible non-dead predecessors. Retain only the best one. + // The base_score is added to all scores so it is only added for the final + // value after the loop. + cost = VP8LevelCost(ss_prev[-MIN_DELTA].costs, level); + best_cur_score = + ss_prev[-MIN_DELTA].score + RDScoreTrellis(lambda, cost, 0); + best_prev = -MIN_DELTA; + for (p = -MIN_DELTA + 1; p <= MAX_DELTA; ++p) { + // Dead nodes (with ss_prev[p].score >= MAX_COST) are automatically + // eliminated since their score can't be better than the current best. + cost = VP8LevelCost(ss_prev[p].costs, level); + // Examine node assuming it's a non-terminal one. + score = ss_prev[p].score + RDScoreTrellis(lambda, cost, 0); + if (score < best_cur_score) { + best_cur_score = score; + best_prev = p; + } + } + best_cur_score += base_score; + // Store best finding in current node. + cur->sign = sign; + cur->level = level; + cur->prev = best_prev; + ss_cur[m].score = best_cur_score; + + // Now, record best terminal node (and thus best entry in the graph). + if (level != 0 && best_cur_score < best_score) { + const score_t last_pos_cost = + (n < 15) ? VP8BitCost(0, probas[band][ctx][0]) : 0; + const score_t last_pos_score = RDScoreTrellis(lambda, last_pos_cost, 0); + score = best_cur_score + last_pos_score; + if (score < best_score) { + best_score = score; + best_path[0] = n; // best eob position + best_path[1] = m; // best node index + best_path[2] = best_prev; // best predecessor + } + } + } + } + + // Fresh start + // Beware! We must preserve in[0]/out[0] value for TYPE_I16_AC case. + if (coeff_type == TYPE_I16_AC) { + memset(in + 1, 0, 15 * sizeof(*in)); + memset(out + 1, 0, 15 * sizeof(*out)); + } else { + memset(in, 0, 16 * sizeof(*in)); + memset(out, 0, 16 * sizeof(*out)); + } + if (best_path[0] == -1) { + return 0; // skip! + } + + { + // Unwind the best path. + // Note: best-prev on terminal node is not necessarily equal to the + // best_prev for non-terminal. So we patch best_path[2] in. + int nz = 0; + int best_node = best_path[1]; + n = best_path[0]; + NODE(n, best_node).prev = best_path[2]; // force best-prev for terminal + + for (; n >= first; --n) { + const Node* const node = &NODE(n, best_node); + const int j = kZigzag[n]; + out[n] = node->sign ? -node->level : node->level; + nz |= node->level; + in[j] = out[n] * mtx->q_[j]; + best_node = node->prev; + } + return (nz != 0); + } +} + +#undef NODE + +//------------------------------------------------------------------------------ +// Performs: difference, transform, quantize, back-transform, add +// all at once. Output is the reconstructed block in *yuv_out, and the +// quantized levels in *levels. + +static int ReconstructIntra16(VP8EncIterator* WEBP_RESTRICT const it, + VP8ModeScore* WEBP_RESTRICT const rd, + uint8_t* WEBP_RESTRICT const yuv_out, + int mode) { + const VP8Encoder* const enc = it->enc_; + const uint8_t* const ref = it->yuv_p_ + VP8I16ModeOffsets[mode]; + const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC; + const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_]; + int nz = 0; + int n; + int16_t tmp[16][16], dc_tmp[16]; + + for (n = 0; n < 16; n += 2) { + VP8FTransform2(src + VP8Scan[n], ref + VP8Scan[n], tmp[n]); + } + VP8FTransformWHT(tmp[0], dc_tmp); + nz |= VP8EncQuantizeBlockWHT(dc_tmp, rd->y_dc_levels, &dqm->y2_) << 24; + + if (DO_TRELLIS_I16 && it->do_trellis_) { + int x, y; + VP8IteratorNzToBytes(it); + for (y = 0, n = 0; y < 4; ++y) { + for (x = 0; x < 4; ++x, ++n) { + const int ctx = it->top_nz_[x] + it->left_nz_[y]; + const int non_zero = TrellisQuantizeBlock( + enc, tmp[n], rd->y_ac_levels[n], ctx, TYPE_I16_AC, &dqm->y1_, + dqm->lambda_trellis_i16_); + it->top_nz_[x] = it->left_nz_[y] = non_zero; + rd->y_ac_levels[n][0] = 0; + nz |= non_zero << n; + } + } + } else { + for (n = 0; n < 16; n += 2) { + // Zero-out the first coeff, so that: a) nz is correct below, and + // b) finding 'last' non-zero coeffs in SetResidualCoeffs() is simplified. + tmp[n][0] = tmp[n + 1][0] = 0; + nz |= VP8EncQuantize2Blocks(tmp[n], rd->y_ac_levels[n], &dqm->y1_) << n; + assert(rd->y_ac_levels[n + 0][0] == 0); + assert(rd->y_ac_levels[n + 1][0] == 0); + } + } + + // Transform back + VP8TransformWHT(dc_tmp, tmp[0]); + for (n = 0; n < 16; n += 2) { + VP8ITransform(ref + VP8Scan[n], tmp[n], yuv_out + VP8Scan[n], 1); + } + + return nz; +} + +static int ReconstructIntra4(VP8EncIterator* WEBP_RESTRICT const it, + int16_t levels[16], + const uint8_t* WEBP_RESTRICT const src, + uint8_t* WEBP_RESTRICT const yuv_out, + int mode) { + const VP8Encoder* const enc = it->enc_; + const uint8_t* const ref = it->yuv_p_ + VP8I4ModeOffsets[mode]; + const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_]; + int nz = 0; + int16_t tmp[16]; + + VP8FTransform(src, ref, tmp); + if (DO_TRELLIS_I4 && it->do_trellis_) { + const int x = it->i4_ & 3, y = it->i4_ >> 2; + const int ctx = it->top_nz_[x] + it->left_nz_[y]; + nz = TrellisQuantizeBlock(enc, tmp, levels, ctx, TYPE_I4_AC, &dqm->y1_, + dqm->lambda_trellis_i4_); + } else { + nz = VP8EncQuantizeBlock(tmp, levels, &dqm->y1_); + } + VP8ITransform(ref, tmp, yuv_out, 0); + return nz; +} + +//------------------------------------------------------------------------------ +// DC-error diffusion + +// Diffusion weights. We under-correct a bit (15/16th of the error is actually +// diffused) to avoid 'rainbow' chessboard pattern of blocks at q~=0. +#define C1 7 // fraction of error sent to the 4x4 block below +#define C2 8 // fraction of error sent to the 4x4 block on the right +#define DSHIFT 4 +#define DSCALE 1 // storage descaling, needed to make the error fit int8_t + +// Quantize as usual, but also compute and return the quantization error. +// Error is already divided by DSHIFT. +static int QuantizeSingle(int16_t* WEBP_RESTRICT const v, + const VP8Matrix* WEBP_RESTRICT const mtx) { + int V = *v; + const int sign = (V < 0); + if (sign) V = -V; + if (V > (int)mtx->zthresh_[0]) { + const int qV = QUANTDIV(V, mtx->iq_[0], mtx->bias_[0]) * mtx->q_[0]; + const int err = (V - qV); + *v = sign ? -qV : qV; + return (sign ? -err : err) >> DSCALE; + } + *v = 0; + return (sign ? -V : V) >> DSCALE; +} + +static void CorrectDCValues(const VP8EncIterator* WEBP_RESTRICT const it, + const VP8Matrix* WEBP_RESTRICT const mtx, + int16_t tmp[][16], + VP8ModeScore* WEBP_RESTRICT const rd) { + // | top[0] | top[1] + // --------+--------+--------- + // left[0] | tmp[0] tmp[1] <-> err0 err1 + // left[1] | tmp[2] tmp[3] err2 err3 + // + // Final errors {err1,err2,err3} are preserved and later restored + // as top[]/left[] on the next block. + int ch; + for (ch = 0; ch <= 1; ++ch) { + const int8_t* const top = it->top_derr_[it->x_][ch]; + const int8_t* const left = it->left_derr_[ch]; + int16_t (* const c)[16] = &tmp[ch * 4]; + int err0, err1, err2, err3; + c[0][0] += (C1 * top[0] + C2 * left[0]) >> (DSHIFT - DSCALE); + err0 = QuantizeSingle(&c[0][0], mtx); + c[1][0] += (C1 * top[1] + C2 * err0) >> (DSHIFT - DSCALE); + err1 = QuantizeSingle(&c[1][0], mtx); + c[2][0] += (C1 * err0 + C2 * left[1]) >> (DSHIFT - DSCALE); + err2 = QuantizeSingle(&c[2][0], mtx); + c[3][0] += (C1 * err1 + C2 * err2) >> (DSHIFT - DSCALE); + err3 = QuantizeSingle(&c[3][0], mtx); + // error 'err' is bounded by mtx->q_[0] which is 132 at max. Hence + // err >> DSCALE will fit in an int8_t type if DSCALE>=1. + assert(abs(err1) <= 127 && abs(err2) <= 127 && abs(err3) <= 127); + rd->derr[ch][0] = (int8_t)err1; + rd->derr[ch][1] = (int8_t)err2; + rd->derr[ch][2] = (int8_t)err3; + } +} + +static void StoreDiffusionErrors(VP8EncIterator* WEBP_RESTRICT const it, + const VP8ModeScore* WEBP_RESTRICT const rd) { + int ch; + for (ch = 0; ch <= 1; ++ch) { + int8_t* const top = it->top_derr_[it->x_][ch]; + int8_t* const left = it->left_derr_[ch]; + left[0] = rd->derr[ch][0]; // restore err1 + left[1] = 3 * rd->derr[ch][2] >> 2; // ... 3/4th of err3 + top[0] = rd->derr[ch][1]; // ... err2 + top[1] = rd->derr[ch][2] - left[1]; // ... 1/4th of err3. + } +} + +#undef C1 +#undef C2 +#undef DSHIFT +#undef DSCALE + +//------------------------------------------------------------------------------ + +static int ReconstructUV(VP8EncIterator* WEBP_RESTRICT const it, + VP8ModeScore* WEBP_RESTRICT const rd, + uint8_t* WEBP_RESTRICT const yuv_out, int mode) { + const VP8Encoder* const enc = it->enc_; + const uint8_t* const ref = it->yuv_p_ + VP8UVModeOffsets[mode]; + const uint8_t* const src = it->yuv_in_ + U_OFF_ENC; + const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_]; + int nz = 0; + int n; + int16_t tmp[8][16]; + + for (n = 0; n < 8; n += 2) { + VP8FTransform2(src + VP8ScanUV[n], ref + VP8ScanUV[n], tmp[n]); + } + if (it->top_derr_ != NULL) CorrectDCValues(it, &dqm->uv_, tmp, rd); + + if (DO_TRELLIS_UV && it->do_trellis_) { + int ch, x, y; + for (ch = 0, n = 0; ch <= 2; ch += 2) { + for (y = 0; y < 2; ++y) { + for (x = 0; x < 2; ++x, ++n) { + const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; + const int non_zero = TrellisQuantizeBlock( + enc, tmp[n], rd->uv_levels[n], ctx, TYPE_CHROMA_A, &dqm->uv_, + dqm->lambda_trellis_uv_); + it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = non_zero; + nz |= non_zero << n; + } + } + } + } else { + for (n = 0; n < 8; n += 2) { + nz |= VP8EncQuantize2Blocks(tmp[n], rd->uv_levels[n], &dqm->uv_) << n; + } + } + + for (n = 0; n < 8; n += 2) { + VP8ITransform(ref + VP8ScanUV[n], tmp[n], yuv_out + VP8ScanUV[n], 1); + } + return (nz << 16); +} + +//------------------------------------------------------------------------------ +// RD-opt decision. Reconstruct each modes, evalue distortion and bit-cost. +// Pick the mode is lower RD-cost = Rate + lambda * Distortion. + +static void StoreMaxDelta(VP8SegmentInfo* const dqm, const int16_t DCs[16]) { + // We look at the first three AC coefficients to determine what is the average + // delta between each sub-4x4 block. + const int v0 = abs(DCs[1]); + const int v1 = abs(DCs[2]); + const int v2 = abs(DCs[4]); + int max_v = (v1 > v0) ? v1 : v0; + max_v = (v2 > max_v) ? v2 : max_v; + if (max_v > dqm->max_edge_) dqm->max_edge_ = max_v; +} + +static void SwapModeScore(VP8ModeScore** a, VP8ModeScore** b) { + VP8ModeScore* const tmp = *a; + *a = *b; + *b = tmp; +} + +static void SwapPtr(uint8_t** a, uint8_t** b) { + uint8_t* const tmp = *a; + *a = *b; + *b = tmp; +} + +static void SwapOut(VP8EncIterator* const it) { + SwapPtr(&it->yuv_out_, &it->yuv_out2_); +} + +static void PickBestIntra16(VP8EncIterator* WEBP_RESTRICT const it, + VP8ModeScore* WEBP_RESTRICT rd) { + const int kNumBlocks = 16; + VP8SegmentInfo* const dqm = &it->enc_->dqm_[it->mb_->segment_]; + const int lambda = dqm->lambda_i16_; + const int tlambda = dqm->tlambda_; + const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC; + VP8ModeScore rd_tmp; + VP8ModeScore* rd_cur = &rd_tmp; + VP8ModeScore* rd_best = rd; + int mode; + int is_flat = IsFlatSource16(it->yuv_in_ + Y_OFF_ENC); + + rd->mode_i16 = -1; + for (mode = 0; mode < NUM_PRED_MODES; ++mode) { + uint8_t* const tmp_dst = it->yuv_out2_ + Y_OFF_ENC; // scratch buffer + rd_cur->mode_i16 = mode; + + // Reconstruct + rd_cur->nz = ReconstructIntra16(it, rd_cur, tmp_dst, mode); + + // Measure RD-score + rd_cur->D = VP8SSE16x16(src, tmp_dst); + rd_cur->SD = + tlambda ? MULT_8B(tlambda, VP8TDisto16x16(src, tmp_dst, kWeightY)) : 0; + rd_cur->H = VP8FixedCostsI16[mode]; + rd_cur->R = VP8GetCostLuma16(it, rd_cur); + if (is_flat) { + // refine the first impression (which was in pixel space) + is_flat = IsFlat(rd_cur->y_ac_levels[0], kNumBlocks, FLATNESS_LIMIT_I16); + if (is_flat) { + // Block is very flat. We put emphasis on the distortion being very low! + rd_cur->D *= 2; + rd_cur->SD *= 2; + } + } + + // Since we always examine Intra16 first, we can overwrite *rd directly. + SetRDScore(lambda, rd_cur); + if (mode == 0 || rd_cur->score < rd_best->score) { + SwapModeScore(&rd_cur, &rd_best); + SwapOut(it); + } + } + if (rd_best != rd) { + memcpy(rd, rd_best, sizeof(*rd)); + } + SetRDScore(dqm->lambda_mode_, rd); // finalize score for mode decision. + VP8SetIntra16Mode(it, rd->mode_i16); + + // we have a blocky macroblock (only DCs are non-zero) with fairly high + // distortion, record max delta so we can later adjust the minimal filtering + // strength needed to smooth these blocks out. + if ((rd->nz & 0x100ffff) == 0x1000000 && rd->D > dqm->min_disto_) { + StoreMaxDelta(dqm, rd->y_dc_levels); + } +} + +//------------------------------------------------------------------------------ + +// return the cost array corresponding to the surrounding prediction modes. +static const uint16_t* GetCostModeI4(VP8EncIterator* WEBP_RESTRICT const it, + const uint8_t modes[16]) { + const int preds_w = it->enc_->preds_w_; + const int x = (it->i4_ & 3), y = it->i4_ >> 2; + const int left = (x == 0) ? it->preds_[y * preds_w - 1] : modes[it->i4_ - 1]; + const int top = (y == 0) ? it->preds_[-preds_w + x] : modes[it->i4_ - 4]; + return VP8FixedCostsI4[top][left]; +} + +static int PickBestIntra4(VP8EncIterator* WEBP_RESTRICT const it, + VP8ModeScore* WEBP_RESTRICT const rd) { + const VP8Encoder* const enc = it->enc_; + const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_]; + const int lambda = dqm->lambda_i4_; + const int tlambda = dqm->tlambda_; + const uint8_t* const src0 = it->yuv_in_ + Y_OFF_ENC; + uint8_t* const best_blocks = it->yuv_out2_ + Y_OFF_ENC; + int total_header_bits = 0; + VP8ModeScore rd_best; + + if (enc->max_i4_header_bits_ == 0) { + return 0; + } + + InitScore(&rd_best); + rd_best.H = 211; // '211' is the value of VP8BitCost(0, 145) + SetRDScore(dqm->lambda_mode_, &rd_best); + VP8IteratorStartI4(it); + do { + const int kNumBlocks = 1; + VP8ModeScore rd_i4; + int mode; + int best_mode = -1; + const uint8_t* const src = src0 + VP8Scan[it->i4_]; + const uint16_t* const mode_costs = GetCostModeI4(it, rd->modes_i4); + uint8_t* best_block = best_blocks + VP8Scan[it->i4_]; + uint8_t* tmp_dst = it->yuv_p_ + I4TMP; // scratch buffer. + + InitScore(&rd_i4); + VP8MakeIntra4Preds(it); + for (mode = 0; mode < NUM_BMODES; ++mode) { + VP8ModeScore rd_tmp; + int16_t tmp_levels[16]; + + // Reconstruct + rd_tmp.nz = + ReconstructIntra4(it, tmp_levels, src, tmp_dst, mode) << it->i4_; + + // Compute RD-score + rd_tmp.D = VP8SSE4x4(src, tmp_dst); + rd_tmp.SD = + tlambda ? MULT_8B(tlambda, VP8TDisto4x4(src, tmp_dst, kWeightY)) + : 0; + rd_tmp.H = mode_costs[mode]; + + // Add flatness penalty, to avoid flat area to be mispredicted + // by a complex mode. + if (mode > 0 && IsFlat(tmp_levels, kNumBlocks, FLATNESS_LIMIT_I4)) { + rd_tmp.R = FLATNESS_PENALTY * kNumBlocks; + } else { + rd_tmp.R = 0; + } + + // early-out check + SetRDScore(lambda, &rd_tmp); + if (best_mode >= 0 && rd_tmp.score >= rd_i4.score) continue; + + // finish computing score + rd_tmp.R += VP8GetCostLuma4(it, tmp_levels); + SetRDScore(lambda, &rd_tmp); + + if (best_mode < 0 || rd_tmp.score < rd_i4.score) { + CopyScore(&rd_i4, &rd_tmp); + best_mode = mode; + SwapPtr(&tmp_dst, &best_block); + memcpy(rd_best.y_ac_levels[it->i4_], tmp_levels, + sizeof(rd_best.y_ac_levels[it->i4_])); + } + } + SetRDScore(dqm->lambda_mode_, &rd_i4); + AddScore(&rd_best, &rd_i4); + if (rd_best.score >= rd->score) { + return 0; + } + total_header_bits += (int)rd_i4.H; // <- equal to mode_costs[best_mode]; + if (total_header_bits > enc->max_i4_header_bits_) { + return 0; + } + // Copy selected samples if not in the right place already. + if (best_block != best_blocks + VP8Scan[it->i4_]) { + VP8Copy4x4(best_block, best_blocks + VP8Scan[it->i4_]); + } + rd->modes_i4[it->i4_] = best_mode; + it->top_nz_[it->i4_ & 3] = it->left_nz_[it->i4_ >> 2] = (rd_i4.nz ? 1 : 0); + } while (VP8IteratorRotateI4(it, best_blocks)); + + // finalize state + CopyScore(rd, &rd_best); + VP8SetIntra4Mode(it, rd->modes_i4); + SwapOut(it); + memcpy(rd->y_ac_levels, rd_best.y_ac_levels, sizeof(rd->y_ac_levels)); + return 1; // select intra4x4 over intra16x16 +} + +//------------------------------------------------------------------------------ + +static void PickBestUV(VP8EncIterator* WEBP_RESTRICT const it, + VP8ModeScore* WEBP_RESTRICT const rd) { + const int kNumBlocks = 8; + const VP8SegmentInfo* const dqm = &it->enc_->dqm_[it->mb_->segment_]; + const int lambda = dqm->lambda_uv_; + const uint8_t* const src = it->yuv_in_ + U_OFF_ENC; + uint8_t* tmp_dst = it->yuv_out2_ + U_OFF_ENC; // scratch buffer + uint8_t* dst0 = it->yuv_out_ + U_OFF_ENC; + uint8_t* dst = dst0; + VP8ModeScore rd_best; + int mode; + + rd->mode_uv = -1; + InitScore(&rd_best); + for (mode = 0; mode < NUM_PRED_MODES; ++mode) { + VP8ModeScore rd_uv; + + // Reconstruct + rd_uv.nz = ReconstructUV(it, &rd_uv, tmp_dst, mode); + + // Compute RD-score + rd_uv.D = VP8SSE16x8(src, tmp_dst); + rd_uv.SD = 0; // not calling TDisto here: it tends to flatten areas. + rd_uv.H = VP8FixedCostsUV[mode]; + rd_uv.R = VP8GetCostUV(it, &rd_uv); + if (mode > 0 && IsFlat(rd_uv.uv_levels[0], kNumBlocks, FLATNESS_LIMIT_UV)) { + rd_uv.R += FLATNESS_PENALTY * kNumBlocks; + } + + SetRDScore(lambda, &rd_uv); + if (mode == 0 || rd_uv.score < rd_best.score) { + CopyScore(&rd_best, &rd_uv); + rd->mode_uv = mode; + memcpy(rd->uv_levels, rd_uv.uv_levels, sizeof(rd->uv_levels)); + if (it->top_derr_ != NULL) { + memcpy(rd->derr, rd_uv.derr, sizeof(rd_uv.derr)); + } + SwapPtr(&dst, &tmp_dst); + } + } + VP8SetIntraUVMode(it, rd->mode_uv); + AddScore(rd, &rd_best); + if (dst != dst0) { // copy 16x8 block if needed + VP8Copy16x8(dst, dst0); + } + if (it->top_derr_ != NULL) { // store diffusion errors for next block + StoreDiffusionErrors(it, rd); + } +} + +//------------------------------------------------------------------------------ +// Final reconstruction and quantization. + +static void SimpleQuantize(VP8EncIterator* WEBP_RESTRICT const it, + VP8ModeScore* WEBP_RESTRICT const rd) { + const VP8Encoder* const enc = it->enc_; + const int is_i16 = (it->mb_->type_ == 1); + int nz = 0; + + if (is_i16) { + nz = ReconstructIntra16(it, rd, it->yuv_out_ + Y_OFF_ENC, it->preds_[0]); + } else { + VP8IteratorStartI4(it); + do { + const int mode = + it->preds_[(it->i4_ & 3) + (it->i4_ >> 2) * enc->preds_w_]; + const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC + VP8Scan[it->i4_]; + uint8_t* const dst = it->yuv_out_ + Y_OFF_ENC + VP8Scan[it->i4_]; + VP8MakeIntra4Preds(it); + nz |= ReconstructIntra4(it, rd->y_ac_levels[it->i4_], + src, dst, mode) << it->i4_; + } while (VP8IteratorRotateI4(it, it->yuv_out_ + Y_OFF_ENC)); + } + + nz |= ReconstructUV(it, rd, it->yuv_out_ + U_OFF_ENC, it->mb_->uv_mode_); + rd->nz = nz; +} + +// Refine intra16/intra4 sub-modes based on distortion only (not rate). +static void RefineUsingDistortion(VP8EncIterator* WEBP_RESTRICT const it, + int try_both_modes, int refine_uv_mode, + VP8ModeScore* WEBP_RESTRICT const rd) { + score_t best_score = MAX_COST; + int nz = 0; + int mode; + int is_i16 = try_both_modes || (it->mb_->type_ == 1); + + const VP8SegmentInfo* const dqm = &it->enc_->dqm_[it->mb_->segment_]; + // Some empiric constants, of approximate order of magnitude. + const int lambda_d_i16 = 106; + const int lambda_d_i4 = 11; + const int lambda_d_uv = 120; + score_t score_i4 = dqm->i4_penalty_; + score_t i4_bit_sum = 0; + const score_t bit_limit = try_both_modes ? it->enc_->mb_header_limit_ + : MAX_COST; // no early-out allowed + + if (is_i16) { // First, evaluate Intra16 distortion + int best_mode = -1; + const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC; + for (mode = 0; mode < NUM_PRED_MODES; ++mode) { + const uint8_t* const ref = it->yuv_p_ + VP8I16ModeOffsets[mode]; + const score_t score = (score_t)VP8SSE16x16(src, ref) * RD_DISTO_MULT + + VP8FixedCostsI16[mode] * lambda_d_i16; + if (mode > 0 && VP8FixedCostsI16[mode] > bit_limit) { + continue; + } + + if (score < best_score) { + best_mode = mode; + best_score = score; + } + } + if (it->x_ == 0 || it->y_ == 0) { + // avoid starting a checkerboard resonance from the border. See bug #432. + if (IsFlatSource16(src)) { + best_mode = (it->x_ == 0) ? 0 : 2; + try_both_modes = 0; // stick to i16 + } + } + VP8SetIntra16Mode(it, best_mode); + // we'll reconstruct later, if i16 mode actually gets selected + } + + // Next, evaluate Intra4 + if (try_both_modes || !is_i16) { + // We don't evaluate the rate here, but just account for it through a + // constant penalty (i4 mode usually needs more bits compared to i16). + is_i16 = 0; + VP8IteratorStartI4(it); + do { + int best_i4_mode = -1; + score_t best_i4_score = MAX_COST; + const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC + VP8Scan[it->i4_]; + const uint16_t* const mode_costs = GetCostModeI4(it, rd->modes_i4); + + VP8MakeIntra4Preds(it); + for (mode = 0; mode < NUM_BMODES; ++mode) { + const uint8_t* const ref = it->yuv_p_ + VP8I4ModeOffsets[mode]; + const score_t score = VP8SSE4x4(src, ref) * RD_DISTO_MULT + + mode_costs[mode] * lambda_d_i4; + if (score < best_i4_score) { + best_i4_mode = mode; + best_i4_score = score; + } + } + i4_bit_sum += mode_costs[best_i4_mode]; + rd->modes_i4[it->i4_] = best_i4_mode; + score_i4 += best_i4_score; + if (score_i4 >= best_score || i4_bit_sum > bit_limit) { + // Intra4 won't be better than Intra16. Bail out and pick Intra16. + is_i16 = 1; + break; + } else { // reconstruct partial block inside yuv_out2_ buffer + uint8_t* const tmp_dst = it->yuv_out2_ + Y_OFF_ENC + VP8Scan[it->i4_]; + nz |= ReconstructIntra4(it, rd->y_ac_levels[it->i4_], + src, tmp_dst, best_i4_mode) << it->i4_; + } + } while (VP8IteratorRotateI4(it, it->yuv_out2_ + Y_OFF_ENC)); + } + + // Final reconstruction, depending on which mode is selected. + if (!is_i16) { + VP8SetIntra4Mode(it, rd->modes_i4); + SwapOut(it); + best_score = score_i4; + } else { + nz = ReconstructIntra16(it, rd, it->yuv_out_ + Y_OFF_ENC, it->preds_[0]); + } + + // ... and UV! + if (refine_uv_mode) { + int best_mode = -1; + score_t best_uv_score = MAX_COST; + const uint8_t* const src = it->yuv_in_ + U_OFF_ENC; + for (mode = 0; mode < NUM_PRED_MODES; ++mode) { + const uint8_t* const ref = it->yuv_p_ + VP8UVModeOffsets[mode]; + const score_t score = VP8SSE16x8(src, ref) * RD_DISTO_MULT + + VP8FixedCostsUV[mode] * lambda_d_uv; + if (score < best_uv_score) { + best_mode = mode; + best_uv_score = score; + } + } + VP8SetIntraUVMode(it, best_mode); + } + nz |= ReconstructUV(it, rd, it->yuv_out_ + U_OFF_ENC, it->mb_->uv_mode_); + + rd->nz = nz; + rd->score = best_score; +} + +//------------------------------------------------------------------------------ +// Entry point + +int VP8Decimate(VP8EncIterator* WEBP_RESTRICT const it, + VP8ModeScore* WEBP_RESTRICT const rd, + VP8RDLevel rd_opt) { + int is_skipped; + const int method = it->enc_->method_; + + InitScore(rd); + + // We can perform predictions for Luma16x16 and Chroma8x8 already. + // Luma4x4 predictions needs to be done as-we-go. + VP8MakeLuma16Preds(it); + VP8MakeChroma8Preds(it); + + if (rd_opt > RD_OPT_NONE) { + it->do_trellis_ = (rd_opt >= RD_OPT_TRELLIS_ALL); + PickBestIntra16(it, rd); + if (method >= 2) { + PickBestIntra4(it, rd); + } + PickBestUV(it, rd); + if (rd_opt == RD_OPT_TRELLIS) { // finish off with trellis-optim now + it->do_trellis_ = 1; + SimpleQuantize(it, rd); + } + } else { + // At this point we have heuristically decided intra16 / intra4. + // For method >= 2, pick the best intra4/intra16 based on SSE (~tad slower). + // For method <= 1, we don't re-examine the decision but just go ahead with + // quantization/reconstruction. + RefineUsingDistortion(it, (method >= 2), (method >= 1), rd); + } + is_skipped = (rd->nz == 0); + VP8SetSkip(it, is_skipped); + return is_skipped; +} diff --git a/third-party/webp/libwebp/src/enc/syntax_enc.c b/third-party/webp/libwebp/src/enc/syntax_enc.c new file mode 100644 index 0000000000..9b8f524d69 --- /dev/null +++ b/third-party/webp/libwebp/src/enc/syntax_enc.c @@ -0,0 +1,392 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Header syntax writing +// +// Author: Skal (pascal.massimino@gmail.com) + +#include + +#include "src/utils/utils.h" +#include "src/webp/format_constants.h" // RIFF constants +#include "src/webp/mux_types.h" // ALPHA_FLAG +#include "src/enc/vp8i_enc.h" + +//------------------------------------------------------------------------------ +// Helper functions + +static int IsVP8XNeeded(const VP8Encoder* const enc) { + return !!enc->has_alpha_; // Currently the only case when VP8X is needed. + // This could change in the future. +} + +static int PutPaddingByte(const WebPPicture* const pic) { + const uint8_t pad_byte[1] = { 0 }; + return !!pic->writer(pad_byte, 1, pic); +} + +//------------------------------------------------------------------------------ +// Writers for header's various pieces (in order of appearance) + +static WebPEncodingError PutRIFFHeader(const VP8Encoder* const enc, + size_t riff_size) { + const WebPPicture* const pic = enc->pic_; + uint8_t riff[RIFF_HEADER_SIZE] = { + 'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'E', 'B', 'P' + }; + assert(riff_size == (uint32_t)riff_size); + PutLE32(riff + TAG_SIZE, (uint32_t)riff_size); + if (!pic->writer(riff, sizeof(riff), pic)) { + return VP8_ENC_ERROR_BAD_WRITE; + } + return VP8_ENC_OK; +} + +static WebPEncodingError PutVP8XHeader(const VP8Encoder* const enc) { + const WebPPicture* const pic = enc->pic_; + uint8_t vp8x[CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE] = { + 'V', 'P', '8', 'X' + }; + uint32_t flags = 0; + + assert(IsVP8XNeeded(enc)); + assert(pic->width >= 1 && pic->height >= 1); + assert(pic->width <= MAX_CANVAS_SIZE && pic->height <= MAX_CANVAS_SIZE); + + if (enc->has_alpha_) { + flags |= ALPHA_FLAG; + } + + PutLE32(vp8x + TAG_SIZE, VP8X_CHUNK_SIZE); + PutLE32(vp8x + CHUNK_HEADER_SIZE, flags); + PutLE24(vp8x + CHUNK_HEADER_SIZE + 4, pic->width - 1); + PutLE24(vp8x + CHUNK_HEADER_SIZE + 7, pic->height - 1); + if (!pic->writer(vp8x, sizeof(vp8x), pic)) { + return VP8_ENC_ERROR_BAD_WRITE; + } + return VP8_ENC_OK; +} + +static WebPEncodingError PutAlphaChunk(const VP8Encoder* const enc) { + const WebPPicture* const pic = enc->pic_; + uint8_t alpha_chunk_hdr[CHUNK_HEADER_SIZE] = { + 'A', 'L', 'P', 'H' + }; + + assert(enc->has_alpha_); + + // Alpha chunk header. + PutLE32(alpha_chunk_hdr + TAG_SIZE, enc->alpha_data_size_); + if (!pic->writer(alpha_chunk_hdr, sizeof(alpha_chunk_hdr), pic)) { + return VP8_ENC_ERROR_BAD_WRITE; + } + + // Alpha chunk data. + if (!pic->writer(enc->alpha_data_, enc->alpha_data_size_, pic)) { + return VP8_ENC_ERROR_BAD_WRITE; + } + + // Padding. + if ((enc->alpha_data_size_ & 1) && !PutPaddingByte(pic)) { + return VP8_ENC_ERROR_BAD_WRITE; + } + return VP8_ENC_OK; +} + +static WebPEncodingError PutVP8Header(const WebPPicture* const pic, + size_t vp8_size) { + uint8_t vp8_chunk_hdr[CHUNK_HEADER_SIZE] = { + 'V', 'P', '8', ' ' + }; + assert(vp8_size == (uint32_t)vp8_size); + PutLE32(vp8_chunk_hdr + TAG_SIZE, (uint32_t)vp8_size); + if (!pic->writer(vp8_chunk_hdr, sizeof(vp8_chunk_hdr), pic)) { + return VP8_ENC_ERROR_BAD_WRITE; + } + return VP8_ENC_OK; +} + +static WebPEncodingError PutVP8FrameHeader(const WebPPicture* const pic, + int profile, size_t size0) { + uint8_t vp8_frm_hdr[VP8_FRAME_HEADER_SIZE]; + uint32_t bits; + + if (size0 >= VP8_MAX_PARTITION0_SIZE) { // partition #0 is too big to fit + return VP8_ENC_ERROR_PARTITION0_OVERFLOW; + } + + // Paragraph 9.1. + bits = 0 // keyframe (1b) + | (profile << 1) // profile (3b) + | (1 << 4) // visible (1b) + | ((uint32_t)size0 << 5); // partition length (19b) + vp8_frm_hdr[0] = (bits >> 0) & 0xff; + vp8_frm_hdr[1] = (bits >> 8) & 0xff; + vp8_frm_hdr[2] = (bits >> 16) & 0xff; + // signature + vp8_frm_hdr[3] = (VP8_SIGNATURE >> 16) & 0xff; + vp8_frm_hdr[4] = (VP8_SIGNATURE >> 8) & 0xff; + vp8_frm_hdr[5] = (VP8_SIGNATURE >> 0) & 0xff; + // dimensions + vp8_frm_hdr[6] = pic->width & 0xff; + vp8_frm_hdr[7] = pic->width >> 8; + vp8_frm_hdr[8] = pic->height & 0xff; + vp8_frm_hdr[9] = pic->height >> 8; + + if (!pic->writer(vp8_frm_hdr, sizeof(vp8_frm_hdr), pic)) { + return VP8_ENC_ERROR_BAD_WRITE; + } + return VP8_ENC_OK; +} + +// WebP Headers. +static int PutWebPHeaders(const VP8Encoder* const enc, size_t size0, + size_t vp8_size, size_t riff_size) { + WebPPicture* const pic = enc->pic_; + WebPEncodingError err = VP8_ENC_OK; + + // RIFF header. + err = PutRIFFHeader(enc, riff_size); + if (err != VP8_ENC_OK) goto Error; + + // VP8X. + if (IsVP8XNeeded(enc)) { + err = PutVP8XHeader(enc); + if (err != VP8_ENC_OK) goto Error; + } + + // Alpha. + if (enc->has_alpha_) { + err = PutAlphaChunk(enc); + if (err != VP8_ENC_OK) goto Error; + } + + // VP8 header. + err = PutVP8Header(pic, vp8_size); + if (err != VP8_ENC_OK) goto Error; + + // VP8 frame header. + err = PutVP8FrameHeader(pic, enc->profile_, size0); + if (err != VP8_ENC_OK) goto Error; + + // All OK. + return 1; + + // Error. + Error: + return WebPEncodingSetError(pic, err); +} + +// Segmentation header +static void PutSegmentHeader(VP8BitWriter* const bw, + const VP8Encoder* const enc) { + const VP8EncSegmentHeader* const hdr = &enc->segment_hdr_; + const VP8EncProba* const proba = &enc->proba_; + if (VP8PutBitUniform(bw, (hdr->num_segments_ > 1))) { + // We always 'update' the quant and filter strength values + const int update_data = 1; + int s; + VP8PutBitUniform(bw, hdr->update_map_); + if (VP8PutBitUniform(bw, update_data)) { + // we always use absolute values, not relative ones + VP8PutBitUniform(bw, 1); // (segment_feature_mode = 1. Paragraph 9.3.) + for (s = 0; s < NUM_MB_SEGMENTS; ++s) { + VP8PutSignedBits(bw, enc->dqm_[s].quant_, 7); + } + for (s = 0; s < NUM_MB_SEGMENTS; ++s) { + VP8PutSignedBits(bw, enc->dqm_[s].fstrength_, 6); + } + } + if (hdr->update_map_) { + for (s = 0; s < 3; ++s) { + if (VP8PutBitUniform(bw, (proba->segments_[s] != 255u))) { + VP8PutBits(bw, proba->segments_[s], 8); + } + } + } + } +} + +// Filtering parameters header +static void PutFilterHeader(VP8BitWriter* const bw, + const VP8EncFilterHeader* const hdr) { + const int use_lf_delta = (hdr->i4x4_lf_delta_ != 0); + VP8PutBitUniform(bw, hdr->simple_); + VP8PutBits(bw, hdr->level_, 6); + VP8PutBits(bw, hdr->sharpness_, 3); + if (VP8PutBitUniform(bw, use_lf_delta)) { + // '0' is the default value for i4x4_lf_delta_ at frame #0. + const int need_update = (hdr->i4x4_lf_delta_ != 0); + if (VP8PutBitUniform(bw, need_update)) { + // we don't use ref_lf_delta => emit four 0 bits + VP8PutBits(bw, 0, 4); + // we use mode_lf_delta for i4x4 + VP8PutSignedBits(bw, hdr->i4x4_lf_delta_, 6); + VP8PutBits(bw, 0, 3); // all others unused + } + } +} + +// Nominal quantization parameters +static void PutQuant(VP8BitWriter* const bw, + const VP8Encoder* const enc) { + VP8PutBits(bw, enc->base_quant_, 7); + VP8PutSignedBits(bw, enc->dq_y1_dc_, 4); + VP8PutSignedBits(bw, enc->dq_y2_dc_, 4); + VP8PutSignedBits(bw, enc->dq_y2_ac_, 4); + VP8PutSignedBits(bw, enc->dq_uv_dc_, 4); + VP8PutSignedBits(bw, enc->dq_uv_ac_, 4); +} + +// Partition sizes +static int EmitPartitionsSize(const VP8Encoder* const enc, + WebPPicture* const pic) { + uint8_t buf[3 * (MAX_NUM_PARTITIONS - 1)]; + int p; + for (p = 0; p < enc->num_parts_ - 1; ++p) { + const size_t part_size = VP8BitWriterSize(enc->parts_ + p); + if (part_size >= VP8_MAX_PARTITION_SIZE) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_PARTITION_OVERFLOW); + } + buf[3 * p + 0] = (part_size >> 0) & 0xff; + buf[3 * p + 1] = (part_size >> 8) & 0xff; + buf[3 * p + 2] = (part_size >> 16) & 0xff; + } + if (p && !pic->writer(buf, 3 * p, pic)) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_WRITE); + } + return 1; +} + +//------------------------------------------------------------------------------ + +static int GeneratePartition0(VP8Encoder* const enc) { + VP8BitWriter* const bw = &enc->bw_; + const int mb_size = enc->mb_w_ * enc->mb_h_; + uint64_t pos1, pos2, pos3; + + pos1 = VP8BitWriterPos(bw); + if (!VP8BitWriterInit(bw, mb_size * 7 / 8)) { // ~7 bits per macroblock + return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + VP8PutBitUniform(bw, 0); // colorspace + VP8PutBitUniform(bw, 0); // clamp type + + PutSegmentHeader(bw, enc); + PutFilterHeader(bw, &enc->filter_hdr_); + VP8PutBits(bw, enc->num_parts_ == 8 ? 3 : + enc->num_parts_ == 4 ? 2 : + enc->num_parts_ == 2 ? 1 : 0, 2); + PutQuant(bw, enc); + VP8PutBitUniform(bw, 0); // no proba update + VP8WriteProbas(bw, &enc->proba_); + pos2 = VP8BitWriterPos(bw); + VP8CodeIntraModes(enc); + VP8BitWriterFinish(bw); + + pos3 = VP8BitWriterPos(bw); + +#if !defined(WEBP_DISABLE_STATS) + if (enc->pic_->stats) { + enc->pic_->stats->header_bytes[0] = (int)((pos2 - pos1 + 7) >> 3); + enc->pic_->stats->header_bytes[1] = (int)((pos3 - pos2 + 7) >> 3); + enc->pic_->stats->alpha_data_size = (int)enc->alpha_data_size_; + } +#else + (void)pos1; + (void)pos2; + (void)pos3; +#endif + if (bw->error_) { + return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + return 1; +} + +void VP8EncFreeBitWriters(VP8Encoder* const enc) { + int p; + VP8BitWriterWipeOut(&enc->bw_); + for (p = 0; p < enc->num_parts_; ++p) { + VP8BitWriterWipeOut(enc->parts_ + p); + } +} + +int VP8EncWrite(VP8Encoder* const enc) { + WebPPicture* const pic = enc->pic_; + VP8BitWriter* const bw = &enc->bw_; + const int task_percent = 19; + const int percent_per_part = task_percent / enc->num_parts_; + const int final_percent = enc->percent_ + task_percent; + int ok = 0; + size_t vp8_size, pad, riff_size; + int p; + + // Partition #0 with header and partition sizes + ok = GeneratePartition0(enc); + if (!ok) return 0; + + // Compute VP8 size + vp8_size = VP8_FRAME_HEADER_SIZE + + VP8BitWriterSize(bw) + + 3 * (enc->num_parts_ - 1); + for (p = 0; p < enc->num_parts_; ++p) { + vp8_size += VP8BitWriterSize(enc->parts_ + p); + } + pad = vp8_size & 1; + vp8_size += pad; + + // Compute RIFF size + // At the minimum it is: "WEBPVP8 nnnn" + VP8 data size. + riff_size = TAG_SIZE + CHUNK_HEADER_SIZE + vp8_size; + if (IsVP8XNeeded(enc)) { // Add size for: VP8X header + data. + riff_size += CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE; + } + if (enc->has_alpha_) { // Add size for: ALPH header + data. + const uint32_t padded_alpha_size = enc->alpha_data_size_ + + (enc->alpha_data_size_ & 1); + riff_size += CHUNK_HEADER_SIZE + padded_alpha_size; + } + // RIFF size should fit in 32-bits. + if (riff_size > 0xfffffffeU) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_FILE_TOO_BIG); + } + + // Emit headers and partition #0 + { + const uint8_t* const part0 = VP8BitWriterBuf(bw); + const size_t size0 = VP8BitWriterSize(bw); + ok = ok && PutWebPHeaders(enc, size0, vp8_size, riff_size) + && pic->writer(part0, size0, pic) + && EmitPartitionsSize(enc, pic); + VP8BitWriterWipeOut(bw); // will free the internal buffer. + } + + // Token partitions + for (p = 0; p < enc->num_parts_; ++p) { + const uint8_t* const buf = VP8BitWriterBuf(enc->parts_ + p); + const size_t size = VP8BitWriterSize(enc->parts_ + p); + if (size) ok = ok && pic->writer(buf, size, pic); + VP8BitWriterWipeOut(enc->parts_ + p); // will free the internal buffer. + ok = ok && WebPReportProgress(pic, enc->percent_ + percent_per_part, + &enc->percent_); + } + + // Padding byte + if (ok && pad) { + ok = PutPaddingByte(pic); + } + + enc->coded_size_ = (int)(CHUNK_HEADER_SIZE + riff_size); + ok = ok && WebPReportProgress(pic, final_percent, &enc->percent_); + if (!ok) WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_WRITE); + return ok; +} + +//------------------------------------------------------------------------------ + diff --git a/third-party/webp/libwebp/src/enc/token_enc.c b/third-party/webp/libwebp/src/enc/token_enc.c new file mode 100644 index 0000000000..3a2192acac --- /dev/null +++ b/third-party/webp/libwebp/src/enc/token_enc.c @@ -0,0 +1,262 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Paginated token buffer +// +// A 'token' is a bit value associated with a probability, either fixed +// or a later-to-be-determined after statistics have been collected. +// For dynamic probability, we just record the slot id (idx) for the probability +// value in the final probability array (uint8_t* probas in VP8EmitTokens). +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include +#include + +#include "src/enc/cost_enc.h" +#include "src/enc/vp8i_enc.h" +#include "src/utils/utils.h" + +#if !defined(DISABLE_TOKEN_BUFFER) + +// we use pages to reduce the number of memcpy() +#define MIN_PAGE_SIZE 8192 // minimum number of token per page +#define FIXED_PROBA_BIT (1u << 14) + +typedef uint16_t token_t; // bit #15: bit value + // bit #14: flags for constant proba or idx + // bits #0..13: slot or constant proba +struct VP8Tokens { + VP8Tokens* next_; // pointer to next page +}; +// Token data is located in memory just after the next_ field. +// This macro is used to return their address and hide the trick. +#define TOKEN_DATA(p) ((const token_t*)&(p)[1]) + +//------------------------------------------------------------------------------ + +void VP8TBufferInit(VP8TBuffer* const b, int page_size) { + b->tokens_ = NULL; + b->pages_ = NULL; + b->last_page_ = &b->pages_; + b->left_ = 0; + b->page_size_ = (page_size < MIN_PAGE_SIZE) ? MIN_PAGE_SIZE : page_size; + b->error_ = 0; +} + +void VP8TBufferClear(VP8TBuffer* const b) { + if (b != NULL) { + VP8Tokens* p = b->pages_; + while (p != NULL) { + VP8Tokens* const next = p->next_; + WebPSafeFree(p); + p = next; + } + VP8TBufferInit(b, b->page_size_); + } +} + +static int TBufferNewPage(VP8TBuffer* const b) { + VP8Tokens* page = NULL; + if (!b->error_) { + const size_t size = sizeof(*page) + b->page_size_ * sizeof(token_t); + page = (VP8Tokens*)WebPSafeMalloc(1ULL, size); + } + if (page == NULL) { + b->error_ = 1; + return 0; + } + page->next_ = NULL; + + *b->last_page_ = page; + b->last_page_ = &page->next_; + b->left_ = b->page_size_; + b->tokens_ = (token_t*)TOKEN_DATA(page); + return 1; +} + +//------------------------------------------------------------------------------ + +#define TOKEN_ID(t, b, ctx) \ + (NUM_PROBAS * ((ctx) + NUM_CTX * ((b) + NUM_BANDS * (t)))) + +static WEBP_INLINE uint32_t AddToken(VP8TBuffer* const b, uint32_t bit, + uint32_t proba_idx, + proba_t* const stats) { + assert(proba_idx < FIXED_PROBA_BIT); + assert(bit <= 1); + if (b->left_ > 0 || TBufferNewPage(b)) { + const int slot = --b->left_; + b->tokens_[slot] = (bit << 15) | proba_idx; + } + VP8RecordStats(bit, stats); + return bit; +} + +static WEBP_INLINE void AddConstantToken(VP8TBuffer* const b, + uint32_t bit, uint32_t proba) { + assert(proba < 256); + assert(bit <= 1); + if (b->left_ > 0 || TBufferNewPage(b)) { + const int slot = --b->left_; + b->tokens_[slot] = (bit << 15) | FIXED_PROBA_BIT | proba; + } +} + +int VP8RecordCoeffTokens(int ctx, const struct VP8Residual* const res, + VP8TBuffer* const tokens) { + const int16_t* const coeffs = res->coeffs; + const int coeff_type = res->coeff_type; + const int last = res->last; + int n = res->first; + uint32_t base_id = TOKEN_ID(coeff_type, n, ctx); + // should be stats[VP8EncBands[n]], but it's equivalent for n=0 or 1 + proba_t* s = res->stats[n][ctx]; + if (!AddToken(tokens, last >= 0, base_id + 0, s + 0)) { + return 0; + } + + while (n < 16) { + const int c = coeffs[n++]; + const int sign = c < 0; + const uint32_t v = sign ? -c : c; + if (!AddToken(tokens, v != 0, base_id + 1, s + 1)) { + base_id = TOKEN_ID(coeff_type, VP8EncBands[n], 0); // ctx=0 + s = res->stats[VP8EncBands[n]][0]; + continue; + } + if (!AddToken(tokens, v > 1, base_id + 2, s + 2)) { + base_id = TOKEN_ID(coeff_type, VP8EncBands[n], 1); // ctx=1 + s = res->stats[VP8EncBands[n]][1]; + } else { + if (!AddToken(tokens, v > 4, base_id + 3, s + 3)) { + if (AddToken(tokens, v != 2, base_id + 4, s + 4)) { + AddToken(tokens, v == 4, base_id + 5, s + 5); + } + } else if (!AddToken(tokens, v > 10, base_id + 6, s + 6)) { + if (!AddToken(tokens, v > 6, base_id + 7, s + 7)) { + AddConstantToken(tokens, v == 6, 159); + } else { + AddConstantToken(tokens, v >= 9, 165); + AddConstantToken(tokens, !(v & 1), 145); + } + } else { + int mask; + const uint8_t* tab; + uint32_t residue = v - 3; + if (residue < (8 << 1)) { // VP8Cat3 (3b) + AddToken(tokens, 0, base_id + 8, s + 8); + AddToken(tokens, 0, base_id + 9, s + 9); + residue -= (8 << 0); + mask = 1 << 2; + tab = VP8Cat3; + } else if (residue < (8 << 2)) { // VP8Cat4 (4b) + AddToken(tokens, 0, base_id + 8, s + 8); + AddToken(tokens, 1, base_id + 9, s + 9); + residue -= (8 << 1); + mask = 1 << 3; + tab = VP8Cat4; + } else if (residue < (8 << 3)) { // VP8Cat5 (5b) + AddToken(tokens, 1, base_id + 8, s + 8); + AddToken(tokens, 0, base_id + 10, s + 9); + residue -= (8 << 2); + mask = 1 << 4; + tab = VP8Cat5; + } else { // VP8Cat6 (11b) + AddToken(tokens, 1, base_id + 8, s + 8); + AddToken(tokens, 1, base_id + 10, s + 9); + residue -= (8 << 3); + mask = 1 << 10; + tab = VP8Cat6; + } + while (mask) { + AddConstantToken(tokens, !!(residue & mask), *tab++); + mask >>= 1; + } + } + base_id = TOKEN_ID(coeff_type, VP8EncBands[n], 2); // ctx=2 + s = res->stats[VP8EncBands[n]][2]; + } + AddConstantToken(tokens, sign, 128); + if (n == 16 || !AddToken(tokens, n <= last, base_id + 0, s + 0)) { + return 1; // EOB + } + } + return 1; +} + +#undef TOKEN_ID + +//------------------------------------------------------------------------------ +// Final coding pass, with known probabilities + +int VP8EmitTokens(VP8TBuffer* const b, VP8BitWriter* const bw, + const uint8_t* const probas, int final_pass) { + const VP8Tokens* p = b->pages_; + assert(!b->error_); + while (p != NULL) { + const VP8Tokens* const next = p->next_; + const int N = (next == NULL) ? b->left_ : 0; + int n = b->page_size_; + const token_t* const tokens = TOKEN_DATA(p); + while (n-- > N) { + const token_t token = tokens[n]; + const int bit = (token >> 15) & 1; + if (token & FIXED_PROBA_BIT) { + VP8PutBit(bw, bit, token & 0xffu); // constant proba + } else { + VP8PutBit(bw, bit, probas[token & 0x3fffu]); + } + } + if (final_pass) WebPSafeFree((void*)p); + p = next; + } + if (final_pass) b->pages_ = NULL; + return 1; +} + +// Size estimation +size_t VP8EstimateTokenSize(VP8TBuffer* const b, const uint8_t* const probas) { + size_t size = 0; + const VP8Tokens* p = b->pages_; + assert(!b->error_); + while (p != NULL) { + const VP8Tokens* const next = p->next_; + const int N = (next == NULL) ? b->left_ : 0; + int n = b->page_size_; + const token_t* const tokens = TOKEN_DATA(p); + while (n-- > N) { + const token_t token = tokens[n]; + const int bit = token & (1 << 15); + if (token & FIXED_PROBA_BIT) { + size += VP8BitCost(bit, token & 0xffu); + } else { + size += VP8BitCost(bit, probas[token & 0x3fffu]); + } + } + p = next; + } + return size; +} + +//------------------------------------------------------------------------------ + +#else // DISABLE_TOKEN_BUFFER + +void VP8TBufferInit(VP8TBuffer* const b, int page_size) { + (void)b; + (void)page_size; +} +void VP8TBufferClear(VP8TBuffer* const b) { + (void)b; +} + +#endif // !DISABLE_TOKEN_BUFFER + diff --git a/third-party/webp/libwebp/src/enc/tree_enc.c b/third-party/webp/libwebp/src/enc/tree_enc.c new file mode 100644 index 0000000000..64ed28360b --- /dev/null +++ b/third-party/webp/libwebp/src/enc/tree_enc.c @@ -0,0 +1,504 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Coding of token probabilities, intra modes and segments. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/enc/vp8i_enc.h" + +//------------------------------------------------------------------------------ +// Default probabilities + +// Paragraph 13.5 +const uint8_t + VP8CoeffsProba0[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = { + { { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } + }, + { { 253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128 }, + { 189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128 }, + { 106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128 } + }, + { { 1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128 }, + { 181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128 }, + { 78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128 }, + }, + { { 1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128 }, + { 184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128 }, + { 77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128 }, + }, + { { 1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128 }, + { 170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128 }, + { 37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128 } + }, + { { 1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128 }, + { 207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128 }, + { 102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128 } + }, + { { 1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128 }, + { 177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128 }, + { 80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128 } + }, + { { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } + } + }, + { { { 198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62 }, + { 131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1 }, + { 68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128 } + }, + { { 1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128 }, + { 184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128 }, + { 81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128 } + }, + { { 1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128 }, + { 99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128 }, + { 23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128 } + }, + { { 1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128 }, + { 109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128 }, + { 44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128 } + }, + { { 1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128 }, + { 94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128 }, + { 22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128 } + }, + { { 1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128 }, + { 124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128 }, + { 35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128 } + }, + { { 1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128 }, + { 121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128 }, + { 45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128 } + }, + { { 1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128 }, + { 203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128 } + } + }, + { { { 253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128 }, + { 175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128 }, + { 73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128 } + }, + { { 1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128 }, + { 239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128 }, + { 155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128 } + }, + { { 1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128 }, + { 201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128 }, + { 69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128 } + }, + { { 1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128 }, + { 141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128 } + }, + { { 1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128 }, + { 149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 } + }, + { { 1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128 } + }, + { { 1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 55, 93, 255, 128, 128, 128, 128, 128, 128, 128, 128 } + }, + { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } + } + }, + { { { 202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255 }, + { 126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128 }, + { 61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128 } + }, + { { 1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128 }, + { 166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128 }, + { 39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128 } + }, + { { 1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128 }, + { 124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128 }, + { 24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128 } + }, + { { 1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128 }, + { 149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128 }, + { 28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128 } + }, + { { 1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128 }, + { 123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128 }, + { 20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128 } + }, + { { 1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128 }, + { 168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128 }, + { 47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128 } + }, + { { 1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128 }, + { 141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128 }, + { 42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128 } + }, + { { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 } + } + } +}; + +void VP8DefaultProbas(VP8Encoder* const enc) { + VP8EncProba* const probas = &enc->proba_; + probas->use_skip_proba_ = 0; + memset(probas->segments_, 255u, sizeof(probas->segments_)); + memcpy(probas->coeffs_, VP8CoeffsProba0, sizeof(VP8CoeffsProba0)); + // Note: we could hard-code the level_costs_ corresponding to VP8CoeffsProba0, + // but that's ~11k of static data. Better call VP8CalculateLevelCosts() later. + probas->dirty_ = 1; +} + +// Paragraph 11.5. 900bytes. +static const uint8_t kBModesProba[NUM_BMODES][NUM_BMODES][NUM_BMODES - 1] = { + { { 231, 120, 48, 89, 115, 113, 120, 152, 112 }, + { 152, 179, 64, 126, 170, 118, 46, 70, 95 }, + { 175, 69, 143, 80, 85, 82, 72, 155, 103 }, + { 56, 58, 10, 171, 218, 189, 17, 13, 152 }, + { 114, 26, 17, 163, 44, 195, 21, 10, 173 }, + { 121, 24, 80, 195, 26, 62, 44, 64, 85 }, + { 144, 71, 10, 38, 171, 213, 144, 34, 26 }, + { 170, 46, 55, 19, 136, 160, 33, 206, 71 }, + { 63, 20, 8, 114, 114, 208, 12, 9, 226 }, + { 81, 40, 11, 96, 182, 84, 29, 16, 36 } }, + { { 134, 183, 89, 137, 98, 101, 106, 165, 148 }, + { 72, 187, 100, 130, 157, 111, 32, 75, 80 }, + { 66, 102, 167, 99, 74, 62, 40, 234, 128 }, + { 41, 53, 9, 178, 241, 141, 26, 8, 107 }, + { 74, 43, 26, 146, 73, 166, 49, 23, 157 }, + { 65, 38, 105, 160, 51, 52, 31, 115, 128 }, + { 104, 79, 12, 27, 217, 255, 87, 17, 7 }, + { 87, 68, 71, 44, 114, 51, 15, 186, 23 }, + { 47, 41, 14, 110, 182, 183, 21, 17, 194 }, + { 66, 45, 25, 102, 197, 189, 23, 18, 22 } }, + { { 88, 88, 147, 150, 42, 46, 45, 196, 205 }, + { 43, 97, 183, 117, 85, 38, 35, 179, 61 }, + { 39, 53, 200, 87, 26, 21, 43, 232, 171 }, + { 56, 34, 51, 104, 114, 102, 29, 93, 77 }, + { 39, 28, 85, 171, 58, 165, 90, 98, 64 }, + { 34, 22, 116, 206, 23, 34, 43, 166, 73 }, + { 107, 54, 32, 26, 51, 1, 81, 43, 31 }, + { 68, 25, 106, 22, 64, 171, 36, 225, 114 }, + { 34, 19, 21, 102, 132, 188, 16, 76, 124 }, + { 62, 18, 78, 95, 85, 57, 50, 48, 51 } }, + { { 193, 101, 35, 159, 215, 111, 89, 46, 111 }, + { 60, 148, 31, 172, 219, 228, 21, 18, 111 }, + { 112, 113, 77, 85, 179, 255, 38, 120, 114 }, + { 40, 42, 1, 196, 245, 209, 10, 25, 109 }, + { 88, 43, 29, 140, 166, 213, 37, 43, 154 }, + { 61, 63, 30, 155, 67, 45, 68, 1, 209 }, + { 100, 80, 8, 43, 154, 1, 51, 26, 71 }, + { 142, 78, 78, 16, 255, 128, 34, 197, 171 }, + { 41, 40, 5, 102, 211, 183, 4, 1, 221 }, + { 51, 50, 17, 168, 209, 192, 23, 25, 82 } }, + { { 138, 31, 36, 171, 27, 166, 38, 44, 229 }, + { 67, 87, 58, 169, 82, 115, 26, 59, 179 }, + { 63, 59, 90, 180, 59, 166, 93, 73, 154 }, + { 40, 40, 21, 116, 143, 209, 34, 39, 175 }, + { 47, 15, 16, 183, 34, 223, 49, 45, 183 }, + { 46, 17, 33, 183, 6, 98, 15, 32, 183 }, + { 57, 46, 22, 24, 128, 1, 54, 17, 37 }, + { 65, 32, 73, 115, 28, 128, 23, 128, 205 }, + { 40, 3, 9, 115, 51, 192, 18, 6, 223 }, + { 87, 37, 9, 115, 59, 77, 64, 21, 47 } }, + { { 104, 55, 44, 218, 9, 54, 53, 130, 226 }, + { 64, 90, 70, 205, 40, 41, 23, 26, 57 }, + { 54, 57, 112, 184, 5, 41, 38, 166, 213 }, + { 30, 34, 26, 133, 152, 116, 10, 32, 134 }, + { 39, 19, 53, 221, 26, 114, 32, 73, 255 }, + { 31, 9, 65, 234, 2, 15, 1, 118, 73 }, + { 75, 32, 12, 51, 192, 255, 160, 43, 51 }, + { 88, 31, 35, 67, 102, 85, 55, 186, 85 }, + { 56, 21, 23, 111, 59, 205, 45, 37, 192 }, + { 55, 38, 70, 124, 73, 102, 1, 34, 98 } }, + { { 125, 98, 42, 88, 104, 85, 117, 175, 82 }, + { 95, 84, 53, 89, 128, 100, 113, 101, 45 }, + { 75, 79, 123, 47, 51, 128, 81, 171, 1 }, + { 57, 17, 5, 71, 102, 57, 53, 41, 49 }, + { 38, 33, 13, 121, 57, 73, 26, 1, 85 }, + { 41, 10, 67, 138, 77, 110, 90, 47, 114 }, + { 115, 21, 2, 10, 102, 255, 166, 23, 6 }, + { 101, 29, 16, 10, 85, 128, 101, 196, 26 }, + { 57, 18, 10, 102, 102, 213, 34, 20, 43 }, + { 117, 20, 15, 36, 163, 128, 68, 1, 26 } }, + { { 102, 61, 71, 37, 34, 53, 31, 243, 192 }, + { 69, 60, 71, 38, 73, 119, 28, 222, 37 }, + { 68, 45, 128, 34, 1, 47, 11, 245, 171 }, + { 62, 17, 19, 70, 146, 85, 55, 62, 70 }, + { 37, 43, 37, 154, 100, 163, 85, 160, 1 }, + { 63, 9, 92, 136, 28, 64, 32, 201, 85 }, + { 75, 15, 9, 9, 64, 255, 184, 119, 16 }, + { 86, 6, 28, 5, 64, 255, 25, 248, 1 }, + { 56, 8, 17, 132, 137, 255, 55, 116, 128 }, + { 58, 15, 20, 82, 135, 57, 26, 121, 40 } }, + { { 164, 50, 31, 137, 154, 133, 25, 35, 218 }, + { 51, 103, 44, 131, 131, 123, 31, 6, 158 }, + { 86, 40, 64, 135, 148, 224, 45, 183, 128 }, + { 22, 26, 17, 131, 240, 154, 14, 1, 209 }, + { 45, 16, 21, 91, 64, 222, 7, 1, 197 }, + { 56, 21, 39, 155, 60, 138, 23, 102, 213 }, + { 83, 12, 13, 54, 192, 255, 68, 47, 28 }, + { 85, 26, 85, 85, 128, 128, 32, 146, 171 }, + { 18, 11, 7, 63, 144, 171, 4, 4, 246 }, + { 35, 27, 10, 146, 174, 171, 12, 26, 128 } }, + { { 190, 80, 35, 99, 180, 80, 126, 54, 45 }, + { 85, 126, 47, 87, 176, 51, 41, 20, 32 }, + { 101, 75, 128, 139, 118, 146, 116, 128, 85 }, + { 56, 41, 15, 176, 236, 85, 37, 9, 62 }, + { 71, 30, 17, 119, 118, 255, 17, 18, 138 }, + { 101, 38, 60, 138, 55, 70, 43, 26, 142 }, + { 146, 36, 19, 30, 171, 255, 97, 27, 20 }, + { 138, 45, 61, 62, 219, 1, 81, 188, 64 }, + { 32, 41, 20, 117, 151, 142, 20, 21, 163 }, + { 112, 19, 12, 61, 195, 128, 48, 4, 24 } } +}; + +static int PutI4Mode(VP8BitWriter* const bw, int mode, + const uint8_t* const prob) { + if (VP8PutBit(bw, mode != B_DC_PRED, prob[0])) { + if (VP8PutBit(bw, mode != B_TM_PRED, prob[1])) { + if (VP8PutBit(bw, mode != B_VE_PRED, prob[2])) { + if (!VP8PutBit(bw, mode >= B_LD_PRED, prob[3])) { + if (VP8PutBit(bw, mode != B_HE_PRED, prob[4])) { + VP8PutBit(bw, mode != B_RD_PRED, prob[5]); + } + } else { + if (VP8PutBit(bw, mode != B_LD_PRED, prob[6])) { + if (VP8PutBit(bw, mode != B_VL_PRED, prob[7])) { + VP8PutBit(bw, mode != B_HD_PRED, prob[8]); + } + } + } + } + } + } + return mode; +} + +static void PutI16Mode(VP8BitWriter* const bw, int mode) { + if (VP8PutBit(bw, (mode == TM_PRED || mode == H_PRED), 156)) { + VP8PutBit(bw, mode == TM_PRED, 128); // TM or HE + } else { + VP8PutBit(bw, mode == V_PRED, 163); // VE or DC + } +} + +static void PutUVMode(VP8BitWriter* const bw, int uv_mode) { + if (VP8PutBit(bw, uv_mode != DC_PRED, 142)) { + if (VP8PutBit(bw, uv_mode != V_PRED, 114)) { + VP8PutBit(bw, uv_mode != H_PRED, 183); // else: TM_PRED + } + } +} + +static void PutSegment(VP8BitWriter* const bw, int s, const uint8_t* p) { + if (VP8PutBit(bw, s >= 2, p[0])) p += 1; + VP8PutBit(bw, s & 1, p[1]); +} + +void VP8CodeIntraModes(VP8Encoder* const enc) { + VP8BitWriter* const bw = &enc->bw_; + VP8EncIterator it; + VP8IteratorInit(enc, &it); + do { + const VP8MBInfo* const mb = it.mb_; + const uint8_t* preds = it.preds_; + if (enc->segment_hdr_.update_map_) { + PutSegment(bw, mb->segment_, enc->proba_.segments_); + } + if (enc->proba_.use_skip_proba_) { + VP8PutBit(bw, mb->skip_, enc->proba_.skip_proba_); + } + if (VP8PutBit(bw, (mb->type_ != 0), 145)) { // i16x16 + PutI16Mode(bw, preds[0]); + } else { + const int preds_w = enc->preds_w_; + const uint8_t* top_pred = preds - preds_w; + int x, y; + for (y = 0; y < 4; ++y) { + int left = preds[-1]; + for (x = 0; x < 4; ++x) { + const uint8_t* const probas = kBModesProba[top_pred[x]][left]; + left = PutI4Mode(bw, preds[x], probas); + } + top_pred = preds; + preds += preds_w; + } + } + PutUVMode(bw, mb->uv_mode_); + } while (VP8IteratorNext(&it)); +} + +//------------------------------------------------------------------------------ +// Paragraph 13 + +const uint8_t + VP8CoeffsUpdateProba[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = { + { { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255 }, + { 250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + } + }, + { { { 217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255 }, + { 234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255 } + }, + { { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + } + }, + { { { 186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255 }, + { 251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255 } + }, + { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + } + }, + { { { 248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255 }, + { 248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + } + } +}; + +void VP8WriteProbas(VP8BitWriter* const bw, const VP8EncProba* const probas) { + int t, b, c, p; + for (t = 0; t < NUM_TYPES; ++t) { + for (b = 0; b < NUM_BANDS; ++b) { + for (c = 0; c < NUM_CTX; ++c) { + for (p = 0; p < NUM_PROBAS; ++p) { + const uint8_t p0 = probas->coeffs_[t][b][c][p]; + const int update = (p0 != VP8CoeffsProba0[t][b][c][p]); + if (VP8PutBit(bw, update, VP8CoeffsUpdateProba[t][b][c][p])) { + VP8PutBits(bw, p0, 8); + } + } + } + } + } + if (VP8PutBitUniform(bw, probas->use_skip_proba_)) { + VP8PutBits(bw, probas->skip_proba_, 8); + } +} + diff --git a/third-party/webp/libwebp/src/enc/vp8i_enc.h b/third-party/webp/libwebp/src/enc/vp8i_enc.h new file mode 100644 index 0000000000..0864fbf1f5 --- /dev/null +++ b/third-party/webp/libwebp/src/enc/vp8i_enc.h @@ -0,0 +1,523 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// WebP encoder: internal header. +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_ENC_VP8I_ENC_H_ +#define WEBP_ENC_VP8I_ENC_H_ + +#include // for memcpy() +#include "src/dec/common_dec.h" +#include "src/dsp/dsp.h" +#include "src/utils/bit_writer_utils.h" +#include "src/utils/thread_utils.h" +#include "src/utils/utils.h" +#include "src/webp/encode.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//------------------------------------------------------------------------------ +// Various defines and enums + +// version numbers +#define ENC_MAJ_VERSION 1 +#define ENC_MIN_VERSION 3 +#define ENC_REV_VERSION 2 + +enum { MAX_LF_LEVELS = 64, // Maximum loop filter level + MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost + MAX_LEVEL = 2047 // max level (note: max codable is 2047 + 67) + }; + +typedef enum { // Rate-distortion optimization levels + RD_OPT_NONE = 0, // no rd-opt + RD_OPT_BASIC = 1, // basic scoring (no trellis) + RD_OPT_TRELLIS = 2, // perform trellis-quant on the final decision only + RD_OPT_TRELLIS_ALL = 3 // trellis-quant for every scoring (much slower) +} VP8RDLevel; + +// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline). +// The original or reconstructed samples can be accessed using VP8Scan[]. +// The predicted blocks can be accessed using offsets to yuv_p_ and +// the arrays VP8*ModeOffsets[]. +// * YUV Samples area (yuv_in_/yuv_out_/yuv_out2_) +// (see VP8Scan[] for accessing the blocks, along with +// Y_OFF_ENC/U_OFF_ENC/V_OFF_ENC): +// +----+----+ +// Y_OFF_ENC |YYYY|UUVV| +// U_OFF_ENC |YYYY|UUVV| +// V_OFF_ENC |YYYY|....| <- 25% wasted U/V area +// |YYYY|....| +// +----+----+ +// * Prediction area ('yuv_p_', size = PRED_SIZE_ENC) +// Intra16 predictions (16x16 block each, two per row): +// |I16DC16|I16TM16| +// |I16VE16|I16HE16| +// Chroma U/V predictions (16x8 block each, two per row): +// |C8DC8|C8TM8| +// |C8VE8|C8HE8| +// Intra 4x4 predictions (4x4 block each) +// |I4DC4 I4TM4 I4VE4 I4HE4|I4RD4 I4VR4 I4LD4 I4VL4| +// |I4HD4 I4HU4 I4TMP .....|.......................| <- ~31% wasted +#define YUV_SIZE_ENC (BPS * 16) +#define PRED_SIZE_ENC (32 * BPS + 16 * BPS + 8 * BPS) // I16+Chroma+I4 preds +#define Y_OFF_ENC (0) +#define U_OFF_ENC (16) +#define V_OFF_ENC (16 + 8) + +extern const uint16_t VP8Scan[16]; +extern const uint16_t VP8UVModeOffsets[4]; +extern const uint16_t VP8I16ModeOffsets[4]; +extern const uint16_t VP8I4ModeOffsets[NUM_BMODES]; + +// Layout of prediction blocks +// intra 16x16 +#define I16DC16 (0 * 16 * BPS) +#define I16TM16 (I16DC16 + 16) +#define I16VE16 (1 * 16 * BPS) +#define I16HE16 (I16VE16 + 16) +// chroma 8x8, two U/V blocks side by side (hence: 16x8 each) +#define C8DC8 (2 * 16 * BPS) +#define C8TM8 (C8DC8 + 1 * 16) +#define C8VE8 (2 * 16 * BPS + 8 * BPS) +#define C8HE8 (C8VE8 + 1 * 16) +// intra 4x4 +#define I4DC4 (3 * 16 * BPS + 0) +#define I4TM4 (I4DC4 + 4) +#define I4VE4 (I4DC4 + 8) +#define I4HE4 (I4DC4 + 12) +#define I4RD4 (I4DC4 + 16) +#define I4VR4 (I4DC4 + 20) +#define I4LD4 (I4DC4 + 24) +#define I4VL4 (I4DC4 + 28) +#define I4HD4 (3 * 16 * BPS + 4 * BPS) +#define I4HU4 (I4HD4 + 4) +#define I4TMP (I4HD4 + 8) + +typedef int64_t score_t; // type used for scores, rate, distortion +// Note that MAX_COST is not the maximum allowed by sizeof(score_t), +// in order to allow overflowing computations. +#define MAX_COST ((score_t)0x7fffffffffffffLL) + +#define QFIX 17 +#define BIAS(b) ((b) << (QFIX - 8)) +// Fun fact: this is the _only_ line where we're actually being lossy and +// discarding bits. +static WEBP_INLINE int QUANTDIV(uint32_t n, uint32_t iQ, uint32_t B) { + return (int)((n * iQ + B) >> QFIX); +} + +// Uncomment the following to remove token-buffer code: +// #define DISABLE_TOKEN_BUFFER + +// quality below which error-diffusion is enabled +#define ERROR_DIFFUSION_QUALITY 98 + +//------------------------------------------------------------------------------ +// Headers + +typedef uint32_t proba_t; // 16b + 16b +typedef uint8_t ProbaArray[NUM_CTX][NUM_PROBAS]; +typedef proba_t StatsArray[NUM_CTX][NUM_PROBAS]; +typedef uint16_t CostArray[NUM_CTX][MAX_VARIABLE_LEVEL + 1]; +typedef const uint16_t* (*CostArrayPtr)[NUM_CTX]; // for easy casting +typedef const uint16_t* CostArrayMap[16][NUM_CTX]; +typedef double LFStats[NUM_MB_SEGMENTS][MAX_LF_LEVELS]; // filter stats + +typedef struct VP8Encoder VP8Encoder; + +// segment features +typedef struct { + int num_segments_; // Actual number of segments. 1 segment only = unused. + int update_map_; // whether to update the segment map or not. + // must be 0 if there's only 1 segment. + int size_; // bit-cost for transmitting the segment map +} VP8EncSegmentHeader; + +// Struct collecting all frame-persistent probabilities. +typedef struct { + uint8_t segments_[3]; // probabilities for segment tree + uint8_t skip_proba_; // final probability of being skipped. + ProbaArray coeffs_[NUM_TYPES][NUM_BANDS]; // 1056 bytes + StatsArray stats_[NUM_TYPES][NUM_BANDS]; // 4224 bytes + CostArray level_cost_[NUM_TYPES][NUM_BANDS]; // 13056 bytes + CostArrayMap remapped_costs_[NUM_TYPES]; // 1536 bytes + int dirty_; // if true, need to call VP8CalculateLevelCosts() + int use_skip_proba_; // Note: we always use skip_proba for now. + int nb_skip_; // number of skipped blocks +} VP8EncProba; + +// Filter parameters. Not actually used in the code (we don't perform +// the in-loop filtering), but filled from user's config +typedef struct { + int simple_; // filtering type: 0=complex, 1=simple + int level_; // base filter level [0..63] + int sharpness_; // [0..7] + int i4x4_lf_delta_; // delta filter level for i4x4 relative to i16x16 +} VP8EncFilterHeader; + +//------------------------------------------------------------------------------ +// Informations about the macroblocks. + +typedef struct { + // block type + unsigned int type_:2; // 0=i4x4, 1=i16x16 + unsigned int uv_mode_:2; + unsigned int skip_:1; + unsigned int segment_:2; + uint8_t alpha_; // quantization-susceptibility +} VP8MBInfo; + +typedef struct VP8Matrix { + uint16_t q_[16]; // quantizer steps + uint16_t iq_[16]; // reciprocals, fixed point. + uint32_t bias_[16]; // rounding bias + uint32_t zthresh_[16]; // value below which a coefficient is zeroed + uint16_t sharpen_[16]; // frequency boosters for slight sharpening +} VP8Matrix; + +typedef struct { + VP8Matrix y1_, y2_, uv_; // quantization matrices + int alpha_; // quant-susceptibility, range [-127,127]. Zero is neutral. + // Lower values indicate a lower risk of blurriness. + int beta_; // filter-susceptibility, range [0,255]. + int quant_; // final segment quantizer. + int fstrength_; // final in-loop filtering strength + int max_edge_; // max edge delta (for filtering strength) + int min_disto_; // minimum distortion required to trigger filtering record + // reactivities + int lambda_i16_, lambda_i4_, lambda_uv_; + int lambda_mode_, lambda_trellis_, tlambda_; + int lambda_trellis_i16_, lambda_trellis_i4_, lambda_trellis_uv_; + + // lambda values for distortion-based evaluation + score_t i4_penalty_; // penalty for using Intra4 +} VP8SegmentInfo; + +typedef int8_t DError[2 /* u/v */][2 /* top or left */]; + +// Handy transient struct to accumulate score and info during RD-optimization +// and mode evaluation. +typedef struct { + score_t D, SD; // Distortion, spectral distortion + score_t H, R, score; // header bits, rate, score. + int16_t y_dc_levels[16]; // Quantized levels for luma-DC, luma-AC, chroma. + int16_t y_ac_levels[16][16]; + int16_t uv_levels[4 + 4][16]; + int mode_i16; // mode number for intra16 prediction + uint8_t modes_i4[16]; // mode numbers for intra4 predictions + int mode_uv; // mode number of chroma prediction + uint32_t nz; // non-zero blocks + int8_t derr[2][3]; // DC diffusion errors for U/V for blocks #1/2/3 +} VP8ModeScore; + +// Iterator structure to iterate through macroblocks, pointing to the +// right neighbouring data (samples, predictions, contexts, ...) +typedef struct { + int x_, y_; // current macroblock + uint8_t* yuv_in_; // input samples + uint8_t* yuv_out_; // output samples + uint8_t* yuv_out2_; // secondary buffer swapped with yuv_out_. + uint8_t* yuv_p_; // scratch buffer for prediction + VP8Encoder* enc_; // back-pointer + VP8MBInfo* mb_; // current macroblock + VP8BitWriter* bw_; // current bit-writer + uint8_t* preds_; // intra mode predictors (4x4 blocks) + uint32_t* nz_; // non-zero pattern + uint8_t i4_boundary_[37]; // 32+5 boundary samples needed by intra4x4 + uint8_t* i4_top_; // pointer to the current top boundary sample + int i4_; // current intra4x4 mode being tested + int top_nz_[9]; // top-non-zero context. + int left_nz_[9]; // left-non-zero. left_nz[8] is independent. + uint64_t bit_count_[4][3]; // bit counters for coded levels. + uint64_t luma_bits_; // macroblock bit-cost for luma + uint64_t uv_bits_; // macroblock bit-cost for chroma + LFStats* lf_stats_; // filter stats (borrowed from enc_) + int do_trellis_; // if true, perform extra level optimisation + int count_down_; // number of mb still to be processed + int count_down0_; // starting counter value (for progress) + int percent0_; // saved initial progress percent + + DError left_derr_; // left error diffusion (u/v) + DError* top_derr_; // top diffusion error - NULL if disabled + + uint8_t* y_left_; // left luma samples (addressable from index -1 to 15). + uint8_t* u_left_; // left u samples (addressable from index -1 to 7) + uint8_t* v_left_; // left v samples (addressable from index -1 to 7) + + uint8_t* y_top_; // top luma samples at position 'x_' + uint8_t* uv_top_; // top u/v samples at position 'x_', packed as 16 bytes + + // memory for storing y/u/v_left_ + uint8_t yuv_left_mem_[17 + 16 + 16 + 8 + WEBP_ALIGN_CST]; + // memory for yuv_* + uint8_t yuv_mem_[3 * YUV_SIZE_ENC + PRED_SIZE_ENC + WEBP_ALIGN_CST]; +} VP8EncIterator; + + // in iterator.c +// must be called first +void VP8IteratorInit(VP8Encoder* const enc, VP8EncIterator* const it); +// restart a scan +void VP8IteratorReset(VP8EncIterator* const it); +// reset iterator position to row 'y' +void VP8IteratorSetRow(VP8EncIterator* const it, int y); +// set count down (=number of iterations to go) +void VP8IteratorSetCountDown(VP8EncIterator* const it, int count_down); +// return true if iteration is finished +int VP8IteratorIsDone(const VP8EncIterator* const it); +// Import uncompressed samples from source. +// If tmp_32 is not NULL, import boundary samples too. +// tmp_32 is a 32-bytes scratch buffer that must be aligned in memory. +void VP8IteratorImport(VP8EncIterator* const it, uint8_t* const tmp_32); +// export decimated samples +void VP8IteratorExport(const VP8EncIterator* const it); +// go to next macroblock. Returns false if not finished. +int VP8IteratorNext(VP8EncIterator* const it); +// save the yuv_out_ boundary values to top_/left_ arrays for next iterations. +void VP8IteratorSaveBoundary(VP8EncIterator* const it); +// Report progression based on macroblock rows. Return 0 for user-abort request. +int VP8IteratorProgress(const VP8EncIterator* const it, int delta); +// Intra4x4 iterations +void VP8IteratorStartI4(VP8EncIterator* const it); +// returns true if not done. +int VP8IteratorRotateI4(VP8EncIterator* const it, + const uint8_t* const yuv_out); + +// Non-zero context setup/teardown +void VP8IteratorNzToBytes(VP8EncIterator* const it); +void VP8IteratorBytesToNz(VP8EncIterator* const it); + +// Helper functions to set mode properties +void VP8SetIntra16Mode(const VP8EncIterator* const it, int mode); +void VP8SetIntra4Mode(const VP8EncIterator* const it, const uint8_t* modes); +void VP8SetIntraUVMode(const VP8EncIterator* const it, int mode); +void VP8SetSkip(const VP8EncIterator* const it, int skip); +void VP8SetSegment(const VP8EncIterator* const it, int segment); + +//------------------------------------------------------------------------------ +// Paginated token buffer + +typedef struct VP8Tokens VP8Tokens; // struct details in token.c + +typedef struct { +#if !defined(DISABLE_TOKEN_BUFFER) + VP8Tokens* pages_; // first page + VP8Tokens** last_page_; // last page + uint16_t* tokens_; // set to (*last_page_)->tokens_ + int left_; // how many free tokens left before the page is full + int page_size_; // number of tokens per page +#endif + int error_; // true in case of malloc error +} VP8TBuffer; + +// initialize an empty buffer +void VP8TBufferInit(VP8TBuffer* const b, int page_size); +void VP8TBufferClear(VP8TBuffer* const b); // de-allocate pages memory + +#if !defined(DISABLE_TOKEN_BUFFER) + +// Finalizes bitstream when probabilities are known. +// Deletes the allocated token memory if final_pass is true. +int VP8EmitTokens(VP8TBuffer* const b, VP8BitWriter* const bw, + const uint8_t* const probas, int final_pass); + +// record the coding of coefficients without knowing the probabilities yet +int VP8RecordCoeffTokens(int ctx, const struct VP8Residual* const res, + VP8TBuffer* const tokens); + +// Estimate the final coded size given a set of 'probas'. +size_t VP8EstimateTokenSize(VP8TBuffer* const b, const uint8_t* const probas); + +#endif // !DISABLE_TOKEN_BUFFER + +//------------------------------------------------------------------------------ +// VP8Encoder + +struct VP8Encoder { + const WebPConfig* config_; // user configuration and parameters + WebPPicture* pic_; // input / output picture + + // headers + VP8EncFilterHeader filter_hdr_; // filtering information + VP8EncSegmentHeader segment_hdr_; // segment information + + int profile_; // VP8's profile, deduced from Config. + + // dimension, in macroblock units. + int mb_w_, mb_h_; + int preds_w_; // stride of the *preds_ prediction plane (=4*mb_w + 1) + + // number of partitions (1, 2, 4 or 8 = MAX_NUM_PARTITIONS) + int num_parts_; + + // per-partition boolean decoders. + VP8BitWriter bw_; // part0 + VP8BitWriter parts_[MAX_NUM_PARTITIONS]; // token partitions + VP8TBuffer tokens_; // token buffer + + int percent_; // for progress + + // transparency blob + int has_alpha_; + uint8_t* alpha_data_; // non-NULL if transparency is present + uint32_t alpha_data_size_; + WebPWorker alpha_worker_; + + // quantization info (one set of DC/AC dequant factor per segment) + VP8SegmentInfo dqm_[NUM_MB_SEGMENTS]; + int base_quant_; // nominal quantizer value. Only used + // for relative coding of segments' quant. + int alpha_; // global susceptibility (<=> complexity) + int uv_alpha_; // U/V quantization susceptibility + // global offset of quantizers, shared by all segments + int dq_y1_dc_; + int dq_y2_dc_, dq_y2_ac_; + int dq_uv_dc_, dq_uv_ac_; + + // probabilities and statistics + VP8EncProba proba_; + uint64_t sse_[4]; // sum of Y/U/V/A squared errors for all macroblocks + uint64_t sse_count_; // pixel count for the sse_[] stats + int coded_size_; + int residual_bytes_[3][4]; + int block_count_[3]; + + // quality/speed settings + int method_; // 0=fastest, 6=best/slowest. + VP8RDLevel rd_opt_level_; // Deduced from method_. + int max_i4_header_bits_; // partition #0 safeness factor + int mb_header_limit_; // rough limit for header bits per MB + int thread_level_; // derived from config->thread_level + int do_search_; // derived from config->target_XXX + int use_tokens_; // if true, use token buffer + + // Memory + VP8MBInfo* mb_info_; // contextual macroblock infos (mb_w_ + 1) + uint8_t* preds_; // predictions modes: (4*mb_w+1) * (4*mb_h+1) + uint32_t* nz_; // non-zero bit context: mb_w+1 + uint8_t* y_top_; // top luma samples. + uint8_t* uv_top_; // top u/v samples. + // U and V are packed into 16 bytes (8 U + 8 V) + LFStats* lf_stats_; // autofilter stats (if NULL, autofilter is off) + DError* top_derr_; // diffusion error (NULL if disabled) +}; + +//------------------------------------------------------------------------------ +// internal functions. Not public. + + // in tree.c +extern const uint8_t VP8CoeffsProba0[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS]; +extern const uint8_t + VP8CoeffsUpdateProba[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS]; +// Reset the token probabilities to their initial (default) values +void VP8DefaultProbas(VP8Encoder* const enc); +// Write the token probabilities +void VP8WriteProbas(VP8BitWriter* const bw, const VP8EncProba* const probas); +// Writes the partition #0 modes (that is: all intra modes) +void VP8CodeIntraModes(VP8Encoder* const enc); + + // in syntax.c +// Generates the final bitstream by coding the partition0 and headers, +// and appending an assembly of all the pre-coded token partitions. +// Return true if everything is ok. +int VP8EncWrite(VP8Encoder* const enc); +// Release memory allocated for bit-writing in VP8EncLoop & seq. +void VP8EncFreeBitWriters(VP8Encoder* const enc); + + // in frame.c +extern const uint8_t VP8Cat3[]; +extern const uint8_t VP8Cat4[]; +extern const uint8_t VP8Cat5[]; +extern const uint8_t VP8Cat6[]; + +// Form all the four Intra16x16 predictions in the yuv_p_ cache +void VP8MakeLuma16Preds(const VP8EncIterator* const it); +// Form all the four Chroma8x8 predictions in the yuv_p_ cache +void VP8MakeChroma8Preds(const VP8EncIterator* const it); +// Form all the ten Intra4x4 predictions in the yuv_p_ cache +// for the 4x4 block it->i4_ +void VP8MakeIntra4Preds(const VP8EncIterator* const it); +// Rate calculation +int VP8GetCostLuma16(VP8EncIterator* const it, const VP8ModeScore* const rd); +int VP8GetCostLuma4(VP8EncIterator* const it, const int16_t levels[16]); +int VP8GetCostUV(VP8EncIterator* const it, const VP8ModeScore* const rd); +// Main coding calls +int VP8EncLoop(VP8Encoder* const enc); +int VP8EncTokenLoop(VP8Encoder* const enc); + + // in webpenc.c +// Assign an error code to a picture. Return false for convenience. +int WebPEncodingSetError(const WebPPicture* const pic, WebPEncodingError error); +int WebPReportProgress(const WebPPicture* const pic, + int percent, int* const percent_store); + + // in analysis.c +// Main analysis loop. Decides the segmentations and complexity. +// Assigns a first guess for Intra16 and uvmode_ prediction modes. +int VP8EncAnalyze(VP8Encoder* const enc); + + // in quant.c +// Sets up segment's quantization values, base_quant_ and filter strengths. +void VP8SetSegmentParams(VP8Encoder* const enc, float quality); +// Pick best modes and fills the levels. Returns true if skipped. +int VP8Decimate(VP8EncIterator* WEBP_RESTRICT const it, + VP8ModeScore* WEBP_RESTRICT const rd, + VP8RDLevel rd_opt); + + // in alpha.c +void VP8EncInitAlpha(VP8Encoder* const enc); // initialize alpha compression +int VP8EncStartAlpha(VP8Encoder* const enc); // start alpha coding process +int VP8EncFinishAlpha(VP8Encoder* const enc); // finalize compressed data +int VP8EncDeleteAlpha(VP8Encoder* const enc); // delete compressed data + +// autofilter +void VP8InitFilter(VP8EncIterator* const it); +void VP8StoreFilterStats(VP8EncIterator* const it); +void VP8AdjustFilterStrength(VP8EncIterator* const it); + +// returns the approximate filtering strength needed to smooth a edge +// step of 'delta', given a sharpness parameter 'sharpness'. +int VP8FilterStrengthFromDelta(int sharpness, int delta); + + // misc utils for picture_*.c: + +// Returns true if 'picture' is non-NULL and dimensions/colorspace are within +// their valid ranges. If returning false, the 'error_code' in 'picture' is +// updated. +int WebPValidatePicture(const WebPPicture* const picture); + +// Remove reference to the ARGB/YUVA buffer (doesn't free anything). +void WebPPictureResetBuffers(WebPPicture* const picture); + +// Allocates ARGB buffer according to set width/height (previous one is +// always free'd). Preserves the YUV(A) buffer. Returns false in case of error +// (invalid param, out-of-memory). +int WebPPictureAllocARGB(WebPPicture* const picture); + +// Allocates YUVA buffer according to set width/height (previous one is always +// free'd). Uses picture->csp to determine whether an alpha buffer is needed. +// Preserves the ARGB buffer. +// Returns false in case of error (invalid param, out-of-memory). +int WebPPictureAllocYUVA(WebPPicture* const picture); + +// Replace samples that are fully transparent by 'color' to help compressibility +// (no guarantee, though). Assumes pic->use_argb is true. +void WebPReplaceTransparentPixels(WebPPicture* const pic, uint32_t color); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_ENC_VP8I_ENC_H_ diff --git a/third-party/webp/libwebp/src/enc/vp8l_enc.c b/third-party/webp/libwebp/src/enc/vp8l_enc.c new file mode 100644 index 0000000000..c43d990d17 --- /dev/null +++ b/third-party/webp/libwebp/src/enc/vp8l_enc.c @@ -0,0 +1,1898 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// main entry for the lossless encoder. +// +// Author: Vikas Arora (vikaas.arora@gmail.com) +// + +#include +#include + +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" +#include "src/enc/backward_references_enc.h" +#include "src/enc/histogram_enc.h" +#include "src/enc/vp8i_enc.h" +#include "src/enc/vp8li_enc.h" +#include "src/utils/bit_writer_utils.h" +#include "src/utils/huffman_encode_utils.h" +#include "src/utils/palette.h" +#include "src/utils/utils.h" +#include "src/webp/encode.h" +#include "src/webp/format_constants.h" + +// Maximum number of histogram images (sub-blocks). +#define MAX_HUFF_IMAGE_SIZE 2600 + +// ----------------------------------------------------------------------------- +// Palette + +// These five modes are evaluated and their respective entropy is computed. +typedef enum { + kDirect = 0, + kSpatial = 1, + kSubGreen = 2, + kSpatialSubGreen = 3, + kPalette = 4, + kPaletteAndSpatial = 5, + kNumEntropyIx = 6 +} EntropyIx; + +typedef enum { + kHistoAlpha = 0, + kHistoAlphaPred, + kHistoGreen, + kHistoGreenPred, + kHistoRed, + kHistoRedPred, + kHistoBlue, + kHistoBluePred, + kHistoRedSubGreen, + kHistoRedPredSubGreen, + kHistoBlueSubGreen, + kHistoBluePredSubGreen, + kHistoPalette, + kHistoTotal // Must be last. +} HistoIx; + +static void AddSingleSubGreen(uint32_t p, + uint32_t* const r, uint32_t* const b) { + const int green = (int)p >> 8; // The upper bits are masked away later. + ++r[(((int)p >> 16) - green) & 0xff]; + ++b[(((int)p >> 0) - green) & 0xff]; +} + +static void AddSingle(uint32_t p, + uint32_t* const a, uint32_t* const r, + uint32_t* const g, uint32_t* const b) { + ++a[(p >> 24) & 0xff]; + ++r[(p >> 16) & 0xff]; + ++g[(p >> 8) & 0xff]; + ++b[(p >> 0) & 0xff]; +} + +static WEBP_INLINE uint32_t HashPix(uint32_t pix) { + // Note that masking with 0xffffffffu is for preventing an + // 'unsigned int overflow' warning. Doesn't impact the compiled code. + return ((((uint64_t)pix + (pix >> 19)) * 0x39c5fba7ull) & 0xffffffffu) >> 24; +} + +static int AnalyzeEntropy(const uint32_t* argb, + int width, int height, int argb_stride, + int use_palette, + int palette_size, int transform_bits, + EntropyIx* const min_entropy_ix, + int* const red_and_blue_always_zero) { + // Allocate histogram set with cache_bits = 0. + uint32_t* histo; + + if (use_palette && palette_size <= 16) { + // In the case of small palettes, we pack 2, 4 or 8 pixels together. In + // practice, small palettes are better than any other transform. + *min_entropy_ix = kPalette; + *red_and_blue_always_zero = 1; + return 1; + } + histo = (uint32_t*)WebPSafeCalloc(kHistoTotal, sizeof(*histo) * 256); + if (histo != NULL) { + int i, x, y; + const uint32_t* prev_row = NULL; + const uint32_t* curr_row = argb; + uint32_t pix_prev = argb[0]; // Skip the first pixel. + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + const uint32_t pix = curr_row[x]; + const uint32_t pix_diff = VP8LSubPixels(pix, pix_prev); + pix_prev = pix; + if ((pix_diff == 0) || (prev_row != NULL && pix == prev_row[x])) { + continue; + } + AddSingle(pix, + &histo[kHistoAlpha * 256], + &histo[kHistoRed * 256], + &histo[kHistoGreen * 256], + &histo[kHistoBlue * 256]); + AddSingle(pix_diff, + &histo[kHistoAlphaPred * 256], + &histo[kHistoRedPred * 256], + &histo[kHistoGreenPred * 256], + &histo[kHistoBluePred * 256]); + AddSingleSubGreen(pix, + &histo[kHistoRedSubGreen * 256], + &histo[kHistoBlueSubGreen * 256]); + AddSingleSubGreen(pix_diff, + &histo[kHistoRedPredSubGreen * 256], + &histo[kHistoBluePredSubGreen * 256]); + { + // Approximate the palette by the entropy of the multiplicative hash. + const uint32_t hash = HashPix(pix); + ++histo[kHistoPalette * 256 + hash]; + } + } + prev_row = curr_row; + curr_row += argb_stride; + } + { + float entropy_comp[kHistoTotal]; + float entropy[kNumEntropyIx]; + int k; + int last_mode_to_analyze = use_palette ? kPalette : kSpatialSubGreen; + int j; + // Let's add one zero to the predicted histograms. The zeros are removed + // too efficiently by the pix_diff == 0 comparison, at least one of the + // zeros is likely to exist. + ++histo[kHistoRedPredSubGreen * 256]; + ++histo[kHistoBluePredSubGreen * 256]; + ++histo[kHistoRedPred * 256]; + ++histo[kHistoGreenPred * 256]; + ++histo[kHistoBluePred * 256]; + ++histo[kHistoAlphaPred * 256]; + + for (j = 0; j < kHistoTotal; ++j) { + entropy_comp[j] = VP8LBitsEntropy(&histo[j * 256], 256); + } + entropy[kDirect] = entropy_comp[kHistoAlpha] + + entropy_comp[kHistoRed] + + entropy_comp[kHistoGreen] + + entropy_comp[kHistoBlue]; + entropy[kSpatial] = entropy_comp[kHistoAlphaPred] + + entropy_comp[kHistoRedPred] + + entropy_comp[kHistoGreenPred] + + entropy_comp[kHistoBluePred]; + entropy[kSubGreen] = entropy_comp[kHistoAlpha] + + entropy_comp[kHistoRedSubGreen] + + entropy_comp[kHistoGreen] + + entropy_comp[kHistoBlueSubGreen]; + entropy[kSpatialSubGreen] = entropy_comp[kHistoAlphaPred] + + entropy_comp[kHistoRedPredSubGreen] + + entropy_comp[kHistoGreenPred] + + entropy_comp[kHistoBluePredSubGreen]; + entropy[kPalette] = entropy_comp[kHistoPalette]; + + // When including transforms, there is an overhead in bits from + // storing them. This overhead is small but matters for small images. + // For spatial, there are 14 transformations. + entropy[kSpatial] += VP8LSubSampleSize(width, transform_bits) * + VP8LSubSampleSize(height, transform_bits) * + VP8LFastLog2(14); + // For color transforms: 24 as only 3 channels are considered in a + // ColorTransformElement. + entropy[kSpatialSubGreen] += VP8LSubSampleSize(width, transform_bits) * + VP8LSubSampleSize(height, transform_bits) * + VP8LFastLog2(24); + // For palettes, add the cost of storing the palette. + // We empirically estimate the cost of a compressed entry as 8 bits. + // The palette is differential-coded when compressed hence a much + // lower cost than sizeof(uint32_t)*8. + entropy[kPalette] += palette_size * 8; + + *min_entropy_ix = kDirect; + for (k = kDirect + 1; k <= last_mode_to_analyze; ++k) { + if (entropy[*min_entropy_ix] > entropy[k]) { + *min_entropy_ix = (EntropyIx)k; + } + } + assert((int)*min_entropy_ix <= last_mode_to_analyze); + *red_and_blue_always_zero = 1; + // Let's check if the histogram of the chosen entropy mode has + // non-zero red and blue values. If all are zero, we can later skip + // the cross color optimization. + { + static const uint8_t kHistoPairs[5][2] = { + { kHistoRed, kHistoBlue }, + { kHistoRedPred, kHistoBluePred }, + { kHistoRedSubGreen, kHistoBlueSubGreen }, + { kHistoRedPredSubGreen, kHistoBluePredSubGreen }, + { kHistoRed, kHistoBlue } + }; + const uint32_t* const red_histo = + &histo[256 * kHistoPairs[*min_entropy_ix][0]]; + const uint32_t* const blue_histo = + &histo[256 * kHistoPairs[*min_entropy_ix][1]]; + for (i = 1; i < 256; ++i) { + if ((red_histo[i] | blue_histo[i]) != 0) { + *red_and_blue_always_zero = 0; + break; + } + } + } + } + WebPSafeFree(histo); + return 1; + } else { + return 0; + } +} + +static int GetHistoBits(int method, int use_palette, int width, int height) { + // Make tile size a function of encoding method (Range: 0 to 6). + int histo_bits = (use_palette ? 9 : 7) - method; + while (1) { + const int huff_image_size = VP8LSubSampleSize(width, histo_bits) * + VP8LSubSampleSize(height, histo_bits); + if (huff_image_size <= MAX_HUFF_IMAGE_SIZE) break; + ++histo_bits; + } + return (histo_bits < MIN_HUFFMAN_BITS) ? MIN_HUFFMAN_BITS : + (histo_bits > MAX_HUFFMAN_BITS) ? MAX_HUFFMAN_BITS : histo_bits; +} + +static int GetTransformBits(int method, int histo_bits) { + const int max_transform_bits = (method < 4) ? 6 : (method > 4) ? 4 : 5; + const int res = + (histo_bits > max_transform_bits) ? max_transform_bits : histo_bits; + assert(res <= MAX_TRANSFORM_BITS); + return res; +} + +// Set of parameters to be used in each iteration of the cruncher. +#define CRUNCH_SUBCONFIGS_MAX 2 +typedef struct { + int lz77_; + int do_no_cache_; +} CrunchSubConfig; +typedef struct { + int entropy_idx_; + PaletteSorting palette_sorting_type_; + CrunchSubConfig sub_configs_[CRUNCH_SUBCONFIGS_MAX]; + int sub_configs_size_; +} CrunchConfig; + +// +2 because we add a palette sorting configuration for kPalette and +// kPaletteAndSpatial. +#define CRUNCH_CONFIGS_MAX (kNumEntropyIx + 2 * kPaletteSortingNum) + +static int EncoderAnalyze(VP8LEncoder* const enc, + CrunchConfig crunch_configs[CRUNCH_CONFIGS_MAX], + int* const crunch_configs_size, + int* const red_and_blue_always_zero) { + const WebPPicture* const pic = enc->pic_; + const int width = pic->width; + const int height = pic->height; + const WebPConfig* const config = enc->config_; + const int method = config->method; + const int low_effort = (config->method == 0); + int i; + int use_palette; + int n_lz77s; + // If set to 0, analyze the cache with the computed cache value. If 1, also + // analyze with no-cache. + int do_no_cache = 0; + assert(pic != NULL && pic->argb != NULL); + + // Check whether a palette is possible. + enc->palette_size_ = GetColorPalette(pic, enc->palette_sorted_); + use_palette = (enc->palette_size_ <= MAX_PALETTE_SIZE); + if (!use_palette) { + enc->palette_size_ = 0; + } + + // Empirical bit sizes. + enc->histo_bits_ = GetHistoBits(method, use_palette, + pic->width, pic->height); + enc->transform_bits_ = GetTransformBits(method, enc->histo_bits_); + + if (low_effort) { + // AnalyzeEntropy is somewhat slow. + crunch_configs[0].entropy_idx_ = use_palette ? kPalette : kSpatialSubGreen; + crunch_configs[0].palette_sorting_type_ = + use_palette ? kSortedDefault : kUnusedPalette; + n_lz77s = 1; + *crunch_configs_size = 1; + } else { + EntropyIx min_entropy_ix; + // Try out multiple LZ77 on images with few colors. + n_lz77s = (enc->palette_size_ > 0 && enc->palette_size_ <= 16) ? 2 : 1; + if (!AnalyzeEntropy(pic->argb, width, height, pic->argb_stride, use_palette, + enc->palette_size_, enc->transform_bits_, + &min_entropy_ix, red_and_blue_always_zero)) { + return 0; + } + if (method == 6 && config->quality == 100) { + do_no_cache = 1; + // Go brute force on all transforms. + *crunch_configs_size = 0; + for (i = 0; i < kNumEntropyIx; ++i) { + // We can only apply kPalette or kPaletteAndSpatial if we can indeed use + // a palette. + if ((i != kPalette && i != kPaletteAndSpatial) || use_palette) { + assert(*crunch_configs_size < CRUNCH_CONFIGS_MAX); + if (use_palette && (i == kPalette || i == kPaletteAndSpatial)) { + int sorting_method; + for (sorting_method = 0; sorting_method < kPaletteSortingNum; + ++sorting_method) { + const PaletteSorting typed_sorting_method = + (PaletteSorting)sorting_method; + // TODO(vrabaud) kSortedDefault should be tested. It is omitted + // for now for backward compatibility. + if (typed_sorting_method == kUnusedPalette || + typed_sorting_method == kSortedDefault) { + continue; + } + crunch_configs[(*crunch_configs_size)].entropy_idx_ = i; + crunch_configs[(*crunch_configs_size)].palette_sorting_type_ = + typed_sorting_method; + ++*crunch_configs_size; + } + } else { + crunch_configs[(*crunch_configs_size)].entropy_idx_ = i; + crunch_configs[(*crunch_configs_size)].palette_sorting_type_ = + kUnusedPalette; + ++*crunch_configs_size; + } + } + } + } else { + // Only choose the guessed best transform. + *crunch_configs_size = 1; + crunch_configs[0].entropy_idx_ = min_entropy_ix; + crunch_configs[0].palette_sorting_type_ = + use_palette ? kMinimizeDelta : kUnusedPalette; + if (config->quality >= 75 && method == 5) { + // Test with and without color cache. + do_no_cache = 1; + // If we have a palette, also check in combination with spatial. + if (min_entropy_ix == kPalette) { + *crunch_configs_size = 2; + crunch_configs[1].entropy_idx_ = kPaletteAndSpatial; + crunch_configs[1].palette_sorting_type_ = kMinimizeDelta; + } + } + } + } + // Fill in the different LZ77s. + assert(n_lz77s <= CRUNCH_SUBCONFIGS_MAX); + for (i = 0; i < *crunch_configs_size; ++i) { + int j; + for (j = 0; j < n_lz77s; ++j) { + assert(j < CRUNCH_SUBCONFIGS_MAX); + crunch_configs[i].sub_configs_[j].lz77_ = + (j == 0) ? kLZ77Standard | kLZ77RLE : kLZ77Box; + crunch_configs[i].sub_configs_[j].do_no_cache_ = do_no_cache; + } + crunch_configs[i].sub_configs_size_ = n_lz77s; + } + return 1; +} + +static int EncoderInit(VP8LEncoder* const enc) { + const WebPPicture* const pic = enc->pic_; + const int width = pic->width; + const int height = pic->height; + const int pix_cnt = width * height; + // we round the block size up, so we're guaranteed to have + // at most MAX_REFS_BLOCK_PER_IMAGE blocks used: + const int refs_block_size = (pix_cnt - 1) / MAX_REFS_BLOCK_PER_IMAGE + 1; + int i; + if (!VP8LHashChainInit(&enc->hash_chain_, pix_cnt)) return 0; + + for (i = 0; i < 4; ++i) VP8LBackwardRefsInit(&enc->refs_[i], refs_block_size); + + return 1; +} + +// Returns false in case of memory error. +static int GetHuffBitLengthsAndCodes( + const VP8LHistogramSet* const histogram_image, + HuffmanTreeCode* const huffman_codes) { + int i, k; + int ok = 0; + uint64_t total_length_size = 0; + uint8_t* mem_buf = NULL; + const int histogram_image_size = histogram_image->size; + int max_num_symbols = 0; + uint8_t* buf_rle = NULL; + HuffmanTree* huff_tree = NULL; + + // Iterate over all histograms and get the aggregate number of codes used. + for (i = 0; i < histogram_image_size; ++i) { + const VP8LHistogram* const histo = histogram_image->histograms[i]; + HuffmanTreeCode* const codes = &huffman_codes[5 * i]; + assert(histo != NULL); + for (k = 0; k < 5; ++k) { + const int num_symbols = + (k == 0) ? VP8LHistogramNumCodes(histo->palette_code_bits_) : + (k == 4) ? NUM_DISTANCE_CODES : 256; + codes[k].num_symbols = num_symbols; + total_length_size += num_symbols; + } + } + + // Allocate and Set Huffman codes. + { + uint16_t* codes; + uint8_t* lengths; + mem_buf = (uint8_t*)WebPSafeCalloc(total_length_size, + sizeof(*lengths) + sizeof(*codes)); + if (mem_buf == NULL) goto End; + + codes = (uint16_t*)mem_buf; + lengths = (uint8_t*)&codes[total_length_size]; + for (i = 0; i < 5 * histogram_image_size; ++i) { + const int bit_length = huffman_codes[i].num_symbols; + huffman_codes[i].codes = codes; + huffman_codes[i].code_lengths = lengths; + codes += bit_length; + lengths += bit_length; + if (max_num_symbols < bit_length) { + max_num_symbols = bit_length; + } + } + } + + buf_rle = (uint8_t*)WebPSafeMalloc(1ULL, max_num_symbols); + huff_tree = (HuffmanTree*)WebPSafeMalloc(3ULL * max_num_symbols, + sizeof(*huff_tree)); + if (buf_rle == NULL || huff_tree == NULL) goto End; + + // Create Huffman trees. + for (i = 0; i < histogram_image_size; ++i) { + HuffmanTreeCode* const codes = &huffman_codes[5 * i]; + VP8LHistogram* const histo = histogram_image->histograms[i]; + VP8LCreateHuffmanTree(histo->literal_, 15, buf_rle, huff_tree, codes + 0); + VP8LCreateHuffmanTree(histo->red_, 15, buf_rle, huff_tree, codes + 1); + VP8LCreateHuffmanTree(histo->blue_, 15, buf_rle, huff_tree, codes + 2); + VP8LCreateHuffmanTree(histo->alpha_, 15, buf_rle, huff_tree, codes + 3); + VP8LCreateHuffmanTree(histo->distance_, 15, buf_rle, huff_tree, codes + 4); + } + ok = 1; + End: + WebPSafeFree(huff_tree); + WebPSafeFree(buf_rle); + if (!ok) { + WebPSafeFree(mem_buf); + memset(huffman_codes, 0, 5 * histogram_image_size * sizeof(*huffman_codes)); + } + return ok; +} + +static void StoreHuffmanTreeOfHuffmanTreeToBitMask( + VP8LBitWriter* const bw, const uint8_t* code_length_bitdepth) { + // RFC 1951 will calm you down if you are worried about this funny sequence. + // This sequence is tuned from that, but more weighted for lower symbol count, + // and more spiking histograms. + static const uint8_t kStorageOrder[CODE_LENGTH_CODES] = { + 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + }; + int i; + // Throw away trailing zeros: + int codes_to_store = CODE_LENGTH_CODES; + for (; codes_to_store > 4; --codes_to_store) { + if (code_length_bitdepth[kStorageOrder[codes_to_store - 1]] != 0) { + break; + } + } + VP8LPutBits(bw, codes_to_store - 4, 4); + for (i = 0; i < codes_to_store; ++i) { + VP8LPutBits(bw, code_length_bitdepth[kStorageOrder[i]], 3); + } +} + +static void ClearHuffmanTreeIfOnlyOneSymbol( + HuffmanTreeCode* const huffman_code) { + int k; + int count = 0; + for (k = 0; k < huffman_code->num_symbols; ++k) { + if (huffman_code->code_lengths[k] != 0) { + ++count; + if (count > 1) return; + } + } + for (k = 0; k < huffman_code->num_symbols; ++k) { + huffman_code->code_lengths[k] = 0; + huffman_code->codes[k] = 0; + } +} + +static void StoreHuffmanTreeToBitMask( + VP8LBitWriter* const bw, + const HuffmanTreeToken* const tokens, const int num_tokens, + const HuffmanTreeCode* const huffman_code) { + int i; + for (i = 0; i < num_tokens; ++i) { + const int ix = tokens[i].code; + const int extra_bits = tokens[i].extra_bits; + VP8LPutBits(bw, huffman_code->codes[ix], huffman_code->code_lengths[ix]); + switch (ix) { + case 16: + VP8LPutBits(bw, extra_bits, 2); + break; + case 17: + VP8LPutBits(bw, extra_bits, 3); + break; + case 18: + VP8LPutBits(bw, extra_bits, 7); + break; + } + } +} + +// 'huff_tree' and 'tokens' are pre-alloacted buffers. +static void StoreFullHuffmanCode(VP8LBitWriter* const bw, + HuffmanTree* const huff_tree, + HuffmanTreeToken* const tokens, + const HuffmanTreeCode* const tree) { + uint8_t code_length_bitdepth[CODE_LENGTH_CODES] = { 0 }; + uint16_t code_length_bitdepth_symbols[CODE_LENGTH_CODES] = { 0 }; + const int max_tokens = tree->num_symbols; + int num_tokens; + HuffmanTreeCode huffman_code; + huffman_code.num_symbols = CODE_LENGTH_CODES; + huffman_code.code_lengths = code_length_bitdepth; + huffman_code.codes = code_length_bitdepth_symbols; + + VP8LPutBits(bw, 0, 1); + num_tokens = VP8LCreateCompressedHuffmanTree(tree, tokens, max_tokens); + { + uint32_t histogram[CODE_LENGTH_CODES] = { 0 }; + uint8_t buf_rle[CODE_LENGTH_CODES] = { 0 }; + int i; + for (i = 0; i < num_tokens; ++i) { + ++histogram[tokens[i].code]; + } + + VP8LCreateHuffmanTree(histogram, 7, buf_rle, huff_tree, &huffman_code); + } + + StoreHuffmanTreeOfHuffmanTreeToBitMask(bw, code_length_bitdepth); + ClearHuffmanTreeIfOnlyOneSymbol(&huffman_code); + { + int trailing_zero_bits = 0; + int trimmed_length = num_tokens; + int write_trimmed_length; + int length; + int i = num_tokens; + while (i-- > 0) { + const int ix = tokens[i].code; + if (ix == 0 || ix == 17 || ix == 18) { + --trimmed_length; // discount trailing zeros + trailing_zero_bits += code_length_bitdepth[ix]; + if (ix == 17) { + trailing_zero_bits += 3; + } else if (ix == 18) { + trailing_zero_bits += 7; + } + } else { + break; + } + } + write_trimmed_length = (trimmed_length > 1 && trailing_zero_bits > 12); + length = write_trimmed_length ? trimmed_length : num_tokens; + VP8LPutBits(bw, write_trimmed_length, 1); + if (write_trimmed_length) { + if (trimmed_length == 2) { + VP8LPutBits(bw, 0, 3 + 2); // nbitpairs=1, trimmed_length=2 + } else { + const int nbits = BitsLog2Floor(trimmed_length - 2); + const int nbitpairs = nbits / 2 + 1; + assert(trimmed_length > 2); + assert(nbitpairs - 1 < 8); + VP8LPutBits(bw, nbitpairs - 1, 3); + VP8LPutBits(bw, trimmed_length - 2, nbitpairs * 2); + } + } + StoreHuffmanTreeToBitMask(bw, tokens, length, &huffman_code); + } +} + +// 'huff_tree' and 'tokens' are pre-alloacted buffers. +static void StoreHuffmanCode(VP8LBitWriter* const bw, + HuffmanTree* const huff_tree, + HuffmanTreeToken* const tokens, + const HuffmanTreeCode* const huffman_code) { + int i; + int count = 0; + int symbols[2] = { 0, 0 }; + const int kMaxBits = 8; + const int kMaxSymbol = 1 << kMaxBits; + + // Check whether it's a small tree. + for (i = 0; i < huffman_code->num_symbols && count < 3; ++i) { + if (huffman_code->code_lengths[i] != 0) { + if (count < 2) symbols[count] = i; + ++count; + } + } + + if (count == 0) { // emit minimal tree for empty cases + // bits: small tree marker: 1, count-1: 0, large 8-bit code: 0, code: 0 + VP8LPutBits(bw, 0x01, 4); + } else if (count <= 2 && symbols[0] < kMaxSymbol && symbols[1] < kMaxSymbol) { + VP8LPutBits(bw, 1, 1); // Small tree marker to encode 1 or 2 symbols. + VP8LPutBits(bw, count - 1, 1); + if (symbols[0] <= 1) { + VP8LPutBits(bw, 0, 1); // Code bit for small (1 bit) symbol value. + VP8LPutBits(bw, symbols[0], 1); + } else { + VP8LPutBits(bw, 1, 1); + VP8LPutBits(bw, symbols[0], 8); + } + if (count == 2) { + VP8LPutBits(bw, symbols[1], 8); + } + } else { + StoreFullHuffmanCode(bw, huff_tree, tokens, huffman_code); + } +} + +static WEBP_INLINE void WriteHuffmanCode(VP8LBitWriter* const bw, + const HuffmanTreeCode* const code, + int code_index) { + const int depth = code->code_lengths[code_index]; + const int symbol = code->codes[code_index]; + VP8LPutBits(bw, symbol, depth); +} + +static WEBP_INLINE void WriteHuffmanCodeWithExtraBits( + VP8LBitWriter* const bw, + const HuffmanTreeCode* const code, + int code_index, + int bits, + int n_bits) { + const int depth = code->code_lengths[code_index]; + const int symbol = code->codes[code_index]; + VP8LPutBits(bw, (bits << depth) | symbol, depth + n_bits); +} + +static int StoreImageToBitMask( + VP8LBitWriter* const bw, int width, int histo_bits, + const VP8LBackwardRefs* const refs, + const uint16_t* histogram_symbols, + const HuffmanTreeCode* const huffman_codes, const WebPPicture* const pic) { + const int histo_xsize = histo_bits ? VP8LSubSampleSize(width, histo_bits) : 1; + const int tile_mask = (histo_bits == 0) ? 0 : -(1 << histo_bits); + // x and y trace the position in the image. + int x = 0; + int y = 0; + int tile_x = x & tile_mask; + int tile_y = y & tile_mask; + int histogram_ix = histogram_symbols[0]; + const HuffmanTreeCode* codes = huffman_codes + 5 * histogram_ix; + VP8LRefsCursor c = VP8LRefsCursorInit(refs); + while (VP8LRefsCursorOk(&c)) { + const PixOrCopy* const v = c.cur_pos; + if ((tile_x != (x & tile_mask)) || (tile_y != (y & tile_mask))) { + tile_x = x & tile_mask; + tile_y = y & tile_mask; + histogram_ix = histogram_symbols[(y >> histo_bits) * histo_xsize + + (x >> histo_bits)]; + codes = huffman_codes + 5 * histogram_ix; + } + if (PixOrCopyIsLiteral(v)) { + static const uint8_t order[] = { 1, 2, 0, 3 }; + int k; + for (k = 0; k < 4; ++k) { + const int code = PixOrCopyLiteral(v, order[k]); + WriteHuffmanCode(bw, codes + k, code); + } + } else if (PixOrCopyIsCacheIdx(v)) { + const int code = PixOrCopyCacheIdx(v); + const int literal_ix = 256 + NUM_LENGTH_CODES + code; + WriteHuffmanCode(bw, codes, literal_ix); + } else { + int bits, n_bits; + int code; + + const int distance = PixOrCopyDistance(v); + VP8LPrefixEncode(v->len, &code, &n_bits, &bits); + WriteHuffmanCodeWithExtraBits(bw, codes, 256 + code, bits, n_bits); + + // Don't write the distance with the extra bits code since + // the distance can be up to 18 bits of extra bits, and the prefix + // 15 bits, totaling to 33, and our PutBits only supports up to 32 bits. + VP8LPrefixEncode(distance, &code, &n_bits, &bits); + WriteHuffmanCode(bw, codes + 4, code); + VP8LPutBits(bw, bits, n_bits); + } + x += PixOrCopyLength(v); + while (x >= width) { + x -= width; + ++y; + } + VP8LRefsCursorNext(&c); + } + if (bw->error_) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + return 1; +} + +// Special case of EncodeImageInternal() for cache-bits=0, histo_bits=31. +// pic and percent are for progress. +static int EncodeImageNoHuffman(VP8LBitWriter* const bw, + const uint32_t* const argb, + VP8LHashChain* const hash_chain, + VP8LBackwardRefs* const refs_array, int width, + int height, int quality, int low_effort, + const WebPPicture* const pic, int percent_range, + int* const percent) { + int i; + int max_tokens = 0; + VP8LBackwardRefs* refs; + HuffmanTreeToken* tokens = NULL; + HuffmanTreeCode huffman_codes[5] = {{0, NULL, NULL}}; + const uint16_t histogram_symbols[1] = {0}; // only one tree, one symbol + int cache_bits = 0; + VP8LHistogramSet* histogram_image = NULL; + HuffmanTree* const huff_tree = (HuffmanTree*)WebPSafeMalloc( + 3ULL * CODE_LENGTH_CODES, sizeof(*huff_tree)); + if (huff_tree == NULL) { + WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + + // Calculate backward references from ARGB image. + if (!VP8LHashChainFill(hash_chain, quality, argb, width, height, low_effort, + pic, percent_range / 2, percent)) { + goto Error; + } + if (!VP8LGetBackwardReferences(width, height, argb, quality, /*low_effort=*/0, + kLZ77Standard | kLZ77RLE, cache_bits, + /*do_no_cache=*/0, hash_chain, refs_array, + &cache_bits, pic, + percent_range - percent_range / 2, percent)) { + goto Error; + } + refs = &refs_array[0]; + histogram_image = VP8LAllocateHistogramSet(1, cache_bits); + if (histogram_image == NULL) { + WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + VP8LHistogramSetClear(histogram_image); + + // Build histogram image and symbols from backward references. + VP8LHistogramStoreRefs(refs, histogram_image->histograms[0]); + + // Create Huffman bit lengths and codes for each histogram image. + assert(histogram_image->size == 1); + if (!GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) { + WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + + // No color cache, no Huffman image. + VP8LPutBits(bw, 0, 1); + + // Find maximum number of symbols for the huffman tree-set. + for (i = 0; i < 5; ++i) { + HuffmanTreeCode* const codes = &huffman_codes[i]; + if (max_tokens < codes->num_symbols) { + max_tokens = codes->num_symbols; + } + } + + tokens = (HuffmanTreeToken*)WebPSafeMalloc(max_tokens, sizeof(*tokens)); + if (tokens == NULL) { + WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + + // Store Huffman codes. + for (i = 0; i < 5; ++i) { + HuffmanTreeCode* const codes = &huffman_codes[i]; + StoreHuffmanCode(bw, huff_tree, tokens, codes); + ClearHuffmanTreeIfOnlyOneSymbol(codes); + } + + // Store actual literals. + if (!StoreImageToBitMask(bw, width, 0, refs, histogram_symbols, huffman_codes, + pic)) { + goto Error; + } + + Error: + WebPSafeFree(tokens); + WebPSafeFree(huff_tree); + VP8LFreeHistogramSet(histogram_image); + WebPSafeFree(huffman_codes[0].codes); + return (pic->error_code == VP8_ENC_OK); +} + +// pic and percent are for progress. +static int EncodeImageInternal( + VP8LBitWriter* const bw, const uint32_t* const argb, + VP8LHashChain* const hash_chain, VP8LBackwardRefs refs_array[4], int width, + int height, int quality, int low_effort, int use_cache, + const CrunchConfig* const config, int* cache_bits, int histogram_bits, + size_t init_byte_position, int* const hdr_size, int* const data_size, + const WebPPicture* const pic, int percent_range, int* const percent) { + const uint32_t histogram_image_xysize = + VP8LSubSampleSize(width, histogram_bits) * + VP8LSubSampleSize(height, histogram_bits); + int remaining_percent = percent_range; + int percent_start = *percent; + VP8LHistogramSet* histogram_image = NULL; + VP8LHistogram* tmp_histo = NULL; + int histogram_image_size = 0; + size_t bit_array_size = 0; + HuffmanTree* const huff_tree = (HuffmanTree*)WebPSafeMalloc( + 3ULL * CODE_LENGTH_CODES, sizeof(*huff_tree)); + HuffmanTreeToken* tokens = NULL; + HuffmanTreeCode* huffman_codes = NULL; + uint16_t* const histogram_symbols = (uint16_t*)WebPSafeMalloc( + histogram_image_xysize, sizeof(*histogram_symbols)); + int sub_configs_idx; + int cache_bits_init, write_histogram_image; + VP8LBitWriter bw_init = *bw, bw_best; + int hdr_size_tmp; + VP8LHashChain hash_chain_histogram; // histogram image hash chain + size_t bw_size_best = ~(size_t)0; + assert(histogram_bits >= MIN_HUFFMAN_BITS); + assert(histogram_bits <= MAX_HUFFMAN_BITS); + assert(hdr_size != NULL); + assert(data_size != NULL); + + memset(&hash_chain_histogram, 0, sizeof(hash_chain_histogram)); + if (!VP8LBitWriterInit(&bw_best, 0)) { + WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + + // Make sure we can allocate the different objects. + if (huff_tree == NULL || histogram_symbols == NULL || + !VP8LHashChainInit(&hash_chain_histogram, histogram_image_xysize)) { + WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + + percent_range = remaining_percent / 5; + if (!VP8LHashChainFill(hash_chain, quality, argb, width, height, + low_effort, pic, percent_range, percent)) { + goto Error; + } + percent_start += percent_range; + remaining_percent -= percent_range; + + if (use_cache) { + // If the value is different from zero, it has been set during the + // palette analysis. + cache_bits_init = (*cache_bits == 0) ? MAX_COLOR_CACHE_BITS : *cache_bits; + } else { + cache_bits_init = 0; + } + // If several iterations will happen, clone into bw_best. + if ((config->sub_configs_size_ > 1 || config->sub_configs_[0].do_no_cache_) && + !VP8LBitWriterClone(bw, &bw_best)) { + WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + + for (sub_configs_idx = 0; sub_configs_idx < config->sub_configs_size_; + ++sub_configs_idx) { + const CrunchSubConfig* const sub_config = + &config->sub_configs_[sub_configs_idx]; + int cache_bits_best, i_cache; + int i_remaining_percent = remaining_percent / config->sub_configs_size_; + int i_percent_range = i_remaining_percent / 4; + i_remaining_percent -= i_percent_range; + + if (!VP8LGetBackwardReferences( + width, height, argb, quality, low_effort, sub_config->lz77_, + cache_bits_init, sub_config->do_no_cache_, hash_chain, + &refs_array[0], &cache_bits_best, pic, i_percent_range, percent)) { + goto Error; + } + + for (i_cache = 0; i_cache < (sub_config->do_no_cache_ ? 2 : 1); ++i_cache) { + const int cache_bits_tmp = (i_cache == 0) ? cache_bits_best : 0; + // Speed-up: no need to study the no-cache case if it was already studied + // in i_cache == 0. + if (i_cache == 1 && cache_bits_best == 0) break; + + // Reset the bit writer for this iteration. + VP8LBitWriterReset(&bw_init, bw); + + // Build histogram image and symbols from backward references. + histogram_image = + VP8LAllocateHistogramSet(histogram_image_xysize, cache_bits_tmp); + tmp_histo = VP8LAllocateHistogram(cache_bits_tmp); + if (histogram_image == NULL || tmp_histo == NULL) { + WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + + i_percent_range = i_remaining_percent / 3; + i_remaining_percent -= i_percent_range; + if (!VP8LGetHistoImageSymbols( + width, height, &refs_array[i_cache], quality, low_effort, + histogram_bits, cache_bits_tmp, histogram_image, tmp_histo, + histogram_symbols, pic, i_percent_range, percent)) { + goto Error; + } + // Create Huffman bit lengths and codes for each histogram image. + histogram_image_size = histogram_image->size; + bit_array_size = 5 * histogram_image_size; + huffman_codes = (HuffmanTreeCode*)WebPSafeCalloc(bit_array_size, + sizeof(*huffman_codes)); + // Note: some histogram_image entries may point to tmp_histos[], so the + // latter need to outlive the following call to + // GetHuffBitLengthsAndCodes(). + if (huffman_codes == NULL || + !GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) { + WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + // Free combined histograms. + VP8LFreeHistogramSet(histogram_image); + histogram_image = NULL; + + // Free scratch histograms. + VP8LFreeHistogram(tmp_histo); + tmp_histo = NULL; + + // Color Cache parameters. + if (cache_bits_tmp > 0) { + VP8LPutBits(bw, 1, 1); + VP8LPutBits(bw, cache_bits_tmp, 4); + } else { + VP8LPutBits(bw, 0, 1); + } + + // Huffman image + meta huffman. + write_histogram_image = (histogram_image_size > 1); + VP8LPutBits(bw, write_histogram_image, 1); + if (write_histogram_image) { + uint32_t* const histogram_argb = (uint32_t*)WebPSafeMalloc( + histogram_image_xysize, sizeof(*histogram_argb)); + int max_index = 0; + uint32_t i; + if (histogram_argb == NULL) { + WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + for (i = 0; i < histogram_image_xysize; ++i) { + const int symbol_index = histogram_symbols[i] & 0xffff; + histogram_argb[i] = (symbol_index << 8); + if (symbol_index >= max_index) { + max_index = symbol_index + 1; + } + } + histogram_image_size = max_index; + + VP8LPutBits(bw, histogram_bits - 2, 3); + i_percent_range = i_remaining_percent / 2; + i_remaining_percent -= i_percent_range; + if (!EncodeImageNoHuffman( + bw, histogram_argb, &hash_chain_histogram, &refs_array[2], + VP8LSubSampleSize(width, histogram_bits), + VP8LSubSampleSize(height, histogram_bits), quality, low_effort, + pic, i_percent_range, percent)) { + WebPSafeFree(histogram_argb); + goto Error; + } + WebPSafeFree(histogram_argb); + } + + // Store Huffman codes. + { + int i; + int max_tokens = 0; + // Find maximum number of symbols for the huffman tree-set. + for (i = 0; i < 5 * histogram_image_size; ++i) { + HuffmanTreeCode* const codes = &huffman_codes[i]; + if (max_tokens < codes->num_symbols) { + max_tokens = codes->num_symbols; + } + } + tokens = (HuffmanTreeToken*)WebPSafeMalloc(max_tokens, sizeof(*tokens)); + if (tokens == NULL) { + WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + for (i = 0; i < 5 * histogram_image_size; ++i) { + HuffmanTreeCode* const codes = &huffman_codes[i]; + StoreHuffmanCode(bw, huff_tree, tokens, codes); + ClearHuffmanTreeIfOnlyOneSymbol(codes); + } + } + // Store actual literals. + hdr_size_tmp = (int)(VP8LBitWriterNumBytes(bw) - init_byte_position); + if (!StoreImageToBitMask(bw, width, histogram_bits, &refs_array[i_cache], + histogram_symbols, huffman_codes, pic)) { + goto Error; + } + // Keep track of the smallest image so far. + if (VP8LBitWriterNumBytes(bw) < bw_size_best) { + bw_size_best = VP8LBitWriterNumBytes(bw); + *cache_bits = cache_bits_tmp; + *hdr_size = hdr_size_tmp; + *data_size = + (int)(VP8LBitWriterNumBytes(bw) - init_byte_position - *hdr_size); + VP8LBitWriterSwap(bw, &bw_best); + } + WebPSafeFree(tokens); + tokens = NULL; + if (huffman_codes != NULL) { + WebPSafeFree(huffman_codes->codes); + WebPSafeFree(huffman_codes); + huffman_codes = NULL; + } + } + } + VP8LBitWriterSwap(bw, &bw_best); + + if (!WebPReportProgress(pic, percent_start + remaining_percent, percent)) { + goto Error; + } + + Error: + WebPSafeFree(tokens); + WebPSafeFree(huff_tree); + VP8LFreeHistogramSet(histogram_image); + VP8LFreeHistogram(tmp_histo); + VP8LHashChainClear(&hash_chain_histogram); + if (huffman_codes != NULL) { + WebPSafeFree(huffman_codes->codes); + WebPSafeFree(huffman_codes); + } + WebPSafeFree(histogram_symbols); + VP8LBitWriterWipeOut(&bw_best); + return (pic->error_code == VP8_ENC_OK); +} + +// ----------------------------------------------------------------------------- +// Transforms + +static void ApplySubtractGreen(VP8LEncoder* const enc, int width, int height, + VP8LBitWriter* const bw) { + VP8LPutBits(bw, TRANSFORM_PRESENT, 1); + VP8LPutBits(bw, SUBTRACT_GREEN_TRANSFORM, 2); + VP8LSubtractGreenFromBlueAndRed(enc->argb_, width * height); +} + +static int ApplyPredictFilter(const VP8LEncoder* const enc, int width, + int height, int quality, int low_effort, + int used_subtract_green, VP8LBitWriter* const bw, + int percent_range, int* const percent) { + const int pred_bits = enc->transform_bits_; + const int transform_width = VP8LSubSampleSize(width, pred_bits); + const int transform_height = VP8LSubSampleSize(height, pred_bits); + // we disable near-lossless quantization if palette is used. + const int near_lossless_strength = + enc->use_palette_ ? 100 : enc->config_->near_lossless; + + if (!VP8LResidualImage( + width, height, pred_bits, low_effort, enc->argb_, enc->argb_scratch_, + enc->transform_data_, near_lossless_strength, enc->config_->exact, + used_subtract_green, enc->pic_, percent_range / 2, percent)) { + return 0; + } + VP8LPutBits(bw, TRANSFORM_PRESENT, 1); + VP8LPutBits(bw, PREDICTOR_TRANSFORM, 2); + assert(pred_bits >= 2); + VP8LPutBits(bw, pred_bits - 2, 3); + return EncodeImageNoHuffman( + bw, enc->transform_data_, (VP8LHashChain*)&enc->hash_chain_, + (VP8LBackwardRefs*)&enc->refs_[0], transform_width, transform_height, + quality, low_effort, enc->pic_, percent_range - percent_range / 2, + percent); +} + +static int ApplyCrossColorFilter(const VP8LEncoder* const enc, int width, + int height, int quality, int low_effort, + VP8LBitWriter* const bw, int percent_range, + int* const percent) { + const int ccolor_transform_bits = enc->transform_bits_; + const int transform_width = VP8LSubSampleSize(width, ccolor_transform_bits); + const int transform_height = VP8LSubSampleSize(height, ccolor_transform_bits); + + if (!VP8LColorSpaceTransform(width, height, ccolor_transform_bits, quality, + enc->argb_, enc->transform_data_, enc->pic_, + percent_range / 2, percent)) { + return 0; + } + VP8LPutBits(bw, TRANSFORM_PRESENT, 1); + VP8LPutBits(bw, CROSS_COLOR_TRANSFORM, 2); + assert(ccolor_transform_bits >= 2); + VP8LPutBits(bw, ccolor_transform_bits - 2, 3); + return EncodeImageNoHuffman( + bw, enc->transform_data_, (VP8LHashChain*)&enc->hash_chain_, + (VP8LBackwardRefs*)&enc->refs_[0], transform_width, transform_height, + quality, low_effort, enc->pic_, percent_range - percent_range / 2, + percent); +} + +// ----------------------------------------------------------------------------- + +static int WriteRiffHeader(const WebPPicture* const pic, size_t riff_size, + size_t vp8l_size) { + uint8_t riff[RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE + VP8L_SIGNATURE_SIZE] = { + 'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'E', 'B', 'P', + 'V', 'P', '8', 'L', 0, 0, 0, 0, VP8L_MAGIC_BYTE, + }; + PutLE32(riff + TAG_SIZE, (uint32_t)riff_size); + PutLE32(riff + RIFF_HEADER_SIZE + TAG_SIZE, (uint32_t)vp8l_size); + return pic->writer(riff, sizeof(riff), pic); +} + +static int WriteImageSize(const WebPPicture* const pic, + VP8LBitWriter* const bw) { + const int width = pic->width - 1; + const int height = pic->height - 1; + assert(width < WEBP_MAX_DIMENSION && height < WEBP_MAX_DIMENSION); + + VP8LPutBits(bw, width, VP8L_IMAGE_SIZE_BITS); + VP8LPutBits(bw, height, VP8L_IMAGE_SIZE_BITS); + return !bw->error_; +} + +static int WriteRealAlphaAndVersion(VP8LBitWriter* const bw, int has_alpha) { + VP8LPutBits(bw, has_alpha, 1); + VP8LPutBits(bw, VP8L_VERSION, VP8L_VERSION_BITS); + return !bw->error_; +} + +static int WriteImage(const WebPPicture* const pic, VP8LBitWriter* const bw, + size_t* const coded_size) { + const uint8_t* const webpll_data = VP8LBitWriterFinish(bw); + const size_t webpll_size = VP8LBitWriterNumBytes(bw); + const size_t vp8l_size = VP8L_SIGNATURE_SIZE + webpll_size; + const size_t pad = vp8l_size & 1; + const size_t riff_size = TAG_SIZE + CHUNK_HEADER_SIZE + vp8l_size + pad; + *coded_size = 0; + + if (bw->error_) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + + if (!WriteRiffHeader(pic, riff_size, vp8l_size) || + !pic->writer(webpll_data, webpll_size, pic)) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_WRITE); + } + + if (pad) { + const uint8_t pad_byte[1] = { 0 }; + if (!pic->writer(pad_byte, 1, pic)) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_WRITE); + } + } + *coded_size = CHUNK_HEADER_SIZE + riff_size; + return 1; +} + +// ----------------------------------------------------------------------------- + +static void ClearTransformBuffer(VP8LEncoder* const enc) { + WebPSafeFree(enc->transform_mem_); + enc->transform_mem_ = NULL; + enc->transform_mem_size_ = 0; +} + +// Allocates the memory for argb (W x H) buffer, 2 rows of context for +// prediction and transform data. +// Flags influencing the memory allocated: +// enc->transform_bits_ +// enc->use_predict_, enc->use_cross_color_ +static int AllocateTransformBuffer(VP8LEncoder* const enc, int width, + int height) { + const uint64_t image_size = (uint64_t)width * height; + // VP8LResidualImage needs room for 2 scanlines of uint32 pixels with an extra + // pixel in each, plus 2 regular scanlines of bytes. + // TODO(skal): Clean up by using arithmetic in bytes instead of words. + const uint64_t argb_scratch_size = + enc->use_predict_ ? (width + 1) * 2 + (width * 2 + sizeof(uint32_t) - 1) / + sizeof(uint32_t) + : 0; + const uint64_t transform_data_size = + (enc->use_predict_ || enc->use_cross_color_) + ? (uint64_t)VP8LSubSampleSize(width, enc->transform_bits_) * + VP8LSubSampleSize(height, enc->transform_bits_) + : 0; + const uint64_t max_alignment_in_words = + (WEBP_ALIGN_CST + sizeof(uint32_t) - 1) / sizeof(uint32_t); + const uint64_t mem_size = image_size + max_alignment_in_words + + argb_scratch_size + max_alignment_in_words + + transform_data_size; + uint32_t* mem = enc->transform_mem_; + if (mem == NULL || mem_size > enc->transform_mem_size_) { + ClearTransformBuffer(enc); + mem = (uint32_t*)WebPSafeMalloc(mem_size, sizeof(*mem)); + if (mem == NULL) { + return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + enc->transform_mem_ = mem; + enc->transform_mem_size_ = (size_t)mem_size; + enc->argb_content_ = kEncoderNone; + } + enc->argb_ = mem; + mem = (uint32_t*)WEBP_ALIGN(mem + image_size); + enc->argb_scratch_ = mem; + mem = (uint32_t*)WEBP_ALIGN(mem + argb_scratch_size); + enc->transform_data_ = mem; + + enc->current_width_ = width; + return 1; +} + +static int MakeInputImageCopy(VP8LEncoder* const enc) { + const WebPPicture* const picture = enc->pic_; + const int width = picture->width; + const int height = picture->height; + + if (!AllocateTransformBuffer(enc, width, height)) return 0; + if (enc->argb_content_ == kEncoderARGB) return 1; + + { + uint32_t* dst = enc->argb_; + const uint32_t* src = picture->argb; + int y; + for (y = 0; y < height; ++y) { + memcpy(dst, src, width * sizeof(*dst)); + dst += width; + src += picture->argb_stride; + } + } + enc->argb_content_ = kEncoderARGB; + assert(enc->current_width_ == width); + return 1; +} + +// ----------------------------------------------------------------------------- + +#define APPLY_PALETTE_GREEDY_MAX 4 + +static WEBP_INLINE uint32_t SearchColorGreedy(const uint32_t palette[], + int palette_size, + uint32_t color) { + (void)palette_size; + assert(palette_size < APPLY_PALETTE_GREEDY_MAX); + assert(3 == APPLY_PALETTE_GREEDY_MAX - 1); + if (color == palette[0]) return 0; + if (color == palette[1]) return 1; + if (color == palette[2]) return 2; + return 3; +} + +static WEBP_INLINE uint32_t ApplyPaletteHash0(uint32_t color) { + // Focus on the green color. + return (color >> 8) & 0xff; +} + +#define PALETTE_INV_SIZE_BITS 11 +#define PALETTE_INV_SIZE (1 << PALETTE_INV_SIZE_BITS) + +static WEBP_INLINE uint32_t ApplyPaletteHash1(uint32_t color) { + // Forget about alpha. + return ((uint32_t)((color & 0x00ffffffu) * 4222244071ull)) >> + (32 - PALETTE_INV_SIZE_BITS); +} + +static WEBP_INLINE uint32_t ApplyPaletteHash2(uint32_t color) { + // Forget about alpha. + return ((uint32_t)((color & 0x00ffffffu) * ((1ull << 31) - 1))) >> + (32 - PALETTE_INV_SIZE_BITS); +} + +// Use 1 pixel cache for ARGB pixels. +#define APPLY_PALETTE_FOR(COLOR_INDEX) do { \ + uint32_t prev_pix = palette[0]; \ + uint32_t prev_idx = 0; \ + for (y = 0; y < height; ++y) { \ + for (x = 0; x < width; ++x) { \ + const uint32_t pix = src[x]; \ + if (pix != prev_pix) { \ + prev_idx = COLOR_INDEX; \ + prev_pix = pix; \ + } \ + tmp_row[x] = prev_idx; \ + } \ + VP8LBundleColorMap(tmp_row, width, xbits, dst); \ + src += src_stride; \ + dst += dst_stride; \ + } \ +} while (0) + +// Remap argb values in src[] to packed palettes entries in dst[] +// using 'row' as a temporary buffer of size 'width'. +// We assume that all src[] values have a corresponding entry in the palette. +// Note: src[] can be the same as dst[] +static int ApplyPalette(const uint32_t* src, uint32_t src_stride, uint32_t* dst, + uint32_t dst_stride, const uint32_t* palette, + int palette_size, int width, int height, int xbits, + const WebPPicture* const pic) { + // TODO(skal): this tmp buffer is not needed if VP8LBundleColorMap() can be + // made to work in-place. + uint8_t* const tmp_row = (uint8_t*)WebPSafeMalloc(width, sizeof(*tmp_row)); + int x, y; + + if (tmp_row == NULL) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + + if (palette_size < APPLY_PALETTE_GREEDY_MAX) { + APPLY_PALETTE_FOR(SearchColorGreedy(palette, palette_size, pix)); + } else { + int i, j; + uint16_t buffer[PALETTE_INV_SIZE]; + uint32_t (*const hash_functions[])(uint32_t) = { + ApplyPaletteHash0, ApplyPaletteHash1, ApplyPaletteHash2 + }; + + // Try to find a perfect hash function able to go from a color to an index + // within 1 << PALETTE_INV_SIZE_BITS in order to build a hash map to go + // from color to index in palette. + for (i = 0; i < 3; ++i) { + int use_LUT = 1; + // Set each element in buffer to max uint16_t. + memset(buffer, 0xff, sizeof(buffer)); + for (j = 0; j < palette_size; ++j) { + const uint32_t ind = hash_functions[i](palette[j]); + if (buffer[ind] != 0xffffu) { + use_LUT = 0; + break; + } else { + buffer[ind] = j; + } + } + if (use_LUT) break; + } + + if (i == 0) { + APPLY_PALETTE_FOR(buffer[ApplyPaletteHash0(pix)]); + } else if (i == 1) { + APPLY_PALETTE_FOR(buffer[ApplyPaletteHash1(pix)]); + } else if (i == 2) { + APPLY_PALETTE_FOR(buffer[ApplyPaletteHash2(pix)]); + } else { + uint32_t idx_map[MAX_PALETTE_SIZE]; + uint32_t palette_sorted[MAX_PALETTE_SIZE]; + PrepareMapToPalette(palette, palette_size, palette_sorted, idx_map); + APPLY_PALETTE_FOR( + idx_map[SearchColorNoIdx(palette_sorted, pix, palette_size)]); + } + } + WebPSafeFree(tmp_row); + return 1; +} +#undef APPLY_PALETTE_FOR +#undef PALETTE_INV_SIZE_BITS +#undef PALETTE_INV_SIZE +#undef APPLY_PALETTE_GREEDY_MAX + +// Note: Expects "enc->palette_" to be set properly. +static int MapImageFromPalette(VP8LEncoder* const enc, int in_place) { + const WebPPicture* const pic = enc->pic_; + const int width = pic->width; + const int height = pic->height; + const uint32_t* const palette = enc->palette_; + const uint32_t* src = in_place ? enc->argb_ : pic->argb; + const int src_stride = in_place ? enc->current_width_ : pic->argb_stride; + const int palette_size = enc->palette_size_; + int xbits; + + // Replace each input pixel by corresponding palette index. + // This is done line by line. + if (palette_size <= 4) { + xbits = (palette_size <= 2) ? 3 : 2; + } else { + xbits = (palette_size <= 16) ? 1 : 0; + } + + if (!AllocateTransformBuffer(enc, VP8LSubSampleSize(width, xbits), height)) { + return 0; + } + if (!ApplyPalette(src, src_stride, + enc->argb_, enc->current_width_, + palette, palette_size, width, height, xbits, pic)) { + return 0; + } + enc->argb_content_ = kEncoderPalette; + return 1; +} + +// Save palette_[] to bitstream. +static WebPEncodingError EncodePalette(VP8LBitWriter* const bw, int low_effort, + VP8LEncoder* const enc, + int percent_range, int* const percent) { + int i; + uint32_t tmp_palette[MAX_PALETTE_SIZE]; + const int palette_size = enc->palette_size_; + const uint32_t* const palette = enc->palette_; + VP8LPutBits(bw, TRANSFORM_PRESENT, 1); + VP8LPutBits(bw, COLOR_INDEXING_TRANSFORM, 2); + assert(palette_size >= 1 && palette_size <= MAX_PALETTE_SIZE); + VP8LPutBits(bw, palette_size - 1, 8); + for (i = palette_size - 1; i >= 1; --i) { + tmp_palette[i] = VP8LSubPixels(palette[i], palette[i - 1]); + } + tmp_palette[0] = palette[0]; + return EncodeImageNoHuffman(bw, tmp_palette, &enc->hash_chain_, + &enc->refs_[0], palette_size, 1, /*quality=*/20, + low_effort, enc->pic_, percent_range, percent); +} + +// ----------------------------------------------------------------------------- +// VP8LEncoder + +static VP8LEncoder* VP8LEncoderNew(const WebPConfig* const config, + const WebPPicture* const picture) { + VP8LEncoder* const enc = (VP8LEncoder*)WebPSafeCalloc(1ULL, sizeof(*enc)); + if (enc == NULL) { + WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + return NULL; + } + enc->config_ = config; + enc->pic_ = picture; + enc->argb_content_ = kEncoderNone; + + VP8LEncDspInit(); + + return enc; +} + +static void VP8LEncoderDelete(VP8LEncoder* enc) { + if (enc != NULL) { + int i; + VP8LHashChainClear(&enc->hash_chain_); + for (i = 0; i < 4; ++i) VP8LBackwardRefsClear(&enc->refs_[i]); + ClearTransformBuffer(enc); + WebPSafeFree(enc); + } +} + +// ----------------------------------------------------------------------------- +// Main call + +typedef struct { + const WebPConfig* config_; + const WebPPicture* picture_; + VP8LBitWriter* bw_; + VP8LEncoder* enc_; + int use_cache_; + CrunchConfig crunch_configs_[CRUNCH_CONFIGS_MAX]; + int num_crunch_configs_; + int red_and_blue_always_zero_; + WebPAuxStats* stats_; +} StreamEncodeContext; + +static int EncodeStreamHook(void* input, void* data2) { + StreamEncodeContext* const params = (StreamEncodeContext*)input; + const WebPConfig* const config = params->config_; + const WebPPicture* const picture = params->picture_; + VP8LBitWriter* const bw = params->bw_; + VP8LEncoder* const enc = params->enc_; + const int use_cache = params->use_cache_; + const CrunchConfig* const crunch_configs = params->crunch_configs_; + const int num_crunch_configs = params->num_crunch_configs_; + const int red_and_blue_always_zero = params->red_and_blue_always_zero_; +#if !defined(WEBP_DISABLE_STATS) + WebPAuxStats* const stats = params->stats_; +#endif + const int quality = (int)config->quality; + const int low_effort = (config->method == 0); +#if (WEBP_NEAR_LOSSLESS == 1) + const int width = picture->width; +#endif + const int height = picture->height; + const size_t byte_position = VP8LBitWriterNumBytes(bw); + int percent = 2; // for WebPProgressHook +#if (WEBP_NEAR_LOSSLESS == 1) + int use_near_lossless = 0; +#endif + int hdr_size = 0; + int data_size = 0; + int use_delta_palette = 0; + int idx; + size_t best_size = ~(size_t)0; + VP8LBitWriter bw_init = *bw, bw_best; + (void)data2; + + if (!VP8LBitWriterInit(&bw_best, 0) || + (num_crunch_configs > 1 && !VP8LBitWriterClone(bw, &bw_best))) { + WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + + for (idx = 0; idx < num_crunch_configs; ++idx) { + const int entropy_idx = crunch_configs[idx].entropy_idx_; + int remaining_percent = 97 / num_crunch_configs, percent_range; + enc->use_palette_ = + (entropy_idx == kPalette) || (entropy_idx == kPaletteAndSpatial); + enc->use_subtract_green_ = + (entropy_idx == kSubGreen) || (entropy_idx == kSpatialSubGreen); + enc->use_predict_ = (entropy_idx == kSpatial) || + (entropy_idx == kSpatialSubGreen) || + (entropy_idx == kPaletteAndSpatial); + // When using a palette, R/B==0, hence no need to test for cross-color. + if (low_effort || enc->use_palette_) { + enc->use_cross_color_ = 0; + } else { + enc->use_cross_color_ = red_and_blue_always_zero ? 0 : enc->use_predict_; + } + // Reset any parameter in the encoder that is set in the previous iteration. + enc->cache_bits_ = 0; + VP8LBackwardRefsClear(&enc->refs_[0]); + VP8LBackwardRefsClear(&enc->refs_[1]); + +#if (WEBP_NEAR_LOSSLESS == 1) + // Apply near-lossless preprocessing. + use_near_lossless = (config->near_lossless < 100) && !enc->use_palette_ && + !enc->use_predict_; + if (use_near_lossless) { + if (!AllocateTransformBuffer(enc, width, height)) goto Error; + if ((enc->argb_content_ != kEncoderNearLossless) && + !VP8ApplyNearLossless(picture, config->near_lossless, enc->argb_)) { + WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + enc->argb_content_ = kEncoderNearLossless; + } else { + enc->argb_content_ = kEncoderNone; + } +#else + enc->argb_content_ = kEncoderNone; +#endif + + // Encode palette + if (enc->use_palette_) { + if (!PaletteSort(crunch_configs[idx].palette_sorting_type_, enc->pic_, + enc->palette_sorted_, enc->palette_size_, + enc->palette_)) { + WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + percent_range = remaining_percent / 4; + if (!EncodePalette(bw, low_effort, enc, percent_range, &percent)) { + goto Error; + } + remaining_percent -= percent_range; + if (!MapImageFromPalette(enc, use_delta_palette)) goto Error; + // If using a color cache, do not have it bigger than the number of + // colors. + if (use_cache && enc->palette_size_ < (1 << MAX_COLOR_CACHE_BITS)) { + enc->cache_bits_ = BitsLog2Floor(enc->palette_size_) + 1; + } + } + if (!use_delta_palette) { + // In case image is not packed. + if (enc->argb_content_ != kEncoderNearLossless && + enc->argb_content_ != kEncoderPalette) { + if (!MakeInputImageCopy(enc)) goto Error; + } + + // ----------------------------------------------------------------------- + // Apply transforms and write transform data. + + if (enc->use_subtract_green_) { + ApplySubtractGreen(enc, enc->current_width_, height, bw); + } + + if (enc->use_predict_) { + percent_range = remaining_percent / 3; + if (!ApplyPredictFilter(enc, enc->current_width_, height, quality, + low_effort, enc->use_subtract_green_, bw, + percent_range, &percent)) { + goto Error; + } + remaining_percent -= percent_range; + } + + if (enc->use_cross_color_) { + percent_range = remaining_percent / 2; + if (!ApplyCrossColorFilter(enc, enc->current_width_, height, quality, + low_effort, bw, percent_range, &percent)) { + goto Error; + } + remaining_percent -= percent_range; + } + } + + VP8LPutBits(bw, !TRANSFORM_PRESENT, 1); // No more transforms. + + // ------------------------------------------------------------------------- + // Encode and write the transformed image. + if (!EncodeImageInternal( + bw, enc->argb_, &enc->hash_chain_, enc->refs_, enc->current_width_, + height, quality, low_effort, use_cache, &crunch_configs[idx], + &enc->cache_bits_, enc->histo_bits_, byte_position, &hdr_size, + &data_size, picture, remaining_percent, &percent)) { + goto Error; + } + + // If we are better than what we already have. + if (VP8LBitWriterNumBytes(bw) < best_size) { + best_size = VP8LBitWriterNumBytes(bw); + // Store the BitWriter. + VP8LBitWriterSwap(bw, &bw_best); +#if !defined(WEBP_DISABLE_STATS) + // Update the stats. + if (stats != NULL) { + stats->lossless_features = 0; + if (enc->use_predict_) stats->lossless_features |= 1; + if (enc->use_cross_color_) stats->lossless_features |= 2; + if (enc->use_subtract_green_) stats->lossless_features |= 4; + if (enc->use_palette_) stats->lossless_features |= 8; + stats->histogram_bits = enc->histo_bits_; + stats->transform_bits = enc->transform_bits_; + stats->cache_bits = enc->cache_bits_; + stats->palette_size = enc->palette_size_; + stats->lossless_size = (int)(best_size - byte_position); + stats->lossless_hdr_size = hdr_size; + stats->lossless_data_size = data_size; + } +#endif + } + // Reset the bit writer for the following iteration if any. + if (num_crunch_configs > 1) VP8LBitWriterReset(&bw_init, bw); + } + VP8LBitWriterSwap(&bw_best, bw); + + Error: + VP8LBitWriterWipeOut(&bw_best); + // The hook should return false in case of error. + return (params->picture_->error_code == VP8_ENC_OK); +} + +int VP8LEncodeStream(const WebPConfig* const config, + const WebPPicture* const picture, + VP8LBitWriter* const bw_main, int use_cache) { + VP8LEncoder* const enc_main = VP8LEncoderNew(config, picture); + VP8LEncoder* enc_side = NULL; + CrunchConfig crunch_configs[CRUNCH_CONFIGS_MAX]; + int num_crunch_configs_main, num_crunch_configs_side = 0; + int idx; + int red_and_blue_always_zero = 0; + WebPWorker worker_main, worker_side; + StreamEncodeContext params_main, params_side; + // The main thread uses picture->stats, the side thread uses stats_side. + WebPAuxStats stats_side; + VP8LBitWriter bw_side; + WebPPicture picture_side; + const WebPWorkerInterface* const worker_interface = WebPGetWorkerInterface(); + int ok_main; + + if (enc_main == NULL || !VP8LBitWriterInit(&bw_side, 0)) { + VP8LEncoderDelete(enc_main); + return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + + // Avoid "garbage value" error from Clang's static analysis tool. + WebPPictureInit(&picture_side); + + // Analyze image (entropy, num_palettes etc) + if (!EncoderAnalyze(enc_main, crunch_configs, &num_crunch_configs_main, + &red_and_blue_always_zero) || + !EncoderInit(enc_main)) { + WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + + // Split the configs between the main and side threads (if any). + if (config->thread_level > 0) { + num_crunch_configs_side = num_crunch_configs_main / 2; + for (idx = 0; idx < num_crunch_configs_side; ++idx) { + params_side.crunch_configs_[idx] = + crunch_configs[num_crunch_configs_main - num_crunch_configs_side + + idx]; + } + params_side.num_crunch_configs_ = num_crunch_configs_side; + } + num_crunch_configs_main -= num_crunch_configs_side; + for (idx = 0; idx < num_crunch_configs_main; ++idx) { + params_main.crunch_configs_[idx] = crunch_configs[idx]; + } + params_main.num_crunch_configs_ = num_crunch_configs_main; + + // Fill in the parameters for the thread workers. + { + const int params_size = (num_crunch_configs_side > 0) ? 2 : 1; + for (idx = 0; idx < params_size; ++idx) { + // Create the parameters for each worker. + WebPWorker* const worker = (idx == 0) ? &worker_main : &worker_side; + StreamEncodeContext* const param = + (idx == 0) ? ¶ms_main : ¶ms_side; + param->config_ = config; + param->use_cache_ = use_cache; + param->red_and_blue_always_zero_ = red_and_blue_always_zero; + if (idx == 0) { + param->picture_ = picture; + param->stats_ = picture->stats; + param->bw_ = bw_main; + param->enc_ = enc_main; + } else { + // Create a side picture (error_code is not thread-safe). + if (!WebPPictureView(picture, /*left=*/0, /*top=*/0, picture->width, + picture->height, &picture_side)) { + assert(0); + } + picture_side.progress_hook = NULL; // Progress hook is not thread-safe. + param->picture_ = &picture_side; // No need to free a view afterwards. + param->stats_ = (picture->stats == NULL) ? NULL : &stats_side; + // Create a side bit writer. + if (!VP8LBitWriterClone(bw_main, &bw_side)) { + WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + param->bw_ = &bw_side; + // Create a side encoder. + enc_side = VP8LEncoderNew(config, &picture_side); + if (enc_side == NULL || !EncoderInit(enc_side)) { + WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + // Copy the values that were computed for the main encoder. + enc_side->histo_bits_ = enc_main->histo_bits_; + enc_side->transform_bits_ = enc_main->transform_bits_; + enc_side->palette_size_ = enc_main->palette_size_; + memcpy(enc_side->palette_, enc_main->palette_, + sizeof(enc_main->palette_)); + memcpy(enc_side->palette_sorted_, enc_main->palette_sorted_, + sizeof(enc_main->palette_sorted_)); + param->enc_ = enc_side; + } + // Create the workers. + worker_interface->Init(worker); + worker->data1 = param; + worker->data2 = NULL; + worker->hook = EncodeStreamHook; + } + } + + // Start the second thread if needed. + if (num_crunch_configs_side != 0) { + if (!worker_interface->Reset(&worker_side)) { + WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } +#if !defined(WEBP_DISABLE_STATS) + // This line is here and not in the param initialization above to remove a + // Clang static analyzer warning. + if (picture->stats != NULL) { + memcpy(&stats_side, picture->stats, sizeof(stats_side)); + } +#endif + worker_interface->Launch(&worker_side); + } + // Execute the main thread. + worker_interface->Execute(&worker_main); + ok_main = worker_interface->Sync(&worker_main); + worker_interface->End(&worker_main); + if (num_crunch_configs_side != 0) { + // Wait for the second thread. + const int ok_side = worker_interface->Sync(&worker_side); + worker_interface->End(&worker_side); + if (!ok_main || !ok_side) { + if (picture->error_code == VP8_ENC_OK) { + assert(picture_side.error_code != VP8_ENC_OK); + WebPEncodingSetError(picture, picture_side.error_code); + } + goto Error; + } + if (VP8LBitWriterNumBytes(&bw_side) < VP8LBitWriterNumBytes(bw_main)) { + VP8LBitWriterSwap(bw_main, &bw_side); +#if !defined(WEBP_DISABLE_STATS) + if (picture->stats != NULL) { + memcpy(picture->stats, &stats_side, sizeof(*picture->stats)); + } +#endif + } + } + + Error: + VP8LBitWriterWipeOut(&bw_side); + VP8LEncoderDelete(enc_main); + VP8LEncoderDelete(enc_side); + return (picture->error_code == VP8_ENC_OK); +} + +#undef CRUNCH_CONFIGS_MAX +#undef CRUNCH_SUBCONFIGS_MAX + +int VP8LEncodeImage(const WebPConfig* const config, + const WebPPicture* const picture) { + int width, height; + int has_alpha; + size_t coded_size; + int percent = 0; + int initial_size; + VP8LBitWriter bw; + + if (picture == NULL) return 0; + + if (config == NULL || picture->argb == NULL) { + return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER); + } + + width = picture->width; + height = picture->height; + // Initialize BitWriter with size corresponding to 16 bpp to photo images and + // 8 bpp for graphical images. + initial_size = (config->image_hint == WEBP_HINT_GRAPH) ? + width * height : width * height * 2; + if (!VP8LBitWriterInit(&bw, initial_size)) { + WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + + if (!WebPReportProgress(picture, 1, &percent)) { + UserAbort: + WebPEncodingSetError(picture, VP8_ENC_ERROR_USER_ABORT); + goto Error; + } + // Reset stats (for pure lossless coding) + if (picture->stats != NULL) { + WebPAuxStats* const stats = picture->stats; + memset(stats, 0, sizeof(*stats)); + stats->PSNR[0] = 99.f; + stats->PSNR[1] = 99.f; + stats->PSNR[2] = 99.f; + stats->PSNR[3] = 99.f; + stats->PSNR[4] = 99.f; + } + + // Write image size. + if (!WriteImageSize(picture, &bw)) { + WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + + has_alpha = WebPPictureHasTransparency(picture); + // Write the non-trivial Alpha flag and lossless version. + if (!WriteRealAlphaAndVersion(&bw, has_alpha)) { + WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; + } + + if (!WebPReportProgress(picture, 2, &percent)) goto UserAbort; + + // Encode main image stream. + if (!VP8LEncodeStream(config, picture, &bw, 1 /*use_cache*/)) goto Error; + + if (!WebPReportProgress(picture, 99, &percent)) goto UserAbort; + + // Finish the RIFF chunk. + if (!WriteImage(picture, &bw, &coded_size)) goto Error; + + if (!WebPReportProgress(picture, 100, &percent)) goto UserAbort; + +#if !defined(WEBP_DISABLE_STATS) + // Save size. + if (picture->stats != NULL) { + picture->stats->coded_size += (int)coded_size; + picture->stats->lossless_size = (int)coded_size; + } +#endif + + if (picture->extra_info != NULL) { + const int mb_w = (width + 15) >> 4; + const int mb_h = (height + 15) >> 4; + memset(picture->extra_info, 0, mb_w * mb_h * sizeof(*picture->extra_info)); + } + + Error: + if (bw.error_) { + WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + } + VP8LBitWriterWipeOut(&bw); + return (picture->error_code == VP8_ENC_OK); +} + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/src/enc/vp8li_enc.h b/third-party/webp/libwebp/src/enc/vp8li_enc.h new file mode 100644 index 0000000000..3d35e1612d --- /dev/null +++ b/third-party/webp/libwebp/src/enc/vp8li_enc.h @@ -0,0 +1,126 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Lossless encoder: internal header. +// +// Author: Vikas Arora (vikaas.arora@gmail.com) + +#ifndef WEBP_ENC_VP8LI_ENC_H_ +#define WEBP_ENC_VP8LI_ENC_H_ + +#ifdef HAVE_CONFIG_H +#include "src/webp/config.h" +#endif +// Either WEBP_NEAR_LOSSLESS is defined as 0 in config.h when compiling to +// disable near-lossless, or it is enabled by default. +#ifndef WEBP_NEAR_LOSSLESS +#define WEBP_NEAR_LOSSLESS 1 +#endif + +#include "src/enc/backward_references_enc.h" +#include "src/enc/histogram_enc.h" +#include "src/utils/bit_writer_utils.h" +#include "src/webp/encode.h" +#include "src/webp/format_constants.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// maximum value of transform_bits_ in VP8LEncoder. +#define MAX_TRANSFORM_BITS 6 + +typedef enum { + kEncoderNone = 0, + kEncoderARGB, + kEncoderNearLossless, + kEncoderPalette +} VP8LEncoderARGBContent; + +typedef struct { + const WebPConfig* config_; // user configuration and parameters + const WebPPicture* pic_; // input picture. + + uint32_t* argb_; // Transformed argb image data. + VP8LEncoderARGBContent argb_content_; // Content type of the argb buffer. + uint32_t* argb_scratch_; // Scratch memory for argb rows + // (used for prediction). + uint32_t* transform_data_; // Scratch memory for transform data. + uint32_t* transform_mem_; // Currently allocated memory. + size_t transform_mem_size_; // Currently allocated memory size. + + int current_width_; // Corresponds to packed image width. + + // Encoding parameters derived from quality parameter. + int histo_bits_; + int transform_bits_; // <= MAX_TRANSFORM_BITS. + int cache_bits_; // If equal to 0, don't use color cache. + + // Encoding parameters derived from image characteristics. + int use_cross_color_; + int use_subtract_green_; + int use_predict_; + int use_palette_; + int palette_size_; + uint32_t palette_[MAX_PALETTE_SIZE]; + // Sorted version of palette_ for cache purposes. + uint32_t palette_sorted_[MAX_PALETTE_SIZE]; + + // Some 'scratch' (potentially large) objects. + struct VP8LBackwardRefs refs_[4]; // Backward Refs array for temporaries. + VP8LHashChain hash_chain_; // HashChain data for constructing + // backward references. +} VP8LEncoder; + +//------------------------------------------------------------------------------ +// internal functions. Not public. + +// Encodes the picture. +// Returns 0 if config or picture is NULL or picture doesn't have valid argb +// input. +int VP8LEncodeImage(const WebPConfig* const config, + const WebPPicture* const picture); + +// Encodes the main image stream using the supplied bit writer. +// If 'use_cache' is false, disables the use of color cache. +// Returns false in case of error (stored in picture->error_code). +int VP8LEncodeStream(const WebPConfig* const config, + const WebPPicture* const picture, VP8LBitWriter* const bw, + int use_cache); + +#if (WEBP_NEAR_LOSSLESS == 1) +// in near_lossless.c +// Near lossless preprocessing in RGB color-space. +int VP8ApplyNearLossless(const WebPPicture* const picture, int quality, + uint32_t* const argb_dst); +#endif + +//------------------------------------------------------------------------------ +// Image transforms in predictor.c. + +// pic and percent are for progress. +// Returns false in case of error (stored in pic->error_code). +int VP8LResidualImage(int width, int height, int bits, int low_effort, + uint32_t* const argb, uint32_t* const argb_scratch, + uint32_t* const image, int near_lossless, int exact, + int used_subtract_green, const WebPPicture* const pic, + int percent_range, int* const percent); + +int VP8LColorSpaceTransform(int width, int height, int bits, int quality, + uint32_t* const argb, uint32_t* image, + const WebPPicture* const pic, int percent_range, + int* const percent); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_ENC_VP8LI_ENC_H_ diff --git a/third-party/webp/libwebp/src/enc/webp_enc.c b/third-party/webp/libwebp/src/enc/webp_enc.c new file mode 100644 index 0000000000..583fe6a8bb --- /dev/null +++ b/third-party/webp/libwebp/src/enc/webp_enc.c @@ -0,0 +1,410 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// WebP encoder: main entry point +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include +#include +#include + +#include "src/enc/cost_enc.h" +#include "src/enc/vp8i_enc.h" +#include "src/enc/vp8li_enc.h" +#include "src/utils/utils.h" + +// #define PRINT_MEMORY_INFO + +#ifdef PRINT_MEMORY_INFO +#include +#endif + +//------------------------------------------------------------------------------ + +int WebPGetEncoderVersion(void) { + return (ENC_MAJ_VERSION << 16) | (ENC_MIN_VERSION << 8) | ENC_REV_VERSION; +} + +//------------------------------------------------------------------------------ +// VP8Encoder +//------------------------------------------------------------------------------ + +static void ResetSegmentHeader(VP8Encoder* const enc) { + VP8EncSegmentHeader* const hdr = &enc->segment_hdr_; + hdr->num_segments_ = enc->config_->segments; + hdr->update_map_ = (hdr->num_segments_ > 1); + hdr->size_ = 0; +} + +static void ResetFilterHeader(VP8Encoder* const enc) { + VP8EncFilterHeader* const hdr = &enc->filter_hdr_; + hdr->simple_ = 1; + hdr->level_ = 0; + hdr->sharpness_ = 0; + hdr->i4x4_lf_delta_ = 0; +} + +static void ResetBoundaryPredictions(VP8Encoder* const enc) { + // init boundary values once for all + // Note: actually, initializing the preds_[] is only needed for intra4. + int i; + uint8_t* const top = enc->preds_ - enc->preds_w_; + uint8_t* const left = enc->preds_ - 1; + for (i = -1; i < 4 * enc->mb_w_; ++i) { + top[i] = B_DC_PRED; + } + for (i = 0; i < 4 * enc->mb_h_; ++i) { + left[i * enc->preds_w_] = B_DC_PRED; + } + enc->nz_[-1] = 0; // constant +} + +// Mapping from config->method_ to coding tools used. +//-------------------+---+---+---+---+---+---+---+ +// Method | 0 | 1 | 2 | 3 |(4)| 5 | 6 | +//-------------------+---+---+---+---+---+---+---+ +// fast probe | x | | | x | | | | +//-------------------+---+---+---+---+---+---+---+ +// dynamic proba | ~ | x | x | x | x | x | x | +//-------------------+---+---+---+---+---+---+---+ +// fast mode analysis|[x]|[x]| | | x | x | x | +//-------------------+---+---+---+---+---+---+---+ +// basic rd-opt | | | | x | x | x | x | +//-------------------+---+---+---+---+---+---+---+ +// disto-refine i4/16| x | x | x | | | | | +//-------------------+---+---+---+---+---+---+---+ +// disto-refine uv | | x | x | | | | | +//-------------------+---+---+---+---+---+---+---+ +// rd-opt i4/16 | | | ~ | x | x | x | x | +//-------------------+---+---+---+---+---+---+---+ +// token buffer (opt)| | | | x | x | x | x | +//-------------------+---+---+---+---+---+---+---+ +// Trellis | | | | | | x |Ful| +//-------------------+---+---+---+---+---+---+---+ +// full-SNS | | | | | x | x | x | +//-------------------+---+---+---+---+---+---+---+ + +static void MapConfigToTools(VP8Encoder* const enc) { + const WebPConfig* const config = enc->config_; + const int method = config->method; + const int limit = 100 - config->partition_limit; + enc->method_ = method; + enc->rd_opt_level_ = (method >= 6) ? RD_OPT_TRELLIS_ALL + : (method >= 5) ? RD_OPT_TRELLIS + : (method >= 3) ? RD_OPT_BASIC + : RD_OPT_NONE; + enc->max_i4_header_bits_ = + 256 * 16 * 16 * // upper bound: up to 16bit per 4x4 block + (limit * limit) / (100 * 100); // ... modulated with a quadratic curve. + + // partition0 = 512k max. + enc->mb_header_limit_ = + (score_t)256 * 510 * 8 * 1024 / (enc->mb_w_ * enc->mb_h_); + + enc->thread_level_ = config->thread_level; + + enc->do_search_ = (config->target_size > 0 || config->target_PSNR > 0); + if (!config->low_memory) { +#if !defined(DISABLE_TOKEN_BUFFER) + enc->use_tokens_ = (enc->rd_opt_level_ >= RD_OPT_BASIC); // need rd stats +#endif + if (enc->use_tokens_) { + enc->num_parts_ = 1; // doesn't work with multi-partition + } + } +} + +// Memory scaling with dimensions: +// memory (bytes) ~= 2.25 * w + 0.0625 * w * h +// +// Typical memory footprint (614x440 picture) +// encoder: 22111 +// info: 4368 +// preds: 17741 +// top samples: 1263 +// non-zero: 175 +// lf-stats: 0 +// total: 45658 +// Transient object sizes: +// VP8EncIterator: 3360 +// VP8ModeScore: 872 +// VP8SegmentInfo: 732 +// VP8EncProba: 18352 +// LFStats: 2048 +// Picture size (yuv): 419328 + +static VP8Encoder* InitVP8Encoder(const WebPConfig* const config, + WebPPicture* const picture) { + VP8Encoder* enc; + const int use_filter = + (config->filter_strength > 0) || (config->autofilter > 0); + const int mb_w = (picture->width + 15) >> 4; + const int mb_h = (picture->height + 15) >> 4; + const int preds_w = 4 * mb_w + 1; + const int preds_h = 4 * mb_h + 1; + const size_t preds_size = preds_w * preds_h * sizeof(*enc->preds_); + const int top_stride = mb_w * 16; + const size_t nz_size = (mb_w + 1) * sizeof(*enc->nz_) + WEBP_ALIGN_CST; + const size_t info_size = mb_w * mb_h * sizeof(*enc->mb_info_); + const size_t samples_size = + 2 * top_stride * sizeof(*enc->y_top_) // top-luma/u/v + + WEBP_ALIGN_CST; // align all + const size_t lf_stats_size = + config->autofilter ? sizeof(*enc->lf_stats_) + WEBP_ALIGN_CST : 0; + const size_t top_derr_size = + (config->quality <= ERROR_DIFFUSION_QUALITY || config->pass > 1) ? + mb_w * sizeof(*enc->top_derr_) : 0; + uint8_t* mem; + const uint64_t size = (uint64_t)sizeof(*enc) // main struct + + WEBP_ALIGN_CST // cache alignment + + info_size // modes info + + preds_size // prediction modes + + samples_size // top/left samples + + top_derr_size // top diffusion error + + nz_size // coeff context bits + + lf_stats_size; // autofilter stats + +#ifdef PRINT_MEMORY_INFO + printf("===================================\n"); + printf("Memory used:\n" + " encoder: %ld\n" + " info: %ld\n" + " preds: %ld\n" + " top samples: %ld\n" + " top diffusion: %ld\n" + " non-zero: %ld\n" + " lf-stats: %ld\n" + " total: %ld\n", + sizeof(*enc) + WEBP_ALIGN_CST, info_size, + preds_size, samples_size, top_derr_size, nz_size, lf_stats_size, size); + printf("Transient object sizes:\n" + " VP8EncIterator: %ld\n" + " VP8ModeScore: %ld\n" + " VP8SegmentInfo: %ld\n" + " VP8EncProba: %ld\n" + " LFStats: %ld\n", + sizeof(VP8EncIterator), sizeof(VP8ModeScore), + sizeof(VP8SegmentInfo), sizeof(VP8EncProba), + sizeof(LFStats)); + printf("Picture size (yuv): %ld\n", + mb_w * mb_h * 384 * sizeof(uint8_t)); + printf("===================================\n"); +#endif + mem = (uint8_t*)WebPSafeMalloc(size, sizeof(*mem)); + if (mem == NULL) { + WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); + return NULL; + } + enc = (VP8Encoder*)mem; + mem = (uint8_t*)WEBP_ALIGN(mem + sizeof(*enc)); + memset(enc, 0, sizeof(*enc)); + enc->num_parts_ = 1 << config->partitions; + enc->mb_w_ = mb_w; + enc->mb_h_ = mb_h; + enc->preds_w_ = preds_w; + enc->mb_info_ = (VP8MBInfo*)mem; + mem += info_size; + enc->preds_ = mem + 1 + enc->preds_w_; + mem += preds_size; + enc->nz_ = 1 + (uint32_t*)WEBP_ALIGN(mem); + mem += nz_size; + enc->lf_stats_ = lf_stats_size ? (LFStats*)WEBP_ALIGN(mem) : NULL; + mem += lf_stats_size; + + // top samples (all 16-aligned) + mem = (uint8_t*)WEBP_ALIGN(mem); + enc->y_top_ = mem; + enc->uv_top_ = enc->y_top_ + top_stride; + mem += 2 * top_stride; + enc->top_derr_ = top_derr_size ? (DError*)mem : NULL; + mem += top_derr_size; + assert(mem <= (uint8_t*)enc + size); + + enc->config_ = config; + enc->profile_ = use_filter ? ((config->filter_type == 1) ? 0 : 1) : 2; + enc->pic_ = picture; + enc->percent_ = 0; + + MapConfigToTools(enc); + VP8EncDspInit(); + VP8DefaultProbas(enc); + ResetSegmentHeader(enc); + ResetFilterHeader(enc); + ResetBoundaryPredictions(enc); + VP8EncDspCostInit(); + VP8EncInitAlpha(enc); + + // lower quality means smaller output -> we modulate a little the page + // size based on quality. This is just a crude 1rst-order prediction. + { + const float scale = 1.f + config->quality * 5.f / 100.f; // in [1,6] + VP8TBufferInit(&enc->tokens_, (int)(mb_w * mb_h * 4 * scale)); + } + return enc; +} + +static int DeleteVP8Encoder(VP8Encoder* enc) { + int ok = 1; + if (enc != NULL) { + ok = VP8EncDeleteAlpha(enc); + VP8TBufferClear(&enc->tokens_); + WebPSafeFree(enc); + } + return ok; +} + +//------------------------------------------------------------------------------ + +#if !defined(WEBP_DISABLE_STATS) +static double GetPSNR(uint64_t err, uint64_t size) { + return (err > 0 && size > 0) ? 10. * log10(255. * 255. * size / err) : 99.; +} + +static void FinalizePSNR(const VP8Encoder* const enc) { + WebPAuxStats* stats = enc->pic_->stats; + const uint64_t size = enc->sse_count_; + const uint64_t* const sse = enc->sse_; + stats->PSNR[0] = (float)GetPSNR(sse[0], size); + stats->PSNR[1] = (float)GetPSNR(sse[1], size / 4); + stats->PSNR[2] = (float)GetPSNR(sse[2], size / 4); + stats->PSNR[3] = (float)GetPSNR(sse[0] + sse[1] + sse[2], size * 3 / 2); + stats->PSNR[4] = (float)GetPSNR(sse[3], size); +} +#endif // !defined(WEBP_DISABLE_STATS) + +static void StoreStats(VP8Encoder* const enc) { +#if !defined(WEBP_DISABLE_STATS) + WebPAuxStats* const stats = enc->pic_->stats; + if (stats != NULL) { + int i, s; + for (i = 0; i < NUM_MB_SEGMENTS; ++i) { + stats->segment_level[i] = enc->dqm_[i].fstrength_; + stats->segment_quant[i] = enc->dqm_[i].quant_; + for (s = 0; s <= 2; ++s) { + stats->residual_bytes[s][i] = enc->residual_bytes_[s][i]; + } + } + FinalizePSNR(enc); + stats->coded_size = enc->coded_size_; + for (i = 0; i < 3; ++i) { + stats->block_count[i] = enc->block_count_[i]; + } + } +#else // defined(WEBP_DISABLE_STATS) + WebPReportProgress(enc->pic_, 100, &enc->percent_); // done! +#endif // !defined(WEBP_DISABLE_STATS) +} + +int WebPEncodingSetError(const WebPPicture* const pic, + WebPEncodingError error) { + assert((int)error < VP8_ENC_ERROR_LAST); + assert((int)error >= VP8_ENC_OK); + // The oldest error reported takes precedence over the new one. + if (pic->error_code == VP8_ENC_OK) { + ((WebPPicture*)pic)->error_code = error; + } + return 0; +} + +int WebPReportProgress(const WebPPicture* const pic, + int percent, int* const percent_store) { + if (percent_store != NULL && percent != *percent_store) { + *percent_store = percent; + if (pic->progress_hook && !pic->progress_hook(percent, pic)) { + // user abort requested + return WebPEncodingSetError(pic, VP8_ENC_ERROR_USER_ABORT); + } + } + return 1; // ok +} +//------------------------------------------------------------------------------ + +int WebPEncode(const WebPConfig* config, WebPPicture* pic) { + int ok = 0; + if (pic == NULL) return 0; + + pic->error_code = VP8_ENC_OK; // all ok so far + if (config == NULL) { // bad params + return WebPEncodingSetError(pic, VP8_ENC_ERROR_NULL_PARAMETER); + } + if (!WebPValidateConfig(config)) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_INVALID_CONFIGURATION); + } + if (!WebPValidatePicture(pic)) return 0; + if (pic->width > WEBP_MAX_DIMENSION || pic->height > WEBP_MAX_DIMENSION) { + return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION); + } + + if (pic->stats != NULL) memset(pic->stats, 0, sizeof(*pic->stats)); + + if (!config->lossless) { + VP8Encoder* enc = NULL; + + if (pic->use_argb || pic->y == NULL || pic->u == NULL || pic->v == NULL) { + // Make sure we have YUVA samples. + if (config->use_sharp_yuv || (config->preprocessing & 4)) { + if (!WebPPictureSharpARGBToYUVA(pic)) { + return 0; + } + } else { + float dithering = 0.f; + if (config->preprocessing & 2) { + const float x = config->quality / 100.f; + const float x2 = x * x; + // slowly decreasing from max dithering at low quality (q->0) + // to 0.5 dithering amplitude at high quality (q->100) + dithering = 1.0f + (0.5f - 1.0f) * x2 * x2; + } + if (!WebPPictureARGBToYUVADithered(pic, WEBP_YUV420, dithering)) { + return 0; + } + } + } + + if (!config->exact) { + WebPCleanupTransparentArea(pic); + } + + enc = InitVP8Encoder(config, pic); + if (enc == NULL) return 0; // pic->error is already set. + // Note: each of the tasks below account for 20% in the progress report. + ok = VP8EncAnalyze(enc); + + // Analysis is done, proceed to actual coding. + ok = ok && VP8EncStartAlpha(enc); // possibly done in parallel + if (!enc->use_tokens_) { + ok = ok && VP8EncLoop(enc); + } else { + ok = ok && VP8EncTokenLoop(enc); + } + ok = ok && VP8EncFinishAlpha(enc); + + ok = ok && VP8EncWrite(enc); + StoreStats(enc); + if (!ok) { + VP8EncFreeBitWriters(enc); + } + ok &= DeleteVP8Encoder(enc); // must always be called, even if !ok + } else { + // Make sure we have ARGB samples. + if (pic->argb == NULL && !WebPPictureYUVAToARGB(pic)) { + return 0; + } + + if (!config->exact) { + WebPReplaceTransparentPixels(pic, 0x000000); + } + + ok = VP8LEncodeImage(config, pic); // Sets pic->error in case of problem. + } + + return ok; +} diff --git a/third-party/webp/libwebp/src/libwebp.pc.in b/third-party/webp/libwebp/src/libwebp.pc.in new file mode 100644 index 0000000000..783090ef66 --- /dev/null +++ b/third-party/webp/libwebp/src/libwebp.pc.in @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libwebp +Description: Library for the WebP graphics format +Version: @PACKAGE_VERSION@ +Requires.private: libsharpyuv +Cflags: -I${includedir} +Libs: -L${libdir} -l@webp_libname_prefix@webp +Libs.private: -lm @PTHREAD_CFLAGS@ @PTHREAD_LIBS@ diff --git a/third-party/webp/libwebp/src/libwebp.rc b/third-party/webp/libwebp/src/libwebp.rc new file mode 100644 index 0000000000..4e8e40291c --- /dev/null +++ b/third-party/webp/libwebp/src/libwebp.rc @@ -0,0 +1,41 @@ +#define APSTUDIO_READONLY_SYMBOLS +#include "winres.h" +#undef APSTUDIO_READONLY_SYMBOLS + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,3,2 + PRODUCTVERSION 1,0,3,2 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "Google, Inc." + VALUE "FileDescription", "libwebp DLL" + VALUE "FileVersion", "1.3.2" + VALUE "InternalName", "libwebp.dll" + VALUE "LegalCopyright", "Copyright (C) 2023" + VALUE "OriginalFilename", "libwebp.dll" + VALUE "ProductName", "WebP Image Codec" + VALUE "ProductVersion", "1.3.2" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // English (United States) resources diff --git a/third-party/webp/libwebp/src/libwebpdecoder.pc.in b/third-party/webp/libwebp/src/libwebpdecoder.pc.in new file mode 100644 index 0000000000..134de0e7cc --- /dev/null +++ b/third-party/webp/libwebp/src/libwebpdecoder.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libwebpdecoder +Description: Library for the WebP graphics format (decode only) +Version: @PACKAGE_VERSION@ +Cflags: -I${includedir} +Libs: -L${libdir} -l@webp_libname_prefix@webpdecoder +Libs.private: -lm @PTHREAD_CFLAGS@ @PTHREAD_LIBS@ diff --git a/third-party/webp/libwebp/src/libwebpdecoder.rc b/third-party/webp/libwebp/src/libwebpdecoder.rc new file mode 100644 index 0000000000..c3f3e4a1b9 --- /dev/null +++ b/third-party/webp/libwebp/src/libwebpdecoder.rc @@ -0,0 +1,41 @@ +#define APSTUDIO_READONLY_SYMBOLS +#include "winres.h" +#undef APSTUDIO_READONLY_SYMBOLS + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,3,2 + PRODUCTVERSION 1,0,3,2 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "Google, Inc." + VALUE "FileDescription", "libwebpdecoder DLL" + VALUE "FileVersion", "1.3.2" + VALUE "InternalName", "libwebpdecoder.dll" + VALUE "LegalCopyright", "Copyright (C) 2023" + VALUE "OriginalFilename", "libwebpdecoder.dll" + VALUE "ProductName", "WebP Image Decoder" + VALUE "ProductVersion", "1.3.2" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // English (United States) resources diff --git a/third-party/webp/libwebp/src/mux/Makefile.am b/third-party/webp/libwebp/src/mux/Makefile.am new file mode 100644 index 0000000000..9abd85951a --- /dev/null +++ b/third-party/webp/libwebp/src/mux/Makefile.am @@ -0,0 +1,22 @@ +AM_CPPFLAGS += -I$(top_builddir) -I$(top_srcdir) +lib_LTLIBRARIES = libwebpmux.la + +libwebpmux_la_SOURCES = +libwebpmux_la_SOURCES += anim_encode.c +libwebpmux_la_SOURCES += animi.h +libwebpmux_la_SOURCES += muxedit.c +libwebpmux_la_SOURCES += muxi.h +libwebpmux_la_SOURCES += muxinternal.c +libwebpmux_la_SOURCES += muxread.c + +libwebpmuxinclude_HEADERS = +libwebpmuxinclude_HEADERS += ../webp/mux.h +libwebpmuxinclude_HEADERS += ../webp/mux_types.h +libwebpmuxinclude_HEADERS += ../webp/types.h +noinst_HEADERS = +noinst_HEADERS += ../webp/format_constants.h + +libwebpmux_la_LIBADD = ../libwebp.la +libwebpmux_la_LDFLAGS = -no-undefined -version-info 3:13:0 -lm +libwebpmuxincludedir = $(includedir)/webp +pkgconfig_DATA = libwebpmux.pc diff --git a/third-party/webp/libwebp/src/mux/anim_encode.c b/third-party/webp/libwebp/src/mux/anim_encode.c new file mode 100644 index 0000000000..d1c61a2f1e --- /dev/null +++ b/third-party/webp/libwebp/src/mux/anim_encode.c @@ -0,0 +1,1586 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// AnimEncoder implementation. +// + +#include +#include +#include // for pow() +#include +#include // for abs() + +#include "src/mux/animi.h" +#include "src/utils/utils.h" +#include "src/webp/decode.h" +#include "src/webp/encode.h" +#include "src/webp/format_constants.h" +#include "src/webp/mux.h" + +#if defined(_MSC_VER) && _MSC_VER < 1900 +#define snprintf _snprintf +#endif + +#define ERROR_STR_MAX_LENGTH 100 + +//------------------------------------------------------------------------------ +// Internal structs. + +// Stores frame rectangle dimensions. +typedef struct { + int x_offset_, y_offset_, width_, height_; +} FrameRectangle; + +// Used to store two candidates of encoded data for an animation frame. One of +// the two will be chosen later. +typedef struct { + WebPMuxFrameInfo sub_frame_; // Encoded frame rectangle. + WebPMuxFrameInfo key_frame_; // Encoded frame if it is a key-frame. + int is_key_frame_; // True if 'key_frame' has been chosen. +} EncodedFrame; + +struct WebPAnimEncoder { + const int canvas_width_; // Canvas width. + const int canvas_height_; // Canvas height. + const WebPAnimEncoderOptions options_; // Global encoding options. + + FrameRectangle prev_rect_; // Previous WebP frame rectangle. + WebPConfig last_config_; // Cached in case a re-encode is needed. + WebPConfig last_config_reversed_; // If 'last_config_' uses lossless, then + // this config uses lossy and vice versa; + // only valid if 'options_.allow_mixed' + // is true. + + WebPPicture* curr_canvas_; // Only pointer; we don't own memory. + + // Canvas buffers. + WebPPicture curr_canvas_copy_; // Possibly modified current canvas. + int curr_canvas_copy_modified_; // True if pixels in 'curr_canvas_copy_' + // differ from those in 'curr_canvas_'. + + WebPPicture prev_canvas_; // Previous canvas. + WebPPicture prev_canvas_disposed_; // Previous canvas disposed to background. + + // Encoded data. + EncodedFrame* encoded_frames_; // Array of encoded frames. + size_t size_; // Number of allocated frames. + size_t start_; // Frame start index. + size_t count_; // Number of valid frames. + size_t flush_count_; // If >0, 'flush_count' frames starting from + // 'start' are ready to be added to mux. + + // key-frame related. + int64_t best_delta_; // min(canvas size - frame size) over the frames. + // Can be negative in certain cases due to + // transparent pixels in a frame. + int keyframe_; // Index of selected key-frame relative to 'start_'. + int count_since_key_frame_; // Frames seen since the last key-frame. + + int first_timestamp_; // Timestamp of the first frame. + int prev_timestamp_; // Timestamp of the last added frame. + int prev_candidate_undecided_; // True if it's not yet decided if previous + // frame would be a sub-frame or a key-frame. + + // Misc. + int is_first_frame_; // True if first frame is yet to be added/being added. + int got_null_frame_; // True if WebPAnimEncoderAdd() has already been called + // with a NULL frame. + + size_t in_frame_count_; // Number of input frames processed so far. + size_t out_frame_count_; // Number of frames added to mux so far. This may be + // different from 'in_frame_count_' due to merging. + + WebPMux* mux_; // Muxer to assemble the WebP bitstream. + char error_str_[ERROR_STR_MAX_LENGTH]; // Error string. Empty if no error. +}; + +// ----------------------------------------------------------------------------- +// Life of WebPAnimEncoder object. + +#define DELTA_INFINITY (1ULL << 32) +#define KEYFRAME_NONE (-1) + +// Reset the counters in the WebPAnimEncoder. +static void ResetCounters(WebPAnimEncoder* const enc) { + enc->start_ = 0; + enc->count_ = 0; + enc->flush_count_ = 0; + enc->best_delta_ = DELTA_INFINITY; + enc->keyframe_ = KEYFRAME_NONE; +} + +static void DisableKeyframes(WebPAnimEncoderOptions* const enc_options) { + enc_options->kmax = INT_MAX; + enc_options->kmin = enc_options->kmax - 1; +} + +#define MAX_CACHED_FRAMES 30 + +static void SanitizeEncoderOptions(WebPAnimEncoderOptions* const enc_options) { + int print_warning = enc_options->verbose; + + if (enc_options->minimize_size) { + DisableKeyframes(enc_options); + } + + if (enc_options->kmax == 1) { // All frames will be key-frames. + enc_options->kmin = 0; + enc_options->kmax = 0; + return; + } else if (enc_options->kmax <= 0) { + DisableKeyframes(enc_options); + print_warning = 0; + } + + if (enc_options->kmin >= enc_options->kmax) { + enc_options->kmin = enc_options->kmax - 1; + if (print_warning) { + fprintf(stderr, "WARNING: Setting kmin = %d, so that kmin < kmax.\n", + enc_options->kmin); + } + } else { + const int kmin_limit = enc_options->kmax / 2 + 1; + if (enc_options->kmin < kmin_limit && kmin_limit < enc_options->kmax) { + // This ensures that enc.keyframe + kmin >= kmax is always true. So, we + // can flush all the frames in the 'count_since_key_frame == kmax' case. + enc_options->kmin = kmin_limit; + if (print_warning) { + fprintf(stderr, + "WARNING: Setting kmin = %d, so that kmin >= kmax / 2 + 1.\n", + enc_options->kmin); + } + } + } + // Limit the max number of frames that are allocated. + if (enc_options->kmax - enc_options->kmin > MAX_CACHED_FRAMES) { + enc_options->kmin = enc_options->kmax - MAX_CACHED_FRAMES; + if (print_warning) { + fprintf(stderr, + "WARNING: Setting kmin = %d, so that kmax - kmin <= %d.\n", + enc_options->kmin, MAX_CACHED_FRAMES); + } + } + assert(enc_options->kmin < enc_options->kmax); +} + +#undef MAX_CACHED_FRAMES + +static void DefaultEncoderOptions(WebPAnimEncoderOptions* const enc_options) { + enc_options->anim_params.loop_count = 0; + enc_options->anim_params.bgcolor = 0xffffffff; // White. + enc_options->minimize_size = 0; + DisableKeyframes(enc_options); + enc_options->allow_mixed = 0; + enc_options->verbose = 0; +} + +int WebPAnimEncoderOptionsInitInternal(WebPAnimEncoderOptions* enc_options, + int abi_version) { + if (enc_options == NULL || + WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_MUX_ABI_VERSION)) { + return 0; + } + DefaultEncoderOptions(enc_options); + return 1; +} + +// This starting value is more fit to WebPCleanupTransparentAreaLossless(). +#define TRANSPARENT_COLOR 0x00000000 + +static void ClearRectangle(WebPPicture* const picture, + int left, int top, int width, int height) { + int j; + for (j = top; j < top + height; ++j) { + uint32_t* const dst = picture->argb + j * picture->argb_stride; + int i; + for (i = left; i < left + width; ++i) { + dst[i] = TRANSPARENT_COLOR; + } + } +} + +static void WebPUtilClearPic(WebPPicture* const picture, + const FrameRectangle* const rect) { + if (rect != NULL) { + ClearRectangle(picture, rect->x_offset_, rect->y_offset_, + rect->width_, rect->height_); + } else { + ClearRectangle(picture, 0, 0, picture->width, picture->height); + } +} + +static void MarkNoError(WebPAnimEncoder* const enc) { + enc->error_str_[0] = '\0'; // Empty string. +} + +static void MarkError(WebPAnimEncoder* const enc, const char* str) { + if (snprintf(enc->error_str_, ERROR_STR_MAX_LENGTH, "%s.", str) < 0) { + assert(0); // FIX ME! + } +} + +static void MarkError2(WebPAnimEncoder* const enc, + const char* str, int error_code) { + if (snprintf(enc->error_str_, ERROR_STR_MAX_LENGTH, "%s: %d.", str, + error_code) < 0) { + assert(0); // FIX ME! + } +} + +WebPAnimEncoder* WebPAnimEncoderNewInternal( + int width, int height, const WebPAnimEncoderOptions* enc_options, + int abi_version) { + WebPAnimEncoder* enc; + + if (WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_MUX_ABI_VERSION)) { + return NULL; + } + if (width <= 0 || height <= 0 || + (width * (uint64_t)height) >= MAX_IMAGE_AREA) { + return NULL; + } + + enc = (WebPAnimEncoder*)WebPSafeCalloc(1, sizeof(*enc)); + if (enc == NULL) return NULL; + MarkNoError(enc); + + // Dimensions and options. + *(int*)&enc->canvas_width_ = width; + *(int*)&enc->canvas_height_ = height; + if (enc_options != NULL) { + *(WebPAnimEncoderOptions*)&enc->options_ = *enc_options; + SanitizeEncoderOptions((WebPAnimEncoderOptions*)&enc->options_); + } else { + DefaultEncoderOptions((WebPAnimEncoderOptions*)&enc->options_); + } + + // Canvas buffers. + if (!WebPPictureInit(&enc->curr_canvas_copy_) || + !WebPPictureInit(&enc->prev_canvas_) || + !WebPPictureInit(&enc->prev_canvas_disposed_)) { + goto Err; + } + enc->curr_canvas_copy_.width = width; + enc->curr_canvas_copy_.height = height; + enc->curr_canvas_copy_.use_argb = 1; + if (!WebPPictureAlloc(&enc->curr_canvas_copy_) || + !WebPPictureCopy(&enc->curr_canvas_copy_, &enc->prev_canvas_) || + !WebPPictureCopy(&enc->curr_canvas_copy_, &enc->prev_canvas_disposed_)) { + goto Err; + } + WebPUtilClearPic(&enc->prev_canvas_, NULL); + enc->curr_canvas_copy_modified_ = 1; + + // Encoded frames. + ResetCounters(enc); + // Note: one extra storage is for the previous frame. + enc->size_ = enc->options_.kmax - enc->options_.kmin + 1; + // We need space for at least 2 frames. But when kmin, kmax are both zero, + // enc->size_ will be 1. So we handle that special case below. + if (enc->size_ < 2) enc->size_ = 2; + enc->encoded_frames_ = + (EncodedFrame*)WebPSafeCalloc(enc->size_, sizeof(*enc->encoded_frames_)); + if (enc->encoded_frames_ == NULL) goto Err; + + enc->mux_ = WebPMuxNew(); + if (enc->mux_ == NULL) goto Err; + + enc->count_since_key_frame_ = 0; + enc->first_timestamp_ = 0; + enc->prev_timestamp_ = 0; + enc->prev_candidate_undecided_ = 0; + enc->is_first_frame_ = 1; + enc->got_null_frame_ = 0; + + return enc; // All OK. + + Err: + WebPAnimEncoderDelete(enc); + return NULL; +} + +// Release the data contained by 'encoded_frame'. +static void FrameRelease(EncodedFrame* const encoded_frame) { + if (encoded_frame != NULL) { + WebPDataClear(&encoded_frame->sub_frame_.bitstream); + WebPDataClear(&encoded_frame->key_frame_.bitstream); + memset(encoded_frame, 0, sizeof(*encoded_frame)); + } +} + +void WebPAnimEncoderDelete(WebPAnimEncoder* enc) { + if (enc != NULL) { + WebPPictureFree(&enc->curr_canvas_copy_); + WebPPictureFree(&enc->prev_canvas_); + WebPPictureFree(&enc->prev_canvas_disposed_); + if (enc->encoded_frames_ != NULL) { + size_t i; + for (i = 0; i < enc->size_; ++i) { + FrameRelease(&enc->encoded_frames_[i]); + } + WebPSafeFree(enc->encoded_frames_); + } + WebPMuxDelete(enc->mux_); + WebPSafeFree(enc); + } +} + +// ----------------------------------------------------------------------------- +// Frame addition. + +// Returns cached frame at the given 'position'. +static EncodedFrame* GetFrame(const WebPAnimEncoder* const enc, + size_t position) { + assert(enc->start_ + position < enc->size_); + return &enc->encoded_frames_[enc->start_ + position]; +} + +typedef int (*ComparePixelsFunc)(const uint32_t*, int, const uint32_t*, int, + int, int); + +// Returns true if 'length' number of pixels in 'src' and 'dst' are equal, +// assuming the given step sizes between pixels. +// 'max_allowed_diff' is unused and only there to allow function pointer use. +static WEBP_INLINE int ComparePixelsLossless(const uint32_t* src, int src_step, + const uint32_t* dst, int dst_step, + int length, int max_allowed_diff) { + (void)max_allowed_diff; + assert(length > 0); + while (length-- > 0) { + if (*src != *dst) { + return 0; + } + src += src_step; + dst += dst_step; + } + return 1; +} + +// Helper to check if each channel in 'src' and 'dst' is at most off by +// 'max_allowed_diff'. +static WEBP_INLINE int PixelsAreSimilar(uint32_t src, uint32_t dst, + int max_allowed_diff) { + const int src_a = (src >> 24) & 0xff; + const int src_r = (src >> 16) & 0xff; + const int src_g = (src >> 8) & 0xff; + const int src_b = (src >> 0) & 0xff; + const int dst_a = (dst >> 24) & 0xff; + const int dst_r = (dst >> 16) & 0xff; + const int dst_g = (dst >> 8) & 0xff; + const int dst_b = (dst >> 0) & 0xff; + + return (src_a == dst_a) && + (abs(src_r - dst_r) * dst_a <= (max_allowed_diff * 255)) && + (abs(src_g - dst_g) * dst_a <= (max_allowed_diff * 255)) && + (abs(src_b - dst_b) * dst_a <= (max_allowed_diff * 255)); +} + +// Returns true if 'length' number of pixels in 'src' and 'dst' are within an +// error bound, assuming the given step sizes between pixels. +static WEBP_INLINE int ComparePixelsLossy(const uint32_t* src, int src_step, + const uint32_t* dst, int dst_step, + int length, int max_allowed_diff) { + assert(length > 0); + while (length-- > 0) { + if (!PixelsAreSimilar(*src, *dst, max_allowed_diff)) { + return 0; + } + src += src_step; + dst += dst_step; + } + return 1; +} + +static int IsEmptyRect(const FrameRectangle* const rect) { + return (rect->width_ == 0) || (rect->height_ == 0); +} + +static int QualityToMaxDiff(float quality) { + const double val = pow(quality / 100., 0.5); + const double max_diff = 31 * (1 - val) + 1 * val; + return (int)(max_diff + 0.5); +} + +// Assumes that an initial valid guess of change rectangle 'rect' is passed. +static void MinimizeChangeRectangle(const WebPPicture* const src, + const WebPPicture* const dst, + FrameRectangle* const rect, + int is_lossless, float quality) { + int i, j; + const ComparePixelsFunc compare_pixels = + is_lossless ? ComparePixelsLossless : ComparePixelsLossy; + const int max_allowed_diff_lossy = QualityToMaxDiff(quality); + const int max_allowed_diff = is_lossless ? 0 : max_allowed_diff_lossy; + + // Assumption/correctness checks. + assert(src->width == dst->width && src->height == dst->height); + assert(rect->x_offset_ + rect->width_ <= dst->width); + assert(rect->y_offset_ + rect->height_ <= dst->height); + + // Left boundary. + for (i = rect->x_offset_; i < rect->x_offset_ + rect->width_; ++i) { + const uint32_t* const src_argb = + &src->argb[rect->y_offset_ * src->argb_stride + i]; + const uint32_t* const dst_argb = + &dst->argb[rect->y_offset_ * dst->argb_stride + i]; + if (compare_pixels(src_argb, src->argb_stride, dst_argb, dst->argb_stride, + rect->height_, max_allowed_diff)) { + --rect->width_; // Redundant column. + ++rect->x_offset_; + } else { + break; + } + } + if (rect->width_ == 0) goto NoChange; + + // Right boundary. + for (i = rect->x_offset_ + rect->width_ - 1; i >= rect->x_offset_; --i) { + const uint32_t* const src_argb = + &src->argb[rect->y_offset_ * src->argb_stride + i]; + const uint32_t* const dst_argb = + &dst->argb[rect->y_offset_ * dst->argb_stride + i]; + if (compare_pixels(src_argb, src->argb_stride, dst_argb, dst->argb_stride, + rect->height_, max_allowed_diff)) { + --rect->width_; // Redundant column. + } else { + break; + } + } + if (rect->width_ == 0) goto NoChange; + + // Top boundary. + for (j = rect->y_offset_; j < rect->y_offset_ + rect->height_; ++j) { + const uint32_t* const src_argb = + &src->argb[j * src->argb_stride + rect->x_offset_]; + const uint32_t* const dst_argb = + &dst->argb[j * dst->argb_stride + rect->x_offset_]; + if (compare_pixels(src_argb, 1, dst_argb, 1, rect->width_, + max_allowed_diff)) { + --rect->height_; // Redundant row. + ++rect->y_offset_; + } else { + break; + } + } + if (rect->height_ == 0) goto NoChange; + + // Bottom boundary. + for (j = rect->y_offset_ + rect->height_ - 1; j >= rect->y_offset_; --j) { + const uint32_t* const src_argb = + &src->argb[j * src->argb_stride + rect->x_offset_]; + const uint32_t* const dst_argb = + &dst->argb[j * dst->argb_stride + rect->x_offset_]; + if (compare_pixels(src_argb, 1, dst_argb, 1, rect->width_, + max_allowed_diff)) { + --rect->height_; // Redundant row. + } else { + break; + } + } + if (rect->height_ == 0) goto NoChange; + + if (IsEmptyRect(rect)) { + NoChange: + rect->x_offset_ = 0; + rect->y_offset_ = 0; + rect->width_ = 0; + rect->height_ = 0; + } +} + +// Snap rectangle to even offsets (and adjust dimensions if needed). +static WEBP_INLINE void SnapToEvenOffsets(FrameRectangle* const rect) { + rect->width_ += (rect->x_offset_ & 1); + rect->height_ += (rect->y_offset_ & 1); + rect->x_offset_ &= ~1; + rect->y_offset_ &= ~1; +} + +typedef struct { + int should_try_; // Should try this set of parameters. + int empty_rect_allowed_; // Frame with empty rectangle can be skipped. + FrameRectangle rect_ll_; // Frame rectangle for lossless compression. + WebPPicture sub_frame_ll_; // Sub-frame pic for lossless compression. + FrameRectangle rect_lossy_; // Frame rectangle for lossy compression. + // Could be smaller than rect_ll_ as pixels + // with small diffs can be ignored. + WebPPicture sub_frame_lossy_; // Sub-frame pic for lossless compression. +} SubFrameParams; + +static int SubFrameParamsInit(SubFrameParams* const params, + int should_try, int empty_rect_allowed) { + params->should_try_ = should_try; + params->empty_rect_allowed_ = empty_rect_allowed; + if (!WebPPictureInit(¶ms->sub_frame_ll_) || + !WebPPictureInit(¶ms->sub_frame_lossy_)) { + return 0; + } + return 1; +} + +static void SubFrameParamsFree(SubFrameParams* const params) { + WebPPictureFree(¶ms->sub_frame_ll_); + WebPPictureFree(¶ms->sub_frame_lossy_); +} + +// Given previous and current canvas, picks the optimal rectangle for the +// current frame based on 'is_lossless' and other parameters. Assumes that the +// initial guess 'rect' is valid. +static int GetSubRect(const WebPPicture* const prev_canvas, + const WebPPicture* const curr_canvas, int is_key_frame, + int is_first_frame, int empty_rect_allowed, + int is_lossless, float quality, + FrameRectangle* const rect, + WebPPicture* const sub_frame) { + if (!is_key_frame || is_first_frame) { // Optimize frame rectangle. + // Note: This behaves as expected for first frame, as 'prev_canvas' is + // initialized to a fully transparent canvas in the beginning. + MinimizeChangeRectangle(prev_canvas, curr_canvas, rect, + is_lossless, quality); + } + + if (IsEmptyRect(rect)) { + if (empty_rect_allowed) { // No need to get 'sub_frame'. + return 1; + } else { // Force a 1x1 rectangle. + rect->width_ = 1; + rect->height_ = 1; + assert(rect->x_offset_ == 0); + assert(rect->y_offset_ == 0); + } + } + + SnapToEvenOffsets(rect); + return WebPPictureView(curr_canvas, rect->x_offset_, rect->y_offset_, + rect->width_, rect->height_, sub_frame); +} + +// Picks optimal frame rectangle for both lossless and lossy compression. The +// initial guess for frame rectangles will be the full canvas. +static int GetSubRects(const WebPPicture* const prev_canvas, + const WebPPicture* const curr_canvas, int is_key_frame, + int is_first_frame, float quality, + SubFrameParams* const params) { + // Lossless frame rectangle. + params->rect_ll_.x_offset_ = 0; + params->rect_ll_.y_offset_ = 0; + params->rect_ll_.width_ = curr_canvas->width; + params->rect_ll_.height_ = curr_canvas->height; + if (!GetSubRect(prev_canvas, curr_canvas, is_key_frame, is_first_frame, + params->empty_rect_allowed_, 1, quality, + ¶ms->rect_ll_, ¶ms->sub_frame_ll_)) { + return 0; + } + // Lossy frame rectangle. + params->rect_lossy_ = params->rect_ll_; // seed with lossless rect. + return GetSubRect(prev_canvas, curr_canvas, is_key_frame, is_first_frame, + params->empty_rect_allowed_, 0, quality, + ¶ms->rect_lossy_, ¶ms->sub_frame_lossy_); +} + +static WEBP_INLINE int clip(int v, int min_v, int max_v) { + return (v < min_v) ? min_v : (v > max_v) ? max_v : v; +} + +int WebPAnimEncoderRefineRect( + const WebPPicture* const prev_canvas, const WebPPicture* const curr_canvas, + int is_lossless, float quality, int* const x_offset, int* const y_offset, + int* const width, int* const height) { + FrameRectangle rect; + int right, left, bottom, top; + if (prev_canvas == NULL || curr_canvas == NULL || + prev_canvas->width != curr_canvas->width || + prev_canvas->height != curr_canvas->height || + !prev_canvas->use_argb || !curr_canvas->use_argb) { + return 0; + } + right = clip(*x_offset + *width, 0, curr_canvas->width); + left = clip(*x_offset, 0, curr_canvas->width - 1); + bottom = clip(*y_offset + *height, 0, curr_canvas->height); + top = clip(*y_offset, 0, curr_canvas->height - 1); + rect.x_offset_ = left; + rect.y_offset_ = top; + rect.width_ = clip(right - left, 0, curr_canvas->width - rect.x_offset_); + rect.height_ = clip(bottom - top, 0, curr_canvas->height - rect.y_offset_); + MinimizeChangeRectangle(prev_canvas, curr_canvas, &rect, is_lossless, + quality); + SnapToEvenOffsets(&rect); + *x_offset = rect.x_offset_; + *y_offset = rect.y_offset_; + *width = rect.width_; + *height = rect.height_; + return 1; +} + +static void DisposeFrameRectangle(int dispose_method, + const FrameRectangle* const rect, + WebPPicture* const curr_canvas) { + assert(rect != NULL); + if (dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) { + WebPUtilClearPic(curr_canvas, rect); + } +} + +static uint32_t RectArea(const FrameRectangle* const rect) { + return (uint32_t)rect->width_ * rect->height_; +} + +static int IsLosslessBlendingPossible(const WebPPicture* const src, + const WebPPicture* const dst, + const FrameRectangle* const rect) { + int i, j; + assert(src->width == dst->width && src->height == dst->height); + assert(rect->x_offset_ + rect->width_ <= dst->width); + assert(rect->y_offset_ + rect->height_ <= dst->height); + for (j = rect->y_offset_; j < rect->y_offset_ + rect->height_; ++j) { + for (i = rect->x_offset_; i < rect->x_offset_ + rect->width_; ++i) { + const uint32_t src_pixel = src->argb[j * src->argb_stride + i]; + const uint32_t dst_pixel = dst->argb[j * dst->argb_stride + i]; + const uint32_t dst_alpha = dst_pixel >> 24; + if (dst_alpha != 0xff && src_pixel != dst_pixel) { + // In this case, if we use blending, we can't attain the desired + // 'dst_pixel' value for this pixel. So, blending is not possible. + return 0; + } + } + } + return 1; +} + +static int IsLossyBlendingPossible(const WebPPicture* const src, + const WebPPicture* const dst, + const FrameRectangle* const rect, + float quality) { + const int max_allowed_diff_lossy = QualityToMaxDiff(quality); + int i, j; + assert(src->width == dst->width && src->height == dst->height); + assert(rect->x_offset_ + rect->width_ <= dst->width); + assert(rect->y_offset_ + rect->height_ <= dst->height); + for (j = rect->y_offset_; j < rect->y_offset_ + rect->height_; ++j) { + for (i = rect->x_offset_; i < rect->x_offset_ + rect->width_; ++i) { + const uint32_t src_pixel = src->argb[j * src->argb_stride + i]; + const uint32_t dst_pixel = dst->argb[j * dst->argb_stride + i]; + const uint32_t dst_alpha = dst_pixel >> 24; + if (dst_alpha != 0xff && + !PixelsAreSimilar(src_pixel, dst_pixel, max_allowed_diff_lossy)) { + // In this case, if we use blending, we can't attain the desired + // 'dst_pixel' value for this pixel. So, blending is not possible. + return 0; + } + } + } + return 1; +} + +// For pixels in 'rect', replace those pixels in 'dst' that are same as 'src' by +// transparent pixels. +// Returns true if at least one pixel gets modified. +static int IncreaseTransparency(const WebPPicture* const src, + const FrameRectangle* const rect, + WebPPicture* const dst) { + int i, j; + int modified = 0; + assert(src != NULL && dst != NULL && rect != NULL); + assert(src->width == dst->width && src->height == dst->height); + for (j = rect->y_offset_; j < rect->y_offset_ + rect->height_; ++j) { + const uint32_t* const psrc = src->argb + j * src->argb_stride; + uint32_t* const pdst = dst->argb + j * dst->argb_stride; + for (i = rect->x_offset_; i < rect->x_offset_ + rect->width_; ++i) { + if (psrc[i] == pdst[i] && pdst[i] != TRANSPARENT_COLOR) { + pdst[i] = TRANSPARENT_COLOR; + modified = 1; + } + } + } + return modified; +} + +#undef TRANSPARENT_COLOR + +// Replace similar blocks of pixels by a 'see-through' transparent block +// with uniform average color. +// Assumes lossy compression is being used. +// Returns true if at least one pixel gets modified. +static int FlattenSimilarBlocks(const WebPPicture* const src, + const FrameRectangle* const rect, + WebPPicture* const dst, float quality) { + const int max_allowed_diff_lossy = QualityToMaxDiff(quality); + int i, j; + int modified = 0; + const int block_size = 8; + const int y_start = (rect->y_offset_ + block_size) & ~(block_size - 1); + const int y_end = (rect->y_offset_ + rect->height_) & ~(block_size - 1); + const int x_start = (rect->x_offset_ + block_size) & ~(block_size - 1); + const int x_end = (rect->x_offset_ + rect->width_) & ~(block_size - 1); + assert(src != NULL && dst != NULL && rect != NULL); + assert(src->width == dst->width && src->height == dst->height); + assert((block_size & (block_size - 1)) == 0); // must be a power of 2 + // Iterate over each block and count similar pixels. + for (j = y_start; j < y_end; j += block_size) { + for (i = x_start; i < x_end; i += block_size) { + int cnt = 0; + int avg_r = 0, avg_g = 0, avg_b = 0; + int x, y; + const uint32_t* const psrc = src->argb + j * src->argb_stride + i; + uint32_t* const pdst = dst->argb + j * dst->argb_stride + i; + for (y = 0; y < block_size; ++y) { + for (x = 0; x < block_size; ++x) { + const uint32_t src_pixel = psrc[x + y * src->argb_stride]; + const int alpha = src_pixel >> 24; + if (alpha == 0xff && + PixelsAreSimilar(src_pixel, pdst[x + y * dst->argb_stride], + max_allowed_diff_lossy)) { + ++cnt; + avg_r += (src_pixel >> 16) & 0xff; + avg_g += (src_pixel >> 8) & 0xff; + avg_b += (src_pixel >> 0) & 0xff; + } + } + } + // If we have a fully similar block, we replace it with an + // average transparent block. This compresses better in lossy mode. + if (cnt == block_size * block_size) { + const uint32_t color = (0x00 << 24) | + ((avg_r / cnt) << 16) | + ((avg_g / cnt) << 8) | + ((avg_b / cnt) << 0); + for (y = 0; y < block_size; ++y) { + for (x = 0; x < block_size; ++x) { + pdst[x + y * dst->argb_stride] = color; + } + } + modified = 1; + } + } + } + return modified; +} + +static int EncodeFrame(const WebPConfig* const config, WebPPicture* const pic, + WebPMemoryWriter* const memory) { + pic->use_argb = 1; + pic->writer = WebPMemoryWrite; + pic->custom_ptr = memory; + if (!WebPEncode(config, pic)) { + return 0; + } + return 1; +} + +// Struct representing a candidate encoded frame including its metadata. +typedef struct { + WebPMemoryWriter mem_; + WebPMuxFrameInfo info_; + FrameRectangle rect_; + int evaluate_; // True if this candidate should be evaluated. +} Candidate; + +// Generates a candidate encoded frame given a picture and metadata. +static WebPEncodingError EncodeCandidate(WebPPicture* const sub_frame, + const FrameRectangle* const rect, + const WebPConfig* const encoder_config, + int use_blending, + Candidate* const candidate) { + WebPConfig config = *encoder_config; + WebPEncodingError error_code = VP8_ENC_OK; + assert(candidate != NULL); + memset(candidate, 0, sizeof(*candidate)); + + // Set frame rect and info. + candidate->rect_ = *rect; + candidate->info_.id = WEBP_CHUNK_ANMF; + candidate->info_.x_offset = rect->x_offset_; + candidate->info_.y_offset = rect->y_offset_; + candidate->info_.dispose_method = WEBP_MUX_DISPOSE_NONE; // Set later. + candidate->info_.blend_method = + use_blending ? WEBP_MUX_BLEND : WEBP_MUX_NO_BLEND; + candidate->info_.duration = 0; // Set in next call to WebPAnimEncoderAdd(). + + // Encode picture. + WebPMemoryWriterInit(&candidate->mem_); + + if (!config.lossless && use_blending) { + // Disable filtering to avoid blockiness in reconstructed frames at the + // time of decoding. + config.autofilter = 0; + config.filter_strength = 0; + } + if (!EncodeFrame(&config, sub_frame, &candidate->mem_)) { + error_code = sub_frame->error_code; + goto Err; + } + + candidate->evaluate_ = 1; + return error_code; + + Err: + WebPMemoryWriterClear(&candidate->mem_); + return error_code; +} + +static void CopyCurrentCanvas(WebPAnimEncoder* const enc) { + if (enc->curr_canvas_copy_modified_) { + WebPCopyPixels(enc->curr_canvas_, &enc->curr_canvas_copy_); + enc->curr_canvas_copy_.progress_hook = enc->curr_canvas_->progress_hook; + enc->curr_canvas_copy_.user_data = enc->curr_canvas_->user_data; + enc->curr_canvas_copy_modified_ = 0; + } +} + +enum { + LL_DISP_NONE = 0, + LL_DISP_BG, + LOSSY_DISP_NONE, + LOSSY_DISP_BG, + CANDIDATE_COUNT +}; + +#define MIN_COLORS_LOSSY 31 // Don't try lossy below this threshold. +#define MAX_COLORS_LOSSLESS 194 // Don't try lossless above this threshold. + +// Generates candidates for a given dispose method given pre-filled sub-frame +// 'params'. +static WebPEncodingError GenerateCandidates( + WebPAnimEncoder* const enc, Candidate candidates[CANDIDATE_COUNT], + WebPMuxAnimDispose dispose_method, int is_lossless, int is_key_frame, + SubFrameParams* const params, + const WebPConfig* const config_ll, const WebPConfig* const config_lossy) { + WebPEncodingError error_code = VP8_ENC_OK; + const int is_dispose_none = (dispose_method == WEBP_MUX_DISPOSE_NONE); + Candidate* const candidate_ll = + is_dispose_none ? &candidates[LL_DISP_NONE] : &candidates[LL_DISP_BG]; + Candidate* const candidate_lossy = is_dispose_none + ? &candidates[LOSSY_DISP_NONE] + : &candidates[LOSSY_DISP_BG]; + WebPPicture* const curr_canvas = &enc->curr_canvas_copy_; + const WebPPicture* const prev_canvas = + is_dispose_none ? &enc->prev_canvas_ : &enc->prev_canvas_disposed_; + int use_blending_ll, use_blending_lossy; + int evaluate_ll, evaluate_lossy; + + CopyCurrentCanvas(enc); + use_blending_ll = + !is_key_frame && + IsLosslessBlendingPossible(prev_canvas, curr_canvas, ¶ms->rect_ll_); + use_blending_lossy = + !is_key_frame && + IsLossyBlendingPossible(prev_canvas, curr_canvas, ¶ms->rect_lossy_, + config_lossy->quality); + + // Pick candidates to be tried. + if (!enc->options_.allow_mixed) { + evaluate_ll = is_lossless; + evaluate_lossy = !is_lossless; + } else if (enc->options_.minimize_size) { + evaluate_ll = 1; + evaluate_lossy = 1; + } else { // Use a heuristic for trying lossless and/or lossy compression. + const int num_colors = WebPGetColorPalette(¶ms->sub_frame_ll_, NULL); + evaluate_ll = (num_colors < MAX_COLORS_LOSSLESS); + evaluate_lossy = (num_colors >= MIN_COLORS_LOSSY); + } + + // Generate candidates. + if (evaluate_ll) { + CopyCurrentCanvas(enc); + if (use_blending_ll) { + enc->curr_canvas_copy_modified_ = + IncreaseTransparency(prev_canvas, ¶ms->rect_ll_, curr_canvas); + } + error_code = EncodeCandidate(¶ms->sub_frame_ll_, ¶ms->rect_ll_, + config_ll, use_blending_ll, candidate_ll); + if (error_code != VP8_ENC_OK) return error_code; + } + if (evaluate_lossy) { + CopyCurrentCanvas(enc); + if (use_blending_lossy) { + enc->curr_canvas_copy_modified_ = + FlattenSimilarBlocks(prev_canvas, ¶ms->rect_lossy_, curr_canvas, + config_lossy->quality); + } + error_code = + EncodeCandidate(¶ms->sub_frame_lossy_, ¶ms->rect_lossy_, + config_lossy, use_blending_lossy, candidate_lossy); + if (error_code != VP8_ENC_OK) return error_code; + enc->curr_canvas_copy_modified_ = 1; + } + return error_code; +} + +#undef MIN_COLORS_LOSSY +#undef MAX_COLORS_LOSSLESS + +static void GetEncodedData(const WebPMemoryWriter* const memory, + WebPData* const encoded_data) { + encoded_data->bytes = memory->mem; + encoded_data->size = memory->size; +} + +// Sets dispose method of the previous frame to be 'dispose_method'. +static void SetPreviousDisposeMethod(WebPAnimEncoder* const enc, + WebPMuxAnimDispose dispose_method) { + const size_t position = enc->count_ - 2; + EncodedFrame* const prev_enc_frame = GetFrame(enc, position); + assert(enc->count_ >= 2); // As current and previous frames are in enc. + + if (enc->prev_candidate_undecided_) { + assert(dispose_method == WEBP_MUX_DISPOSE_NONE); + prev_enc_frame->sub_frame_.dispose_method = dispose_method; + prev_enc_frame->key_frame_.dispose_method = dispose_method; + } else { + WebPMuxFrameInfo* const prev_info = prev_enc_frame->is_key_frame_ + ? &prev_enc_frame->key_frame_ + : &prev_enc_frame->sub_frame_; + prev_info->dispose_method = dispose_method; + } +} + +static int IncreasePreviousDuration(WebPAnimEncoder* const enc, int duration) { + const size_t position = enc->count_ - 1; + EncodedFrame* const prev_enc_frame = GetFrame(enc, position); + int new_duration; + + assert(enc->count_ >= 1); + assert(!prev_enc_frame->is_key_frame_ || + prev_enc_frame->sub_frame_.duration == + prev_enc_frame->key_frame_.duration); + assert(prev_enc_frame->sub_frame_.duration == + (prev_enc_frame->sub_frame_.duration & (MAX_DURATION - 1))); + assert(duration == (duration & (MAX_DURATION - 1))); + + new_duration = prev_enc_frame->sub_frame_.duration + duration; + if (new_duration >= MAX_DURATION) { // Special case. + // Separate out previous frame from earlier merged frames to avoid overflow. + // We add a 1x1 transparent frame for the previous frame, with blending on. + const FrameRectangle rect = { 0, 0, 1, 1 }; + const uint8_t lossless_1x1_bytes[] = { + 0x52, 0x49, 0x46, 0x46, 0x14, 0x00, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50, + 0x56, 0x50, 0x38, 0x4c, 0x08, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, + 0x10, 0x88, 0x88, 0x08 + }; + const WebPData lossless_1x1 = { + lossless_1x1_bytes, sizeof(lossless_1x1_bytes) + }; + const uint8_t lossy_1x1_bytes[] = { + 0x52, 0x49, 0x46, 0x46, 0x40, 0x00, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50, + 0x56, 0x50, 0x38, 0x58, 0x0a, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x4c, 0x50, 0x48, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x56, 0x50, 0x38, 0x20, 0x18, 0x00, 0x00, 0x00, + 0x30, 0x01, 0x00, 0x9d, 0x01, 0x2a, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, + 0x34, 0x25, 0xa4, 0x00, 0x03, 0x70, 0x00, 0xfe, 0xfb, 0xfd, 0x50, 0x00 + }; + const WebPData lossy_1x1 = { lossy_1x1_bytes, sizeof(lossy_1x1_bytes) }; + const int can_use_lossless = + (enc->last_config_.lossless || enc->options_.allow_mixed); + EncodedFrame* const curr_enc_frame = GetFrame(enc, enc->count_); + curr_enc_frame->is_key_frame_ = 0; + curr_enc_frame->sub_frame_.id = WEBP_CHUNK_ANMF; + curr_enc_frame->sub_frame_.x_offset = 0; + curr_enc_frame->sub_frame_.y_offset = 0; + curr_enc_frame->sub_frame_.dispose_method = WEBP_MUX_DISPOSE_NONE; + curr_enc_frame->sub_frame_.blend_method = WEBP_MUX_BLEND; + curr_enc_frame->sub_frame_.duration = duration; + if (!WebPDataCopy(can_use_lossless ? &lossless_1x1 : &lossy_1x1, + &curr_enc_frame->sub_frame_.bitstream)) { + return 0; + } + ++enc->count_; + ++enc->count_since_key_frame_; + enc->flush_count_ = enc->count_ - 1; + enc->prev_candidate_undecided_ = 0; + enc->prev_rect_ = rect; + } else { // Regular case. + // Increase duration of the previous frame by 'duration'. + prev_enc_frame->sub_frame_.duration = new_duration; + prev_enc_frame->key_frame_.duration = new_duration; + } + return 1; +} + +// Pick the candidate encoded frame with smallest size and release other +// candidates. +// TODO(later): Perhaps a rough SSIM/PSNR produced by the encoder should +// also be a criteria, in addition to sizes. +static void PickBestCandidate(WebPAnimEncoder* const enc, + Candidate* const candidates, int is_key_frame, + EncodedFrame* const encoded_frame) { + int i; + int best_idx = -1; + size_t best_size = ~0; + for (i = 0; i < CANDIDATE_COUNT; ++i) { + if (candidates[i].evaluate_) { + const size_t candidate_size = candidates[i].mem_.size; + if (candidate_size < best_size) { + best_idx = i; + best_size = candidate_size; + } + } + } + assert(best_idx != -1); + for (i = 0; i < CANDIDATE_COUNT; ++i) { + if (candidates[i].evaluate_) { + if (i == best_idx) { + WebPMuxFrameInfo* const dst = is_key_frame + ? &encoded_frame->key_frame_ + : &encoded_frame->sub_frame_; + *dst = candidates[i].info_; + GetEncodedData(&candidates[i].mem_, &dst->bitstream); + if (!is_key_frame) { + // Note: Previous dispose method only matters for non-keyframes. + // Also, we don't want to modify previous dispose method that was + // selected when a non key-frame was assumed. + const WebPMuxAnimDispose prev_dispose_method = + (best_idx == LL_DISP_NONE || best_idx == LOSSY_DISP_NONE) + ? WEBP_MUX_DISPOSE_NONE + : WEBP_MUX_DISPOSE_BACKGROUND; + SetPreviousDisposeMethod(enc, prev_dispose_method); + } + enc->prev_rect_ = candidates[i].rect_; // save for next frame. + } else { + WebPMemoryWriterClear(&candidates[i].mem_); + candidates[i].evaluate_ = 0; + } + } + } +} + +// Depending on the configuration, tries different compressions +// (lossy/lossless), dispose methods, blending methods etc to encode the current +// frame and outputs the best one in 'encoded_frame'. +// 'frame_skipped' will be set to true if this frame should actually be skipped. +static WebPEncodingError SetFrame(WebPAnimEncoder* const enc, + const WebPConfig* const config, + int is_key_frame, + EncodedFrame* const encoded_frame, + int* const frame_skipped) { + int i; + WebPEncodingError error_code = VP8_ENC_OK; + const WebPPicture* const curr_canvas = &enc->curr_canvas_copy_; + const WebPPicture* const prev_canvas = &enc->prev_canvas_; + Candidate candidates[CANDIDATE_COUNT]; + const int is_lossless = config->lossless; + const int consider_lossless = is_lossless || enc->options_.allow_mixed; + const int consider_lossy = !is_lossless || enc->options_.allow_mixed; + const int is_first_frame = enc->is_first_frame_; + + // First frame cannot be skipped as there is no 'previous frame' to merge it + // to. So, empty rectangle is not allowed for the first frame. + const int empty_rect_allowed_none = !is_first_frame; + + // Even if there is exact pixel match between 'disposed previous canvas' and + // 'current canvas', we can't skip current frame, as there may not be exact + // pixel match between 'previous canvas' and 'current canvas'. So, we don't + // allow empty rectangle in this case. + const int empty_rect_allowed_bg = 0; + + // If current frame is a key-frame, dispose method of previous frame doesn't + // matter, so we don't try dispose to background. + // Also, if key-frame insertion is on, and previous frame could be picked as + // either a sub-frame or a key-frame, then we can't be sure about what frame + // rectangle would be disposed. In that case too, we don't try dispose to + // background. + const int dispose_bg_possible = + !is_key_frame && !enc->prev_candidate_undecided_; + + SubFrameParams dispose_none_params; + SubFrameParams dispose_bg_params; + + WebPConfig config_ll = *config; + WebPConfig config_lossy = *config; + config_ll.lossless = 1; + config_lossy.lossless = 0; + enc->last_config_ = *config; + enc->last_config_reversed_ = config->lossless ? config_lossy : config_ll; + *frame_skipped = 0; + + if (!SubFrameParamsInit(&dispose_none_params, 1, empty_rect_allowed_none) || + !SubFrameParamsInit(&dispose_bg_params, 0, empty_rect_allowed_bg)) { + return VP8_ENC_ERROR_INVALID_CONFIGURATION; + } + + memset(candidates, 0, sizeof(candidates)); + + // Change-rectangle assuming previous frame was DISPOSE_NONE. + if (!GetSubRects(prev_canvas, curr_canvas, is_key_frame, is_first_frame, + config_lossy.quality, &dispose_none_params)) { + error_code = VP8_ENC_ERROR_INVALID_CONFIGURATION; + goto Err; + } + + if ((consider_lossless && IsEmptyRect(&dispose_none_params.rect_ll_)) || + (consider_lossy && IsEmptyRect(&dispose_none_params.rect_lossy_))) { + // Don't encode the frame at all. Instead, the duration of the previous + // frame will be increased later. + assert(empty_rect_allowed_none); + *frame_skipped = 1; + goto End; + } + + if (dispose_bg_possible) { + // Change-rectangle assuming previous frame was DISPOSE_BACKGROUND. + WebPPicture* const prev_canvas_disposed = &enc->prev_canvas_disposed_; + WebPCopyPixels(prev_canvas, prev_canvas_disposed); + DisposeFrameRectangle(WEBP_MUX_DISPOSE_BACKGROUND, &enc->prev_rect_, + prev_canvas_disposed); + + if (!GetSubRects(prev_canvas_disposed, curr_canvas, is_key_frame, + is_first_frame, config_lossy.quality, + &dispose_bg_params)) { + error_code = VP8_ENC_ERROR_INVALID_CONFIGURATION; + goto Err; + } + assert(!IsEmptyRect(&dispose_bg_params.rect_ll_)); + assert(!IsEmptyRect(&dispose_bg_params.rect_lossy_)); + + if (enc->options_.minimize_size) { // Try both dispose methods. + dispose_bg_params.should_try_ = 1; + dispose_none_params.should_try_ = 1; + } else if ((is_lossless && + RectArea(&dispose_bg_params.rect_ll_) < + RectArea(&dispose_none_params.rect_ll_)) || + (!is_lossless && + RectArea(&dispose_bg_params.rect_lossy_) < + RectArea(&dispose_none_params.rect_lossy_))) { + dispose_bg_params.should_try_ = 1; // Pick DISPOSE_BACKGROUND. + dispose_none_params.should_try_ = 0; + } + } + + if (dispose_none_params.should_try_) { + error_code = GenerateCandidates( + enc, candidates, WEBP_MUX_DISPOSE_NONE, is_lossless, is_key_frame, + &dispose_none_params, &config_ll, &config_lossy); + if (error_code != VP8_ENC_OK) goto Err; + } + + if (dispose_bg_params.should_try_) { + assert(!enc->is_first_frame_); + assert(dispose_bg_possible); + error_code = GenerateCandidates( + enc, candidates, WEBP_MUX_DISPOSE_BACKGROUND, is_lossless, is_key_frame, + &dispose_bg_params, &config_ll, &config_lossy); + if (error_code != VP8_ENC_OK) goto Err; + } + + PickBestCandidate(enc, candidates, is_key_frame, encoded_frame); + + goto End; + + Err: + for (i = 0; i < CANDIDATE_COUNT; ++i) { + if (candidates[i].evaluate_) { + WebPMemoryWriterClear(&candidates[i].mem_); + } + } + + End: + SubFrameParamsFree(&dispose_none_params); + SubFrameParamsFree(&dispose_bg_params); + return error_code; +} + +// Calculate the penalty incurred if we encode given frame as a key frame +// instead of a sub-frame. +static int64_t KeyFramePenalty(const EncodedFrame* const encoded_frame) { + return ((int64_t)encoded_frame->key_frame_.bitstream.size - + encoded_frame->sub_frame_.bitstream.size); +} + +static int CacheFrame(WebPAnimEncoder* const enc, + const WebPConfig* const config) { + int ok = 0; + int frame_skipped = 0; + WebPEncodingError error_code = VP8_ENC_OK; + const size_t position = enc->count_; + EncodedFrame* const encoded_frame = GetFrame(enc, position); + + ++enc->count_; + + if (enc->is_first_frame_) { // Add this as a key-frame. + error_code = SetFrame(enc, config, 1, encoded_frame, &frame_skipped); + if (error_code != VP8_ENC_OK) goto End; + assert(frame_skipped == 0); // First frame can't be skipped, even if empty. + assert(position == 0 && enc->count_ == 1); + encoded_frame->is_key_frame_ = 1; + enc->flush_count_ = 0; + enc->count_since_key_frame_ = 0; + enc->prev_candidate_undecided_ = 0; + } else { + ++enc->count_since_key_frame_; + if (enc->count_since_key_frame_ <= enc->options_.kmin) { + // Add this as a frame rectangle. + error_code = SetFrame(enc, config, 0, encoded_frame, &frame_skipped); + if (error_code != VP8_ENC_OK) goto End; + if (frame_skipped) goto Skip; + encoded_frame->is_key_frame_ = 0; + enc->flush_count_ = enc->count_ - 1; + enc->prev_candidate_undecided_ = 0; + } else { + int64_t curr_delta; + FrameRectangle prev_rect_key, prev_rect_sub; + + // Add this as a frame rectangle to enc. + error_code = SetFrame(enc, config, 0, encoded_frame, &frame_skipped); + if (error_code != VP8_ENC_OK) goto End; + if (frame_skipped) goto Skip; + prev_rect_sub = enc->prev_rect_; + + + // Add this as a key-frame to enc, too. + error_code = SetFrame(enc, config, 1, encoded_frame, &frame_skipped); + if (error_code != VP8_ENC_OK) goto End; + assert(frame_skipped == 0); // Key-frame cannot be an empty rectangle. + prev_rect_key = enc->prev_rect_; + + // Analyze size difference of the two variants. + curr_delta = KeyFramePenalty(encoded_frame); + if (curr_delta <= enc->best_delta_) { // Pick this as the key-frame. + if (enc->keyframe_ != KEYFRAME_NONE) { + EncodedFrame* const old_keyframe = GetFrame(enc, enc->keyframe_); + assert(old_keyframe->is_key_frame_); + old_keyframe->is_key_frame_ = 0; + } + encoded_frame->is_key_frame_ = 1; + enc->prev_candidate_undecided_ = 1; + enc->keyframe_ = (int)position; + enc->best_delta_ = curr_delta; + enc->flush_count_ = enc->count_ - 1; // We can flush previous frames. + } else { + encoded_frame->is_key_frame_ = 0; + enc->prev_candidate_undecided_ = 0; + } + // Note: We need '>=' below because when kmin and kmax are both zero, + // count_since_key_frame will always be > kmax. + if (enc->count_since_key_frame_ >= enc->options_.kmax) { + enc->flush_count_ = enc->count_ - 1; + enc->count_since_key_frame_ = 0; + enc->keyframe_ = KEYFRAME_NONE; + enc->best_delta_ = DELTA_INFINITY; + } + if (!enc->prev_candidate_undecided_) { + enc->prev_rect_ = + encoded_frame->is_key_frame_ ? prev_rect_key : prev_rect_sub; + } + } + } + + // Update previous to previous and previous canvases for next call. + WebPCopyPixels(enc->curr_canvas_, &enc->prev_canvas_); + enc->is_first_frame_ = 0; + + Skip: + ok = 1; + ++enc->in_frame_count_; + + End: + if (!ok || frame_skipped) { + FrameRelease(encoded_frame); + // We reset some counters, as the frame addition failed/was skipped. + --enc->count_; + if (!enc->is_first_frame_) --enc->count_since_key_frame_; + if (!ok) { + MarkError2(enc, "ERROR adding frame. WebPEncodingError", error_code); + } + } + enc->curr_canvas_->error_code = error_code; // report error_code + assert(ok || error_code != VP8_ENC_OK); + return ok; +} + +static int FlushFrames(WebPAnimEncoder* const enc) { + while (enc->flush_count_ > 0) { + WebPMuxError err; + EncodedFrame* const curr = GetFrame(enc, 0); + const WebPMuxFrameInfo* const info = + curr->is_key_frame_ ? &curr->key_frame_ : &curr->sub_frame_; + assert(enc->mux_ != NULL); + err = WebPMuxPushFrame(enc->mux_, info, 1); + if (err != WEBP_MUX_OK) { + MarkError2(enc, "ERROR adding frame. WebPMuxError", err); + return 0; + } + if (enc->options_.verbose) { + fprintf(stderr, "INFO: Added frame. offset:%d,%d dispose:%d blend:%d\n", + info->x_offset, info->y_offset, info->dispose_method, + info->blend_method); + } + ++enc->out_frame_count_; + FrameRelease(curr); + ++enc->start_; + --enc->flush_count_; + --enc->count_; + if (enc->keyframe_ != KEYFRAME_NONE) --enc->keyframe_; + } + + if (enc->count_ == 1 && enc->start_ != 0) { + // Move enc->start to index 0. + const int enc_start_tmp = (int)enc->start_; + EncodedFrame temp = enc->encoded_frames_[0]; + enc->encoded_frames_[0] = enc->encoded_frames_[enc_start_tmp]; + enc->encoded_frames_[enc_start_tmp] = temp; + FrameRelease(&enc->encoded_frames_[enc_start_tmp]); + enc->start_ = 0; + } + return 1; +} + +#undef DELTA_INFINITY +#undef KEYFRAME_NONE + +int WebPAnimEncoderAdd(WebPAnimEncoder* enc, WebPPicture* frame, int timestamp, + const WebPConfig* encoder_config) { + WebPConfig config; + int ok; + + if (enc == NULL) { + return 0; + } + MarkNoError(enc); + + if (!enc->is_first_frame_) { + // Make sure timestamps are non-decreasing (integer wrap-around is OK). + const uint32_t prev_frame_duration = + (uint32_t)timestamp - enc->prev_timestamp_; + if (prev_frame_duration >= MAX_DURATION) { + if (frame != NULL) { + frame->error_code = VP8_ENC_ERROR_INVALID_CONFIGURATION; + } + MarkError(enc, "ERROR adding frame: timestamps must be non-decreasing"); + return 0; + } + if (!IncreasePreviousDuration(enc, (int)prev_frame_duration)) { + return 0; + } + // IncreasePreviousDuration() may add a frame to avoid exceeding + // MAX_DURATION which could cause CacheFrame() to over read encoded_frames_ + // before the next flush. + if (enc->count_ == enc->size_ && !FlushFrames(enc)) { + return 0; + } + } else { + enc->first_timestamp_ = timestamp; + } + + if (frame == NULL) { // Special: last call. + enc->got_null_frame_ = 1; + enc->prev_timestamp_ = timestamp; + return 1; + } + + if (frame->width != enc->canvas_width_ || + frame->height != enc->canvas_height_) { + frame->error_code = VP8_ENC_ERROR_INVALID_CONFIGURATION; + MarkError(enc, "ERROR adding frame: Invalid frame dimensions"); + return 0; + } + + if (!frame->use_argb) { // Convert frame from YUV(A) to ARGB. + if (enc->options_.verbose) { + fprintf(stderr, "WARNING: Converting frame from YUV(A) to ARGB format; " + "this incurs a small loss.\n"); + } + if (!WebPPictureYUVAToARGB(frame)) { + MarkError(enc, "ERROR converting frame from YUV(A) to ARGB"); + return 0; + } + } + + if (encoder_config != NULL) { + if (!WebPValidateConfig(encoder_config)) { + MarkError(enc, "ERROR adding frame: Invalid WebPConfig"); + return 0; + } + config = *encoder_config; + } else { + WebPConfigInit(&config); + config.lossless = 1; + } + assert(enc->curr_canvas_ == NULL); + enc->curr_canvas_ = frame; // Store reference. + assert(enc->curr_canvas_copy_modified_ == 1); + CopyCurrentCanvas(enc); + + ok = CacheFrame(enc, &config) && FlushFrames(enc); + + enc->curr_canvas_ = NULL; + enc->curr_canvas_copy_modified_ = 1; + if (ok) { + enc->prev_timestamp_ = timestamp; + } + return ok; +} + +// ----------------------------------------------------------------------------- +// Bitstream assembly. + +static int DecodeFrameOntoCanvas(const WebPMuxFrameInfo* const frame, + WebPPicture* const canvas) { + const WebPData* const image = &frame->bitstream; + WebPPicture sub_image; + WebPDecoderConfig config; + WebPInitDecoderConfig(&config); + WebPUtilClearPic(canvas, NULL); + if (WebPGetFeatures(image->bytes, image->size, &config.input) != + VP8_STATUS_OK) { + return 0; + } + if (!WebPPictureView(canvas, frame->x_offset, frame->y_offset, + config.input.width, config.input.height, &sub_image)) { + return 0; + } + config.output.is_external_memory = 1; + config.output.colorspace = MODE_BGRA; + config.output.u.RGBA.rgba = (uint8_t*)sub_image.argb; + config.output.u.RGBA.stride = sub_image.argb_stride * 4; + config.output.u.RGBA.size = config.output.u.RGBA.stride * sub_image.height; + + if (WebPDecode(image->bytes, image->size, &config) != VP8_STATUS_OK) { + return 0; + } + return 1; +} + +static int FrameToFullCanvas(WebPAnimEncoder* const enc, + const WebPMuxFrameInfo* const frame, + WebPData* const full_image) { + WebPPicture* const canvas_buf = &enc->curr_canvas_copy_; + WebPMemoryWriter mem1, mem2; + WebPMemoryWriterInit(&mem1); + WebPMemoryWriterInit(&mem2); + + if (!DecodeFrameOntoCanvas(frame, canvas_buf)) goto Err; + if (!EncodeFrame(&enc->last_config_, canvas_buf, &mem1)) goto Err; + GetEncodedData(&mem1, full_image); + + if (enc->options_.allow_mixed) { + if (!EncodeFrame(&enc->last_config_reversed_, canvas_buf, &mem2)) goto Err; + if (mem2.size < mem1.size) { + GetEncodedData(&mem2, full_image); + WebPMemoryWriterClear(&mem1); + } else { + WebPMemoryWriterClear(&mem2); + } + } + return 1; + + Err: + WebPMemoryWriterClear(&mem1); + WebPMemoryWriterClear(&mem2); + return 0; +} + +// Convert a single-frame animation to a non-animated image if appropriate. +// TODO(urvang): Can we pick one of the two heuristically (based on frame +// rectangle and/or presence of alpha)? +static WebPMuxError OptimizeSingleFrame(WebPAnimEncoder* const enc, + WebPData* const webp_data) { + WebPMuxError err = WEBP_MUX_OK; + int canvas_width, canvas_height; + WebPMuxFrameInfo frame; + WebPData full_image; + WebPData webp_data2; + WebPMux* const mux = WebPMuxCreate(webp_data, 0); + if (mux == NULL) return WEBP_MUX_BAD_DATA; + assert(enc->out_frame_count_ == 1); + WebPDataInit(&frame.bitstream); + WebPDataInit(&full_image); + WebPDataInit(&webp_data2); + + err = WebPMuxGetFrame(mux, 1, &frame); + if (err != WEBP_MUX_OK) goto End; + if (frame.id != WEBP_CHUNK_ANMF) goto End; // Non-animation: nothing to do. + err = WebPMuxGetCanvasSize(mux, &canvas_width, &canvas_height); + if (err != WEBP_MUX_OK) goto End; + if (!FrameToFullCanvas(enc, &frame, &full_image)) { + err = WEBP_MUX_BAD_DATA; + goto End; + } + err = WebPMuxSetImage(mux, &full_image, 1); + if (err != WEBP_MUX_OK) goto End; + err = WebPMuxAssemble(mux, &webp_data2); + if (err != WEBP_MUX_OK) goto End; + + if (webp_data2.size < webp_data->size) { // Pick 'webp_data2' if smaller. + WebPDataClear(webp_data); + *webp_data = webp_data2; + WebPDataInit(&webp_data2); + } + + End: + WebPDataClear(&frame.bitstream); + WebPDataClear(&full_image); + WebPMuxDelete(mux); + WebPDataClear(&webp_data2); + return err; +} + +int WebPAnimEncoderAssemble(WebPAnimEncoder* enc, WebPData* webp_data) { + WebPMux* mux; + WebPMuxError err; + + if (enc == NULL) { + return 0; + } + MarkNoError(enc); + + if (webp_data == NULL) { + MarkError(enc, "ERROR assembling: NULL input"); + return 0; + } + + if (enc->in_frame_count_ == 0) { + MarkError(enc, "ERROR: No frames to assemble"); + return 0; + } + + if (!enc->got_null_frame_ && enc->in_frame_count_ > 1 && enc->count_ > 0) { + // set duration of the last frame to be avg of durations of previous frames. + const double delta_time = + (uint32_t)enc->prev_timestamp_ - enc->first_timestamp_; + const int average_duration = (int)(delta_time / (enc->in_frame_count_ - 1)); + if (!IncreasePreviousDuration(enc, average_duration)) { + return 0; + } + } + + // Flush any remaining frames. + enc->flush_count_ = enc->count_; + if (!FlushFrames(enc)) { + return 0; + } + + // Set definitive canvas size. + mux = enc->mux_; + err = WebPMuxSetCanvasSize(mux, enc->canvas_width_, enc->canvas_height_); + if (err != WEBP_MUX_OK) goto Err; + + err = WebPMuxSetAnimationParams(mux, &enc->options_.anim_params); + if (err != WEBP_MUX_OK) goto Err; + + // Assemble into a WebP bitstream. + err = WebPMuxAssemble(mux, webp_data); + if (err != WEBP_MUX_OK) goto Err; + + if (enc->out_frame_count_ == 1) { + err = OptimizeSingleFrame(enc, webp_data); + if (err != WEBP_MUX_OK) goto Err; + } + return 1; + + Err: + MarkError2(enc, "ERROR assembling WebP", err); + return 0; +} + +const char* WebPAnimEncoderGetError(WebPAnimEncoder* enc) { + if (enc == NULL) return NULL; + return enc->error_str_; +} + +// ----------------------------------------------------------------------------- diff --git a/third-party/webp/libwebp/src/mux/animi.h b/third-party/webp/libwebp/src/mux/animi.h new file mode 100644 index 0000000000..34c45ba4da --- /dev/null +++ b/third-party/webp/libwebp/src/mux/animi.h @@ -0,0 +1,43 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Internal header for animation related functions. +// +// Author: Hui Su (huisu@google.com) + +#ifndef WEBP_MUX_ANIMI_H_ +#define WEBP_MUX_ANIMI_H_ + +#include "src/webp/mux.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Picks the optimal rectangle between two pictures, starting with initial +// values of offsets and dimensions that are passed in. The initial +// values will be clipped, if necessary, to make sure the rectangle is +// within the canvas. "use_argb" must be true for both pictures. +// Parameters: +// prev_canvas, curr_canvas - (in) two input pictures to compare. +// is_lossless, quality - (in) encoding settings. +// x_offset, y_offset, width, height - (in/out) rectangle between the two +// input pictures. +// Returns true on success. +int WebPAnimEncoderRefineRect( + const struct WebPPicture* const prev_canvas, + const struct WebPPicture* const curr_canvas, + int is_lossless, float quality, int* const x_offset, int* const y_offset, + int* const width, int* const height); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_MUX_ANIMI_H_ diff --git a/third-party/webp/libwebp/src/mux/libwebpmux.pc.in b/third-party/webp/libwebp/src/mux/libwebpmux.pc.in new file mode 100644 index 0000000000..c770daafc6 --- /dev/null +++ b/third-party/webp/libwebp/src/mux/libwebpmux.pc.in @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libwebpmux +Description: Library for manipulating the WebP graphics format container +Version: @PACKAGE_VERSION@ +Requires.private: libwebp >= 0.2.0 +Cflags: -I${includedir} +Libs: -L${libdir} -l@webp_libname_prefix@webpmux +Libs.private: -lm diff --git a/third-party/webp/libwebp/src/mux/libwebpmux.rc b/third-party/webp/libwebp/src/mux/libwebpmux.rc new file mode 100644 index 0000000000..bca38f6d87 --- /dev/null +++ b/third-party/webp/libwebp/src/mux/libwebpmux.rc @@ -0,0 +1,41 @@ +#define APSTUDIO_READONLY_SYMBOLS +#include "winres.h" +#undef APSTUDIO_READONLY_SYMBOLS + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,3,2 + PRODUCTVERSION 1,0,3,2 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "Google, Inc." + VALUE "FileDescription", "libwebpmux DLL" + VALUE "FileVersion", "1.3.2" + VALUE "InternalName", "libwebpmux.dll" + VALUE "LegalCopyright", "Copyright (C) 2023" + VALUE "OriginalFilename", "libwebpmux.dll" + VALUE "ProductName", "WebP Image Muxer" + VALUE "ProductVersion", "1.3.2" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // English (United States) resources diff --git a/third-party/webp/libwebp/src/mux/muxedit.c b/third-party/webp/libwebp/src/mux/muxedit.c new file mode 100644 index 0000000000..aab479cc6c --- /dev/null +++ b/third-party/webp/libwebp/src/mux/muxedit.c @@ -0,0 +1,657 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Set and delete APIs for mux. +// +// Authors: Urvang (urvang@google.com) +// Vikas (vikasa@google.com) + +#include +#include "src/mux/muxi.h" +#include "src/utils/utils.h" + +//------------------------------------------------------------------------------ +// Life of a mux object. + +static void MuxInit(WebPMux* const mux) { + assert(mux != NULL); + memset(mux, 0, sizeof(*mux)); + mux->canvas_width_ = 0; // just to be explicit + mux->canvas_height_ = 0; +} + +WebPMux* WebPNewInternal(int version) { + if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_MUX_ABI_VERSION)) { + return NULL; + } else { + WebPMux* const mux = (WebPMux*)WebPSafeMalloc(1ULL, sizeof(WebPMux)); + if (mux != NULL) MuxInit(mux); + return mux; + } +} + +// Delete all images in 'wpi_list'. +static void DeleteAllImages(WebPMuxImage** const wpi_list) { + while (*wpi_list != NULL) { + *wpi_list = MuxImageDelete(*wpi_list); + } +} + +static void MuxRelease(WebPMux* const mux) { + assert(mux != NULL); + DeleteAllImages(&mux->images_); + ChunkListDelete(&mux->vp8x_); + ChunkListDelete(&mux->iccp_); + ChunkListDelete(&mux->anim_); + ChunkListDelete(&mux->exif_); + ChunkListDelete(&mux->xmp_); + ChunkListDelete(&mux->unknown_); +} + +void WebPMuxDelete(WebPMux* mux) { + if (mux != NULL) { + MuxRelease(mux); + WebPSafeFree(mux); + } +} + +//------------------------------------------------------------------------------ +// Helper method(s). + +// Handy MACRO, makes MuxSet() very symmetric to MuxGet(). +#define SWITCH_ID_LIST(INDEX, LIST) \ + if (idx == (INDEX)) { \ + err = ChunkAssignData(&chunk, data, copy_data, tag); \ + if (err == WEBP_MUX_OK) { \ + err = ChunkSetHead(&chunk, (LIST)); \ + if (err != WEBP_MUX_OK) ChunkRelease(&chunk); \ + } \ + return err; \ + } + +static WebPMuxError MuxSet(WebPMux* const mux, uint32_t tag, + const WebPData* const data, int copy_data) { + WebPChunk chunk; + WebPMuxError err = WEBP_MUX_NOT_FOUND; + const CHUNK_INDEX idx = ChunkGetIndexFromTag(tag); + assert(mux != NULL); + assert(!IsWPI(kChunks[idx].id)); + + ChunkInit(&chunk); + SWITCH_ID_LIST(IDX_VP8X, &mux->vp8x_); + SWITCH_ID_LIST(IDX_ICCP, &mux->iccp_); + SWITCH_ID_LIST(IDX_ANIM, &mux->anim_); + SWITCH_ID_LIST(IDX_EXIF, &mux->exif_); + SWITCH_ID_LIST(IDX_XMP, &mux->xmp_); + SWITCH_ID_LIST(IDX_UNKNOWN, &mux->unknown_); + return err; +} +#undef SWITCH_ID_LIST + +// Create data for frame given image data, offsets and duration. +static WebPMuxError CreateFrameData( + int width, int height, const WebPMuxFrameInfo* const info, + WebPData* const frame) { + uint8_t* frame_bytes; + const size_t frame_size = kChunks[IDX_ANMF].size; + + assert(width > 0 && height > 0 && info->duration >= 0); + assert(info->dispose_method == (info->dispose_method & 1)); + // Note: assertion on upper bounds is done in PutLE24(). + + frame_bytes = (uint8_t*)WebPSafeMalloc(1ULL, frame_size); + if (frame_bytes == NULL) return WEBP_MUX_MEMORY_ERROR; + + PutLE24(frame_bytes + 0, info->x_offset / 2); + PutLE24(frame_bytes + 3, info->y_offset / 2); + + PutLE24(frame_bytes + 6, width - 1); + PutLE24(frame_bytes + 9, height - 1); + PutLE24(frame_bytes + 12, info->duration); + frame_bytes[15] = + (info->blend_method == WEBP_MUX_NO_BLEND ? 2 : 0) | + (info->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND ? 1 : 0); + + frame->bytes = frame_bytes; + frame->size = frame_size; + return WEBP_MUX_OK; +} + +// Outputs image data given a bitstream. The bitstream can either be a +// single-image WebP file or raw VP8/VP8L data. +// Also outputs 'is_lossless' to be true if the given bitstream is lossless. +static WebPMuxError GetImageData(const WebPData* const bitstream, + WebPData* const image, WebPData* const alpha, + int* const is_lossless) { + WebPDataInit(alpha); // Default: no alpha. + if (bitstream->size < TAG_SIZE || + memcmp(bitstream->bytes, "RIFF", TAG_SIZE)) { + // It is NOT webp file data. Return input data as is. + *image = *bitstream; + } else { + // It is webp file data. Extract image data from it. + const WebPMuxImage* wpi; + WebPMux* const mux = WebPMuxCreate(bitstream, 0); + if (mux == NULL) return WEBP_MUX_BAD_DATA; + wpi = mux->images_; + assert(wpi != NULL && wpi->img_ != NULL); + *image = wpi->img_->data_; + if (wpi->alpha_ != NULL) { + *alpha = wpi->alpha_->data_; + } + WebPMuxDelete(mux); + } + *is_lossless = VP8LCheckSignature(image->bytes, image->size); + return WEBP_MUX_OK; +} + +static WebPMuxError DeleteChunks(WebPChunk** chunk_list, uint32_t tag) { + WebPMuxError err = WEBP_MUX_NOT_FOUND; + assert(chunk_list); + while (*chunk_list) { + WebPChunk* const chunk = *chunk_list; + if (chunk->tag_ == tag) { + *chunk_list = ChunkDelete(chunk); + err = WEBP_MUX_OK; + } else { + chunk_list = &chunk->next_; + } + } + return err; +} + +static WebPMuxError MuxDeleteAllNamedData(WebPMux* const mux, uint32_t tag) { + const WebPChunkId id = ChunkGetIdFromTag(tag); + assert(mux != NULL); + if (IsWPI(id)) return WEBP_MUX_INVALID_ARGUMENT; + return DeleteChunks(MuxGetChunkListFromId(mux, id), tag); +} + +//------------------------------------------------------------------------------ +// Set API(s). + +WebPMuxError WebPMuxSetChunk(WebPMux* mux, const char fourcc[4], + const WebPData* chunk_data, int copy_data) { + uint32_t tag; + WebPMuxError err; + if (mux == NULL || fourcc == NULL || chunk_data == NULL || + chunk_data->bytes == NULL || chunk_data->size > MAX_CHUNK_PAYLOAD) { + return WEBP_MUX_INVALID_ARGUMENT; + } + tag = ChunkGetTagFromFourCC(fourcc); + + // Delete existing chunk(s) with the same 'fourcc'. + err = MuxDeleteAllNamedData(mux, tag); + if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err; + + // Add the given chunk. + return MuxSet(mux, tag, chunk_data, copy_data); +} + +// Creates a chunk from given 'data' and sets it as 1st chunk in 'chunk_list'. +static WebPMuxError AddDataToChunkList( + const WebPData* const data, int copy_data, uint32_t tag, + WebPChunk** chunk_list) { + WebPChunk chunk; + WebPMuxError err; + ChunkInit(&chunk); + err = ChunkAssignData(&chunk, data, copy_data, tag); + if (err != WEBP_MUX_OK) goto Err; + err = ChunkSetHead(&chunk, chunk_list); + if (err != WEBP_MUX_OK) goto Err; + return WEBP_MUX_OK; + Err: + ChunkRelease(&chunk); + return err; +} + +// Extracts image & alpha data from the given bitstream and then sets wpi.alpha_ +// and wpi.img_ appropriately. +static WebPMuxError SetAlphaAndImageChunks( + const WebPData* const bitstream, int copy_data, WebPMuxImage* const wpi) { + int is_lossless = 0; + WebPData image, alpha; + WebPMuxError err = GetImageData(bitstream, &image, &alpha, &is_lossless); + const int image_tag = + is_lossless ? kChunks[IDX_VP8L].tag : kChunks[IDX_VP8].tag; + if (err != WEBP_MUX_OK) return err; + if (alpha.bytes != NULL) { + err = AddDataToChunkList(&alpha, copy_data, kChunks[IDX_ALPHA].tag, + &wpi->alpha_); + if (err != WEBP_MUX_OK) return err; + } + err = AddDataToChunkList(&image, copy_data, image_tag, &wpi->img_); + if (err != WEBP_MUX_OK) return err; + return MuxImageFinalize(wpi) ? WEBP_MUX_OK : WEBP_MUX_INVALID_ARGUMENT; +} + +WebPMuxError WebPMuxSetImage(WebPMux* mux, const WebPData* bitstream, + int copy_data) { + WebPMuxImage wpi; + WebPMuxError err; + + if (mux == NULL || bitstream == NULL || bitstream->bytes == NULL || + bitstream->size > MAX_CHUNK_PAYLOAD) { + return WEBP_MUX_INVALID_ARGUMENT; + } + + if (mux->images_ != NULL) { + // Only one 'simple image' can be added in mux. So, remove present images. + DeleteAllImages(&mux->images_); + } + + MuxImageInit(&wpi); + err = SetAlphaAndImageChunks(bitstream, copy_data, &wpi); + if (err != WEBP_MUX_OK) goto Err; + + // Add this WebPMuxImage to mux. + err = MuxImagePush(&wpi, &mux->images_); + if (err != WEBP_MUX_OK) goto Err; + + // All is well. + return WEBP_MUX_OK; + + Err: // Something bad happened. + MuxImageRelease(&wpi); + return err; +} + +WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPMuxFrameInfo* info, + int copy_data) { + WebPMuxImage wpi; + WebPMuxError err; + + if (mux == NULL || info == NULL) return WEBP_MUX_INVALID_ARGUMENT; + + if (info->id != WEBP_CHUNK_ANMF) return WEBP_MUX_INVALID_ARGUMENT; + + if (info->bitstream.bytes == NULL || + info->bitstream.size > MAX_CHUNK_PAYLOAD) { + return WEBP_MUX_INVALID_ARGUMENT; + } + + if (mux->images_ != NULL) { + const WebPMuxImage* const image = mux->images_; + const uint32_t image_id = (image->header_ != NULL) ? + ChunkGetIdFromTag(image->header_->tag_) : WEBP_CHUNK_IMAGE; + if (image_id != info->id) { + return WEBP_MUX_INVALID_ARGUMENT; // Conflicting frame types. + } + } + + MuxImageInit(&wpi); + err = SetAlphaAndImageChunks(&info->bitstream, copy_data, &wpi); + if (err != WEBP_MUX_OK) goto Err; + assert(wpi.img_ != NULL); // As SetAlphaAndImageChunks() was successful. + + { + WebPData frame; + const uint32_t tag = kChunks[IDX_ANMF].tag; + WebPMuxFrameInfo tmp = *info; + tmp.x_offset &= ~1; // Snap offsets to even. + tmp.y_offset &= ~1; + if (tmp.x_offset < 0 || tmp.x_offset >= MAX_POSITION_OFFSET || + tmp.y_offset < 0 || tmp.y_offset >= MAX_POSITION_OFFSET || + (tmp.duration < 0 || tmp.duration >= MAX_DURATION) || + tmp.dispose_method != (tmp.dispose_method & 1)) { + err = WEBP_MUX_INVALID_ARGUMENT; + goto Err; + } + err = CreateFrameData(wpi.width_, wpi.height_, &tmp, &frame); + if (err != WEBP_MUX_OK) goto Err; + // Add frame chunk (with copy_data = 1). + err = AddDataToChunkList(&frame, 1, tag, &wpi.header_); + WebPDataClear(&frame); // frame owned by wpi.header_ now. + if (err != WEBP_MUX_OK) goto Err; + } + + // Add this WebPMuxImage to mux. + err = MuxImagePush(&wpi, &mux->images_); + if (err != WEBP_MUX_OK) goto Err; + + // All is well. + return WEBP_MUX_OK; + + Err: // Something bad happened. + MuxImageRelease(&wpi); + return err; +} + +WebPMuxError WebPMuxSetAnimationParams(WebPMux* mux, + const WebPMuxAnimParams* params) { + WebPMuxError err; + uint8_t data[ANIM_CHUNK_SIZE]; + const WebPData anim = { data, ANIM_CHUNK_SIZE }; + + if (mux == NULL || params == NULL) return WEBP_MUX_INVALID_ARGUMENT; + if (params->loop_count < 0 || params->loop_count >= MAX_LOOP_COUNT) { + return WEBP_MUX_INVALID_ARGUMENT; + } + + // Delete any existing ANIM chunk(s). + err = MuxDeleteAllNamedData(mux, kChunks[IDX_ANIM].tag); + if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err; + + // Set the animation parameters. + PutLE32(data, params->bgcolor); + PutLE16(data + 4, params->loop_count); + return MuxSet(mux, kChunks[IDX_ANIM].tag, &anim, 1); +} + +WebPMuxError WebPMuxSetCanvasSize(WebPMux* mux, + int width, int height) { + WebPMuxError err; + if (mux == NULL) { + return WEBP_MUX_INVALID_ARGUMENT; + } + if (width < 0 || height < 0 || + width > MAX_CANVAS_SIZE || height > MAX_CANVAS_SIZE) { + return WEBP_MUX_INVALID_ARGUMENT; + } + if (width * (uint64_t)height >= MAX_IMAGE_AREA) { + return WEBP_MUX_INVALID_ARGUMENT; + } + if ((width * height) == 0 && (width | height) != 0) { + // one of width / height is zero, but not both -> invalid! + return WEBP_MUX_INVALID_ARGUMENT; + } + // If we already assembled a VP8X chunk, invalidate it. + err = MuxDeleteAllNamedData(mux, kChunks[IDX_VP8X].tag); + if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err; + + mux->canvas_width_ = width; + mux->canvas_height_ = height; + return WEBP_MUX_OK; +} + +//------------------------------------------------------------------------------ +// Delete API(s). + +WebPMuxError WebPMuxDeleteChunk(WebPMux* mux, const char fourcc[4]) { + if (mux == NULL || fourcc == NULL) return WEBP_MUX_INVALID_ARGUMENT; + return MuxDeleteAllNamedData(mux, ChunkGetTagFromFourCC(fourcc)); +} + +WebPMuxError WebPMuxDeleteFrame(WebPMux* mux, uint32_t nth) { + if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT; + return MuxImageDeleteNth(&mux->images_, nth); +} + +//------------------------------------------------------------------------------ +// Assembly of the WebP RIFF file. + +static WebPMuxError GetFrameInfo( + const WebPChunk* const frame_chunk, + int* const x_offset, int* const y_offset, int* const duration) { + const WebPData* const data = &frame_chunk->data_; + const size_t expected_data_size = ANMF_CHUNK_SIZE; + assert(frame_chunk->tag_ == kChunks[IDX_ANMF].tag); + assert(frame_chunk != NULL); + if (data->size != expected_data_size) return WEBP_MUX_INVALID_ARGUMENT; + + *x_offset = 2 * GetLE24(data->bytes + 0); + *y_offset = 2 * GetLE24(data->bytes + 3); + *duration = GetLE24(data->bytes + 12); + return WEBP_MUX_OK; +} + +static WebPMuxError GetImageInfo(const WebPMuxImage* const wpi, + int* const x_offset, int* const y_offset, + int* const duration, + int* const width, int* const height) { + const WebPChunk* const frame_chunk = wpi->header_; + WebPMuxError err; + assert(wpi != NULL); + assert(frame_chunk != NULL); + + // Get offsets and duration from ANMF chunk. + err = GetFrameInfo(frame_chunk, x_offset, y_offset, duration); + if (err != WEBP_MUX_OK) return err; + + // Get width and height from VP8/VP8L chunk. + if (width != NULL) *width = wpi->width_; + if (height != NULL) *height = wpi->height_; + return WEBP_MUX_OK; +} + +// Returns the tightest dimension for the canvas considering the image list. +static WebPMuxError GetAdjustedCanvasSize(const WebPMux* const mux, + int* const width, int* const height) { + WebPMuxImage* wpi = NULL; + assert(mux != NULL); + assert(width != NULL && height != NULL); + + wpi = mux->images_; + assert(wpi != NULL); + assert(wpi->img_ != NULL); + + if (wpi->next_ != NULL) { + int max_x = 0, max_y = 0; + // if we have a chain of wpi's, header_ is necessarily set + assert(wpi->header_ != NULL); + // Aggregate the bounding box for animation frames. + for (; wpi != NULL; wpi = wpi->next_) { + int x_offset = 0, y_offset = 0, duration = 0, w = 0, h = 0; + const WebPMuxError err = GetImageInfo(wpi, &x_offset, &y_offset, + &duration, &w, &h); + const int max_x_pos = x_offset + w; + const int max_y_pos = y_offset + h; + if (err != WEBP_MUX_OK) return err; + assert(x_offset < MAX_POSITION_OFFSET); + assert(y_offset < MAX_POSITION_OFFSET); + + if (max_x_pos > max_x) max_x = max_x_pos; + if (max_y_pos > max_y) max_y = max_y_pos; + } + *width = max_x; + *height = max_y; + } else { + // For a single image, canvas dimensions are same as image dimensions. + *width = wpi->width_; + *height = wpi->height_; + } + return WEBP_MUX_OK; +} + +// VP8X format: +// Total Size : 10, +// Flags : 4 bytes, +// Width : 3 bytes, +// Height : 3 bytes. +static WebPMuxError CreateVP8XChunk(WebPMux* const mux) { + WebPMuxError err = WEBP_MUX_OK; + uint32_t flags = 0; + int width = 0; + int height = 0; + uint8_t data[VP8X_CHUNK_SIZE]; + const WebPData vp8x = { data, VP8X_CHUNK_SIZE }; + const WebPMuxImage* images = NULL; + + assert(mux != NULL); + images = mux->images_; // First image. + if (images == NULL || images->img_ == NULL || + images->img_->data_.bytes == NULL) { + return WEBP_MUX_INVALID_ARGUMENT; + } + + // If VP8X chunk(s) is(are) already present, remove them (and later add new + // VP8X chunk with updated flags). + err = MuxDeleteAllNamedData(mux, kChunks[IDX_VP8X].tag); + if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err; + + // Set flags. + if (mux->iccp_ != NULL && mux->iccp_->data_.bytes != NULL) { + flags |= ICCP_FLAG; + } + if (mux->exif_ != NULL && mux->exif_->data_.bytes != NULL) { + flags |= EXIF_FLAG; + } + if (mux->xmp_ != NULL && mux->xmp_->data_.bytes != NULL) { + flags |= XMP_FLAG; + } + if (images->header_ != NULL) { + if (images->header_->tag_ == kChunks[IDX_ANMF].tag) { + // This is an image with animation. + flags |= ANIMATION_FLAG; + } + } + if (MuxImageCount(images, WEBP_CHUNK_ALPHA) > 0) { + flags |= ALPHA_FLAG; // Some images have an alpha channel. + } + + err = GetAdjustedCanvasSize(mux, &width, &height); + if (err != WEBP_MUX_OK) return err; + + if (width <= 0 || height <= 0) { + return WEBP_MUX_INVALID_ARGUMENT; + } + if (width > MAX_CANVAS_SIZE || height > MAX_CANVAS_SIZE) { + return WEBP_MUX_INVALID_ARGUMENT; + } + + if (mux->canvas_width_ != 0 || mux->canvas_height_ != 0) { + if (width > mux->canvas_width_ || height > mux->canvas_height_) { + return WEBP_MUX_INVALID_ARGUMENT; + } + width = mux->canvas_width_; + height = mux->canvas_height_; + } + + if (flags == 0 && mux->unknown_ == NULL) { + // For simple file format, VP8X chunk should not be added. + return WEBP_MUX_OK; + } + + if (MuxHasAlpha(images)) { + // This means some frames explicitly/implicitly contain alpha. + // Note: This 'flags' update must NOT be done for a lossless image + // without a VP8X chunk! + flags |= ALPHA_FLAG; + } + + PutLE32(data + 0, flags); // VP8X chunk flags. + PutLE24(data + 4, width - 1); // canvas width. + PutLE24(data + 7, height - 1); // canvas height. + + return MuxSet(mux, kChunks[IDX_VP8X].tag, &vp8x, 1); +} + +// Cleans up 'mux' by removing any unnecessary chunks. +static WebPMuxError MuxCleanup(WebPMux* const mux) { + int num_frames; + int num_anim_chunks; + + // If we have an image with a single frame, and its rectangle + // covers the whole canvas, convert it to a non-animated image + // (to avoid writing ANMF chunk unnecessarily). + WebPMuxError err = WebPMuxNumChunks(mux, kChunks[IDX_ANMF].id, &num_frames); + if (err != WEBP_MUX_OK) return err; + if (num_frames == 1) { + WebPMuxImage* frame = NULL; + err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, 1, &frame); + if (err != WEBP_MUX_OK) return err; + // We know that one frame does exist. + assert(frame != NULL); + if (frame->header_ != NULL && + ((mux->canvas_width_ == 0 && mux->canvas_height_ == 0) || + (frame->width_ == mux->canvas_width_ && + frame->height_ == mux->canvas_height_))) { + assert(frame->header_->tag_ == kChunks[IDX_ANMF].tag); + ChunkDelete(frame->header_); // Removes ANMF chunk. + frame->header_ = NULL; + num_frames = 0; + } + } + // Remove ANIM chunk if this is a non-animated image. + err = WebPMuxNumChunks(mux, kChunks[IDX_ANIM].id, &num_anim_chunks); + if (err != WEBP_MUX_OK) return err; + if (num_anim_chunks >= 1 && num_frames == 0) { + err = MuxDeleteAllNamedData(mux, kChunks[IDX_ANIM].tag); + if (err != WEBP_MUX_OK) return err; + } + return WEBP_MUX_OK; +} + +// Total size of a list of images. +static size_t ImageListDiskSize(const WebPMuxImage* wpi_list) { + size_t size = 0; + while (wpi_list != NULL) { + size += MuxImageDiskSize(wpi_list); + wpi_list = wpi_list->next_; + } + return size; +} + +// Write out the given list of images into 'dst'. +static uint8_t* ImageListEmit(const WebPMuxImage* wpi_list, uint8_t* dst) { + while (wpi_list != NULL) { + dst = MuxImageEmit(wpi_list, dst); + wpi_list = wpi_list->next_; + } + return dst; +} + +WebPMuxError WebPMuxAssemble(WebPMux* mux, WebPData* assembled_data) { + size_t size = 0; + uint8_t* data = NULL; + uint8_t* dst = NULL; + WebPMuxError err; + + if (assembled_data == NULL) { + return WEBP_MUX_INVALID_ARGUMENT; + } + // Clean up returned data, in case something goes wrong. + memset(assembled_data, 0, sizeof(*assembled_data)); + + if (mux == NULL) { + return WEBP_MUX_INVALID_ARGUMENT; + } + + // Finalize mux. + err = MuxCleanup(mux); + if (err != WEBP_MUX_OK) return err; + err = CreateVP8XChunk(mux); + if (err != WEBP_MUX_OK) return err; + + // Allocate data. + size = ChunkListDiskSize(mux->vp8x_) + ChunkListDiskSize(mux->iccp_) + + ChunkListDiskSize(mux->anim_) + ImageListDiskSize(mux->images_) + + ChunkListDiskSize(mux->exif_) + ChunkListDiskSize(mux->xmp_) + + ChunkListDiskSize(mux->unknown_) + RIFF_HEADER_SIZE; + + data = (uint8_t*)WebPSafeMalloc(1ULL, size); + if (data == NULL) return WEBP_MUX_MEMORY_ERROR; + + // Emit header & chunks. + dst = MuxEmitRiffHeader(data, size); + dst = ChunkListEmit(mux->vp8x_, dst); + dst = ChunkListEmit(mux->iccp_, dst); + dst = ChunkListEmit(mux->anim_, dst); + dst = ImageListEmit(mux->images_, dst); + dst = ChunkListEmit(mux->exif_, dst); + dst = ChunkListEmit(mux->xmp_, dst); + dst = ChunkListEmit(mux->unknown_, dst); + assert(dst == data + size); + + // Validate mux. + err = MuxValidate(mux); + if (err != WEBP_MUX_OK) { + WebPSafeFree(data); + data = NULL; + size = 0; + } + + // Finalize data. + assembled_data->bytes = data; + assembled_data->size = size; + + return err; +} + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/src/mux/muxi.h b/third-party/webp/libwebp/src/mux/muxi.h new file mode 100644 index 0000000000..afc5954353 --- /dev/null +++ b/third-party/webp/libwebp/src/mux/muxi.h @@ -0,0 +1,234 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Internal header for mux library. +// +// Author: Urvang (urvang@google.com) + +#ifndef WEBP_MUX_MUXI_H_ +#define WEBP_MUX_MUXI_H_ + +#include +#include +#include "src/dec/vp8i_dec.h" +#include "src/dec/vp8li_dec.h" +#include "src/webp/mux.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//------------------------------------------------------------------------------ +// Defines and constants. + +#define MUX_MAJ_VERSION 1 +#define MUX_MIN_VERSION 3 +#define MUX_REV_VERSION 2 + +// Chunk object. +typedef struct WebPChunk WebPChunk; +struct WebPChunk { + uint32_t tag_; + int owner_; // True if *data_ memory is owned internally. + // VP8X, ANIM, and other internally created chunks + // like ANMF are always owned. + WebPData data_; + WebPChunk* next_; +}; + +// MuxImage object. Store a full WebP image (including ANMF chunk, ALPH +// chunk and VP8/VP8L chunk), +typedef struct WebPMuxImage WebPMuxImage; +struct WebPMuxImage { + WebPChunk* header_; // Corresponds to WEBP_CHUNK_ANMF. + WebPChunk* alpha_; // Corresponds to WEBP_CHUNK_ALPHA. + WebPChunk* img_; // Corresponds to WEBP_CHUNK_IMAGE. + WebPChunk* unknown_; // Corresponds to WEBP_CHUNK_UNKNOWN. + int width_; + int height_; + int has_alpha_; // Through ALPH chunk or as part of VP8L. + int is_partial_; // True if only some of the chunks are filled. + WebPMuxImage* next_; +}; + +// Main mux object. Stores data chunks. +struct WebPMux { + WebPMuxImage* images_; + WebPChunk* iccp_; + WebPChunk* exif_; + WebPChunk* xmp_; + WebPChunk* anim_; + WebPChunk* vp8x_; + + WebPChunk* unknown_; + int canvas_width_; + int canvas_height_; +}; + +// CHUNK_INDEX enum: used for indexing within 'kChunks' (defined below) only. +// Note: the reason for having two enums ('WebPChunkId' and 'CHUNK_INDEX') is to +// allow two different chunks to have the same id (e.g. WebPChunkId +// 'WEBP_CHUNK_IMAGE' can correspond to CHUNK_INDEX 'IDX_VP8' or 'IDX_VP8L'). +typedef enum { + IDX_VP8X = 0, + IDX_ICCP, + IDX_ANIM, + IDX_ANMF, + IDX_ALPHA, + IDX_VP8, + IDX_VP8L, + IDX_EXIF, + IDX_XMP, + IDX_UNKNOWN, + + IDX_NIL, + IDX_LAST_CHUNK +} CHUNK_INDEX; + +#define NIL_TAG 0x00000000u // To signal void chunk. + +typedef struct { + uint32_t tag; + WebPChunkId id; + uint32_t size; +} ChunkInfo; + +extern const ChunkInfo kChunks[IDX_LAST_CHUNK]; + +//------------------------------------------------------------------------------ +// Chunk object management. + +// Initialize. +void ChunkInit(WebPChunk* const chunk); + +// Get chunk index from chunk tag. Returns IDX_UNKNOWN if not found. +CHUNK_INDEX ChunkGetIndexFromTag(uint32_t tag); + +// Get chunk id from chunk tag. Returns WEBP_CHUNK_UNKNOWN if not found. +WebPChunkId ChunkGetIdFromTag(uint32_t tag); + +// Convert a fourcc string to a tag. +uint32_t ChunkGetTagFromFourCC(const char fourcc[4]); + +// Get chunk index from fourcc. Returns IDX_UNKNOWN if given fourcc is unknown. +CHUNK_INDEX ChunkGetIndexFromFourCC(const char fourcc[4]); + +// Search for nth chunk with given 'tag' in the chunk list. +// nth = 0 means "last of the list". +WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag); + +// Fill the chunk with the given data. +WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data, + int copy_data, uint32_t tag); + +// Sets 'chunk' as the only element in 'chunk_list' if it is empty. +// On success ownership is transferred from 'chunk' to the 'chunk_list'. +WebPMuxError ChunkSetHead(WebPChunk* const chunk, WebPChunk** const chunk_list); +// Sets 'chunk' at last position in the 'chunk_list'. +// On success ownership is transferred from 'chunk' to the 'chunk_list'. +// *chunk_list also points towards the last valid element of the initial +// *chunk_list. +WebPMuxError ChunkAppend(WebPChunk* const chunk, WebPChunk*** const chunk_list); + +// Releases chunk and returns chunk->next_. +WebPChunk* ChunkRelease(WebPChunk* const chunk); + +// Deletes given chunk & returns chunk->next_. +WebPChunk* ChunkDelete(WebPChunk* const chunk); + +// Deletes all chunks in the given chunk list. +void ChunkListDelete(WebPChunk** const chunk_list); + +// Returns size of the chunk including chunk header and padding byte (if any). +static WEBP_INLINE size_t SizeWithPadding(size_t chunk_size) { + assert(chunk_size <= MAX_CHUNK_PAYLOAD); + return CHUNK_HEADER_SIZE + ((chunk_size + 1) & ~1U); +} + +// Size of a chunk including header and padding. +static WEBP_INLINE size_t ChunkDiskSize(const WebPChunk* chunk) { + const size_t data_size = chunk->data_.size; + return SizeWithPadding(data_size); +} + +// Total size of a list of chunks. +size_t ChunkListDiskSize(const WebPChunk* chunk_list); + +// Write out the given list of chunks into 'dst'. +uint8_t* ChunkListEmit(const WebPChunk* chunk_list, uint8_t* dst); + +//------------------------------------------------------------------------------ +// MuxImage object management. + +// Initialize. +void MuxImageInit(WebPMuxImage* const wpi); + +// Releases image 'wpi' and returns wpi->next. +WebPMuxImage* MuxImageRelease(WebPMuxImage* const wpi); + +// Delete image 'wpi' and return the next image in the list or NULL. +// 'wpi' can be NULL. +WebPMuxImage* MuxImageDelete(WebPMuxImage* const wpi); + +// Count number of images matching the given tag id in the 'wpi_list'. +// If id == WEBP_CHUNK_NIL, all images will be matched. +int MuxImageCount(const WebPMuxImage* wpi_list, WebPChunkId id); + +// Update width/height/has_alpha info from chunks within wpi. +// Also remove ALPH chunk if not needed. +int MuxImageFinalize(WebPMuxImage* const wpi); + +// Check if given ID corresponds to an image related chunk. +static WEBP_INLINE int IsWPI(WebPChunkId id) { + switch (id) { + case WEBP_CHUNK_ANMF: + case WEBP_CHUNK_ALPHA: + case WEBP_CHUNK_IMAGE: return 1; + default: return 0; + } +} + +// Pushes 'wpi' at the end of 'wpi_list'. +WebPMuxError MuxImagePush(const WebPMuxImage* wpi, WebPMuxImage** wpi_list); + +// Delete nth image in the image list. +WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth); + +// Get nth image in the image list. +WebPMuxError MuxImageGetNth(const WebPMuxImage** wpi_list, uint32_t nth, + WebPMuxImage** wpi); + +// Total size of the given image. +size_t MuxImageDiskSize(const WebPMuxImage* const wpi); + +// Write out the given image into 'dst'. +uint8_t* MuxImageEmit(const WebPMuxImage* const wpi, uint8_t* dst); + +//------------------------------------------------------------------------------ +// Helper methods for mux. + +// Checks if the given image list contains at least one image with alpha. +int MuxHasAlpha(const WebPMuxImage* images); + +// Write out RIFF header into 'data', given total data size 'size'. +uint8_t* MuxEmitRiffHeader(uint8_t* const data, size_t size); + +// Returns the list where chunk with given ID is to be inserted in mux. +WebPChunk** MuxGetChunkListFromId(const WebPMux* mux, WebPChunkId id); + +// Validates the given mux object. +WebPMuxError MuxValidate(const WebPMux* const mux); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_MUX_MUXI_H_ diff --git a/third-party/webp/libwebp/src/mux/muxinternal.c b/third-party/webp/libwebp/src/mux/muxinternal.c new file mode 100644 index 0000000000..75b6b416b9 --- /dev/null +++ b/third-party/webp/libwebp/src/mux/muxinternal.c @@ -0,0 +1,549 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Internal objects and utils for mux. +// +// Authors: Urvang (urvang@google.com) +// Vikas (vikasa@google.com) + +#include +#include "src/mux/muxi.h" +#include "src/utils/utils.h" + +#define UNDEFINED_CHUNK_SIZE ((uint32_t)(-1)) + +const ChunkInfo kChunks[] = { + { MKFOURCC('V', 'P', '8', 'X'), WEBP_CHUNK_VP8X, VP8X_CHUNK_SIZE }, + { MKFOURCC('I', 'C', 'C', 'P'), WEBP_CHUNK_ICCP, UNDEFINED_CHUNK_SIZE }, + { MKFOURCC('A', 'N', 'I', 'M'), WEBP_CHUNK_ANIM, ANIM_CHUNK_SIZE }, + { MKFOURCC('A', 'N', 'M', 'F'), WEBP_CHUNK_ANMF, ANMF_CHUNK_SIZE }, + { MKFOURCC('A', 'L', 'P', 'H'), WEBP_CHUNK_ALPHA, UNDEFINED_CHUNK_SIZE }, + { MKFOURCC('V', 'P', '8', ' '), WEBP_CHUNK_IMAGE, UNDEFINED_CHUNK_SIZE }, + { MKFOURCC('V', 'P', '8', 'L'), WEBP_CHUNK_IMAGE, UNDEFINED_CHUNK_SIZE }, + { MKFOURCC('E', 'X', 'I', 'F'), WEBP_CHUNK_EXIF, UNDEFINED_CHUNK_SIZE }, + { MKFOURCC('X', 'M', 'P', ' '), WEBP_CHUNK_XMP, UNDEFINED_CHUNK_SIZE }, + { NIL_TAG, WEBP_CHUNK_UNKNOWN, UNDEFINED_CHUNK_SIZE }, + + { NIL_TAG, WEBP_CHUNK_NIL, UNDEFINED_CHUNK_SIZE } +}; + +//------------------------------------------------------------------------------ + +int WebPGetMuxVersion(void) { + return (MUX_MAJ_VERSION << 16) | (MUX_MIN_VERSION << 8) | MUX_REV_VERSION; +} + +//------------------------------------------------------------------------------ +// Life of a chunk object. + +void ChunkInit(WebPChunk* const chunk) { + assert(chunk); + memset(chunk, 0, sizeof(*chunk)); + chunk->tag_ = NIL_TAG; +} + +WebPChunk* ChunkRelease(WebPChunk* const chunk) { + WebPChunk* next; + if (chunk == NULL) return NULL; + if (chunk->owner_) { + WebPDataClear(&chunk->data_); + } + next = chunk->next_; + ChunkInit(chunk); + return next; +} + +//------------------------------------------------------------------------------ +// Chunk misc methods. + +CHUNK_INDEX ChunkGetIndexFromTag(uint32_t tag) { + int i; + for (i = 0; kChunks[i].tag != NIL_TAG; ++i) { + if (tag == kChunks[i].tag) return (CHUNK_INDEX)i; + } + return IDX_UNKNOWN; +} + +WebPChunkId ChunkGetIdFromTag(uint32_t tag) { + int i; + for (i = 0; kChunks[i].tag != NIL_TAG; ++i) { + if (tag == kChunks[i].tag) return kChunks[i].id; + } + return WEBP_CHUNK_UNKNOWN; +} + +uint32_t ChunkGetTagFromFourCC(const char fourcc[4]) { + return MKFOURCC(fourcc[0], fourcc[1], fourcc[2], fourcc[3]); +} + +CHUNK_INDEX ChunkGetIndexFromFourCC(const char fourcc[4]) { + const uint32_t tag = ChunkGetTagFromFourCC(fourcc); + return ChunkGetIndexFromTag(tag); +} + +//------------------------------------------------------------------------------ +// Chunk search methods. + +// Returns next chunk in the chunk list with the given tag. +static WebPChunk* ChunkSearchNextInList(WebPChunk* chunk, uint32_t tag) { + while (chunk != NULL && chunk->tag_ != tag) { + chunk = chunk->next_; + } + return chunk; +} + +WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag) { + uint32_t iter = nth; + first = ChunkSearchNextInList(first, tag); + if (first == NULL) return NULL; + + while (--iter != 0) { + WebPChunk* next_chunk = ChunkSearchNextInList(first->next_, tag); + if (next_chunk == NULL) break; + first = next_chunk; + } + return ((nth > 0) && (iter > 0)) ? NULL : first; +} + +//------------------------------------------------------------------------------ +// Chunk writer methods. + +WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data, + int copy_data, uint32_t tag) { + // For internally allocated chunks, always copy data & make it owner of data. + if (tag == kChunks[IDX_VP8X].tag || tag == kChunks[IDX_ANIM].tag) { + copy_data = 1; + } + + ChunkRelease(chunk); + + if (data != NULL) { + if (copy_data) { // Copy data. + if (!WebPDataCopy(data, &chunk->data_)) return WEBP_MUX_MEMORY_ERROR; + chunk->owner_ = 1; // Chunk is owner of data. + } else { // Don't copy data. + chunk->data_ = *data; + } + } + chunk->tag_ = tag; + return WEBP_MUX_OK; +} + +WebPMuxError ChunkSetHead(WebPChunk* const chunk, + WebPChunk** const chunk_list) { + WebPChunk* new_chunk; + + assert(chunk_list != NULL); + if (*chunk_list != NULL) { + return WEBP_MUX_NOT_FOUND; + } + + new_chunk = (WebPChunk*)WebPSafeMalloc(1ULL, sizeof(*new_chunk)); + if (new_chunk == NULL) return WEBP_MUX_MEMORY_ERROR; + *new_chunk = *chunk; + chunk->owner_ = 0; + new_chunk->next_ = NULL; + *chunk_list = new_chunk; + return WEBP_MUX_OK; +} + +WebPMuxError ChunkAppend(WebPChunk* const chunk, + WebPChunk*** const chunk_list) { + WebPMuxError err; + assert(chunk_list != NULL && *chunk_list != NULL); + + if (**chunk_list == NULL) { + err = ChunkSetHead(chunk, *chunk_list); + } else { + WebPChunk* last_chunk = **chunk_list; + while (last_chunk->next_ != NULL) last_chunk = last_chunk->next_; + err = ChunkSetHead(chunk, &last_chunk->next_); + if (err == WEBP_MUX_OK) *chunk_list = &last_chunk->next_; + } + return err; +} + +//------------------------------------------------------------------------------ +// Chunk deletion method(s). + +WebPChunk* ChunkDelete(WebPChunk* const chunk) { + WebPChunk* const next = ChunkRelease(chunk); + WebPSafeFree(chunk); + return next; +} + +void ChunkListDelete(WebPChunk** const chunk_list) { + while (*chunk_list != NULL) { + *chunk_list = ChunkDelete(*chunk_list); + } +} + +//------------------------------------------------------------------------------ +// Chunk serialization methods. + +static uint8_t* ChunkEmit(const WebPChunk* const chunk, uint8_t* dst) { + const size_t chunk_size = chunk->data_.size; + assert(chunk); + assert(chunk->tag_ != NIL_TAG); + PutLE32(dst + 0, chunk->tag_); + PutLE32(dst + TAG_SIZE, (uint32_t)chunk_size); + assert(chunk_size == (uint32_t)chunk_size); + memcpy(dst + CHUNK_HEADER_SIZE, chunk->data_.bytes, chunk_size); + if (chunk_size & 1) + dst[CHUNK_HEADER_SIZE + chunk_size] = 0; // Add padding. + return dst + ChunkDiskSize(chunk); +} + +uint8_t* ChunkListEmit(const WebPChunk* chunk_list, uint8_t* dst) { + while (chunk_list != NULL) { + dst = ChunkEmit(chunk_list, dst); + chunk_list = chunk_list->next_; + } + return dst; +} + +size_t ChunkListDiskSize(const WebPChunk* chunk_list) { + size_t size = 0; + while (chunk_list != NULL) { + size += ChunkDiskSize(chunk_list); + chunk_list = chunk_list->next_; + } + return size; +} + +//------------------------------------------------------------------------------ +// Life of a MuxImage object. + +void MuxImageInit(WebPMuxImage* const wpi) { + assert(wpi); + memset(wpi, 0, sizeof(*wpi)); +} + +WebPMuxImage* MuxImageRelease(WebPMuxImage* const wpi) { + WebPMuxImage* next; + if (wpi == NULL) return NULL; + // There should be at most one chunk of header_, alpha_, img_ but we call + // ChunkListDelete to be safe + ChunkListDelete(&wpi->header_); + ChunkListDelete(&wpi->alpha_); + ChunkListDelete(&wpi->img_); + ChunkListDelete(&wpi->unknown_); + + next = wpi->next_; + MuxImageInit(wpi); + return next; +} + +//------------------------------------------------------------------------------ +// MuxImage search methods. + +// Get a reference to appropriate chunk list within an image given chunk tag. +static WebPChunk** GetChunkListFromId(const WebPMuxImage* const wpi, + WebPChunkId id) { + assert(wpi != NULL); + switch (id) { + case WEBP_CHUNK_ANMF: return (WebPChunk**)&wpi->header_; + case WEBP_CHUNK_ALPHA: return (WebPChunk**)&wpi->alpha_; + case WEBP_CHUNK_IMAGE: return (WebPChunk**)&wpi->img_; + default: return NULL; + } +} + +int MuxImageCount(const WebPMuxImage* wpi_list, WebPChunkId id) { + int count = 0; + const WebPMuxImage* current; + for (current = wpi_list; current != NULL; current = current->next_) { + if (id == WEBP_CHUNK_NIL) { + ++count; // Special case: count all images. + } else { + const WebPChunk* const wpi_chunk = *GetChunkListFromId(current, id); + if (wpi_chunk != NULL) { + const WebPChunkId wpi_chunk_id = ChunkGetIdFromTag(wpi_chunk->tag_); + if (wpi_chunk_id == id) ++count; // Count images with a matching 'id'. + } + } + } + return count; +} + +// Outputs a pointer to 'prev_wpi->next_', +// where 'prev_wpi' is the pointer to the image at position (nth - 1). +// Returns true if nth image was found. +static int SearchImageToGetOrDelete(WebPMuxImage** wpi_list, uint32_t nth, + WebPMuxImage*** const location) { + uint32_t count = 0; + assert(wpi_list); + *location = wpi_list; + + if (nth == 0) { + nth = MuxImageCount(*wpi_list, WEBP_CHUNK_NIL); + if (nth == 0) return 0; // Not found. + } + + while (*wpi_list != NULL) { + WebPMuxImage* const cur_wpi = *wpi_list; + ++count; + if (count == nth) return 1; // Found. + wpi_list = &cur_wpi->next_; + *location = wpi_list; + } + return 0; // Not found. +} + +//------------------------------------------------------------------------------ +// MuxImage writer methods. + +WebPMuxError MuxImagePush(const WebPMuxImage* wpi, WebPMuxImage** wpi_list) { + WebPMuxImage* new_wpi; + + while (*wpi_list != NULL) { + WebPMuxImage* const cur_wpi = *wpi_list; + if (cur_wpi->next_ == NULL) break; + wpi_list = &cur_wpi->next_; + } + + new_wpi = (WebPMuxImage*)WebPSafeMalloc(1ULL, sizeof(*new_wpi)); + if (new_wpi == NULL) return WEBP_MUX_MEMORY_ERROR; + *new_wpi = *wpi; + new_wpi->next_ = NULL; + + if (*wpi_list != NULL) { + (*wpi_list)->next_ = new_wpi; + } else { + *wpi_list = new_wpi; + } + return WEBP_MUX_OK; +} + +//------------------------------------------------------------------------------ +// MuxImage deletion methods. + +WebPMuxImage* MuxImageDelete(WebPMuxImage* const wpi) { + // Delete the components of wpi. If wpi is NULL this is a noop. + WebPMuxImage* const next = MuxImageRelease(wpi); + WebPSafeFree(wpi); + return next; +} + +WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth) { + assert(wpi_list); + if (!SearchImageToGetOrDelete(wpi_list, nth, &wpi_list)) { + return WEBP_MUX_NOT_FOUND; + } + *wpi_list = MuxImageDelete(*wpi_list); + return WEBP_MUX_OK; +} + +//------------------------------------------------------------------------------ +// MuxImage reader methods. + +WebPMuxError MuxImageGetNth(const WebPMuxImage** wpi_list, uint32_t nth, + WebPMuxImage** wpi) { + assert(wpi_list); + assert(wpi); + if (!SearchImageToGetOrDelete((WebPMuxImage**)wpi_list, nth, + (WebPMuxImage***)&wpi_list)) { + return WEBP_MUX_NOT_FOUND; + } + *wpi = (WebPMuxImage*)*wpi_list; + return WEBP_MUX_OK; +} + +//------------------------------------------------------------------------------ +// MuxImage serialization methods. + +// Size of an image. +size_t MuxImageDiskSize(const WebPMuxImage* const wpi) { + size_t size = 0; + if (wpi->header_ != NULL) size += ChunkDiskSize(wpi->header_); + if (wpi->alpha_ != NULL) size += ChunkDiskSize(wpi->alpha_); + if (wpi->img_ != NULL) size += ChunkDiskSize(wpi->img_); + if (wpi->unknown_ != NULL) size += ChunkListDiskSize(wpi->unknown_); + return size; +} + +// Special case as ANMF chunk encapsulates other image chunks. +static uint8_t* ChunkEmitSpecial(const WebPChunk* const header, + size_t total_size, uint8_t* dst) { + const size_t header_size = header->data_.size; + const size_t offset_to_next = total_size - CHUNK_HEADER_SIZE; + assert(header->tag_ == kChunks[IDX_ANMF].tag); + PutLE32(dst + 0, header->tag_); + PutLE32(dst + TAG_SIZE, (uint32_t)offset_to_next); + assert(header_size == (uint32_t)header_size); + memcpy(dst + CHUNK_HEADER_SIZE, header->data_.bytes, header_size); + if (header_size & 1) { + dst[CHUNK_HEADER_SIZE + header_size] = 0; // Add padding. + } + return dst + ChunkDiskSize(header); +} + +uint8_t* MuxImageEmit(const WebPMuxImage* const wpi, uint8_t* dst) { + // Ordering of chunks to be emitted is strictly as follows: + // 1. ANMF chunk (if present). + // 2. ALPH chunk (if present). + // 3. VP8/VP8L chunk. + assert(wpi); + if (wpi->header_ != NULL) { + dst = ChunkEmitSpecial(wpi->header_, MuxImageDiskSize(wpi), dst); + } + if (wpi->alpha_ != NULL) dst = ChunkEmit(wpi->alpha_, dst); + if (wpi->img_ != NULL) dst = ChunkEmit(wpi->img_, dst); + if (wpi->unknown_ != NULL) dst = ChunkListEmit(wpi->unknown_, dst); + return dst; +} + +//------------------------------------------------------------------------------ +// Helper methods for mux. + +int MuxHasAlpha(const WebPMuxImage* images) { + while (images != NULL) { + if (images->has_alpha_) return 1; + images = images->next_; + } + return 0; +} + +uint8_t* MuxEmitRiffHeader(uint8_t* const data, size_t size) { + PutLE32(data + 0, MKFOURCC('R', 'I', 'F', 'F')); + PutLE32(data + TAG_SIZE, (uint32_t)size - CHUNK_HEADER_SIZE); + assert(size == (uint32_t)size); + PutLE32(data + TAG_SIZE + CHUNK_SIZE_BYTES, MKFOURCC('W', 'E', 'B', 'P')); + return data + RIFF_HEADER_SIZE; +} + +WebPChunk** MuxGetChunkListFromId(const WebPMux* mux, WebPChunkId id) { + assert(mux != NULL); + switch (id) { + case WEBP_CHUNK_VP8X: return (WebPChunk**)&mux->vp8x_; + case WEBP_CHUNK_ICCP: return (WebPChunk**)&mux->iccp_; + case WEBP_CHUNK_ANIM: return (WebPChunk**)&mux->anim_; + case WEBP_CHUNK_EXIF: return (WebPChunk**)&mux->exif_; + case WEBP_CHUNK_XMP: return (WebPChunk**)&mux->xmp_; + default: return (WebPChunk**)&mux->unknown_; + } +} + +static int IsNotCompatible(int feature, int num_items) { + return (feature != 0) != (num_items > 0); +} + +#define NO_FLAG ((WebPFeatureFlags)0) + +// Test basic constraints: +// retrieval, maximum number of chunks by index (use -1 to skip) +// and feature incompatibility (use NO_FLAG to skip). +// On success returns WEBP_MUX_OK and stores the chunk count in *num. +static WebPMuxError ValidateChunk(const WebPMux* const mux, CHUNK_INDEX idx, + WebPFeatureFlags feature, + uint32_t vp8x_flags, + int max, int* num) { + const WebPMuxError err = + WebPMuxNumChunks(mux, kChunks[idx].id, num); + if (err != WEBP_MUX_OK) return err; + if (max > -1 && *num > max) return WEBP_MUX_INVALID_ARGUMENT; + if (feature != NO_FLAG && IsNotCompatible(vp8x_flags & feature, *num)) { + return WEBP_MUX_INVALID_ARGUMENT; + } + return WEBP_MUX_OK; +} + +WebPMuxError MuxValidate(const WebPMux* const mux) { + int num_iccp; + int num_exif; + int num_xmp; + int num_anim; + int num_frames; + int num_vp8x; + int num_images; + int num_alpha; + uint32_t flags; + WebPMuxError err; + + // Verify mux is not NULL. + if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT; + + // Verify mux has at least one image. + if (mux->images_ == NULL) return WEBP_MUX_INVALID_ARGUMENT; + + err = WebPMuxGetFeatures(mux, &flags); + if (err != WEBP_MUX_OK) return err; + + // At most one color profile chunk. + err = ValidateChunk(mux, IDX_ICCP, ICCP_FLAG, flags, 1, &num_iccp); + if (err != WEBP_MUX_OK) return err; + + // At most one EXIF metadata. + err = ValidateChunk(mux, IDX_EXIF, EXIF_FLAG, flags, 1, &num_exif); + if (err != WEBP_MUX_OK) return err; + + // At most one XMP metadata. + err = ValidateChunk(mux, IDX_XMP, XMP_FLAG, flags, 1, &num_xmp); + if (err != WEBP_MUX_OK) return err; + + // Animation: ANIMATION_FLAG, ANIM chunk and ANMF chunk(s) are consistent. + // At most one ANIM chunk. + err = ValidateChunk(mux, IDX_ANIM, NO_FLAG, flags, 1, &num_anim); + if (err != WEBP_MUX_OK) return err; + err = ValidateChunk(mux, IDX_ANMF, NO_FLAG, flags, -1, &num_frames); + if (err != WEBP_MUX_OK) return err; + + { + const int has_animation = !!(flags & ANIMATION_FLAG); + if (has_animation && (num_anim == 0 || num_frames == 0)) { + return WEBP_MUX_INVALID_ARGUMENT; + } + if (!has_animation && (num_anim == 1 || num_frames > 0)) { + return WEBP_MUX_INVALID_ARGUMENT; + } + if (!has_animation) { + const WebPMuxImage* images = mux->images_; + // There can be only one image. + if (images == NULL || images->next_ != NULL) { + return WEBP_MUX_INVALID_ARGUMENT; + } + // Size must match. + if (mux->canvas_width_ > 0) { + if (images->width_ != mux->canvas_width_ || + images->height_ != mux->canvas_height_) { + return WEBP_MUX_INVALID_ARGUMENT; + } + } + } + } + + // Verify either VP8X chunk is present OR there is only one elem in + // mux->images_. + err = ValidateChunk(mux, IDX_VP8X, NO_FLAG, flags, 1, &num_vp8x); + if (err != WEBP_MUX_OK) return err; + err = ValidateChunk(mux, IDX_VP8, NO_FLAG, flags, -1, &num_images); + if (err != WEBP_MUX_OK) return err; + if (num_vp8x == 0 && num_images != 1) return WEBP_MUX_INVALID_ARGUMENT; + + // ALPHA_FLAG & alpha chunk(s) are consistent. + // Note: ALPHA_FLAG can be set when there is actually no Alpha data present. + if (MuxHasAlpha(mux->images_)) { + if (num_vp8x > 0) { + // VP8X chunk is present, so it should contain ALPHA_FLAG. + if (!(flags & ALPHA_FLAG)) return WEBP_MUX_INVALID_ARGUMENT; + } else { + // VP8X chunk is not present, so ALPH chunks should NOT be present either. + err = WebPMuxNumChunks(mux, WEBP_CHUNK_ALPHA, &num_alpha); + if (err != WEBP_MUX_OK) return err; + if (num_alpha > 0) return WEBP_MUX_INVALID_ARGUMENT; + } + } + + return WEBP_MUX_OK; +} + +#undef NO_FLAG + +//------------------------------------------------------------------------------ + diff --git a/third-party/webp/libwebp/src/mux/muxread.c b/third-party/webp/libwebp/src/mux/muxread.c new file mode 100644 index 0000000000..9862ec68ee --- /dev/null +++ b/third-party/webp/libwebp/src/mux/muxread.c @@ -0,0 +1,557 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Read APIs for mux. +// +// Authors: Urvang (urvang@google.com) +// Vikas (vikasa@google.com) + +#include +#include "src/mux/muxi.h" +#include "src/utils/utils.h" + +//------------------------------------------------------------------------------ +// Helper method(s). + +// Handy MACRO. +#define SWITCH_ID_LIST(INDEX, LIST) \ + if (idx == (INDEX)) { \ + const WebPChunk* const chunk = ChunkSearchList((LIST), nth, \ + kChunks[(INDEX)].tag); \ + if (chunk) { \ + *data = chunk->data_; \ + return WEBP_MUX_OK; \ + } else { \ + return WEBP_MUX_NOT_FOUND; \ + } \ + } + +static WebPMuxError MuxGet(const WebPMux* const mux, CHUNK_INDEX idx, + uint32_t nth, WebPData* const data) { + assert(mux != NULL); + assert(!IsWPI(kChunks[idx].id)); + WebPDataInit(data); + + SWITCH_ID_LIST(IDX_VP8X, mux->vp8x_); + SWITCH_ID_LIST(IDX_ICCP, mux->iccp_); + SWITCH_ID_LIST(IDX_ANIM, mux->anim_); + SWITCH_ID_LIST(IDX_EXIF, mux->exif_); + SWITCH_ID_LIST(IDX_XMP, mux->xmp_); + assert(idx != IDX_UNKNOWN); + return WEBP_MUX_NOT_FOUND; +} +#undef SWITCH_ID_LIST + +// Fill the chunk with the given data (includes chunk header bytes), after some +// verifications. +static WebPMuxError ChunkVerifyAndAssign(WebPChunk* chunk, + const uint8_t* data, size_t data_size, + size_t riff_size, int copy_data) { + uint32_t chunk_size; + WebPData chunk_data; + + // Correctness checks. + if (data_size < CHUNK_HEADER_SIZE) return WEBP_MUX_NOT_ENOUGH_DATA; + chunk_size = GetLE32(data + TAG_SIZE); + if (chunk_size > MAX_CHUNK_PAYLOAD) return WEBP_MUX_BAD_DATA; + + { + const size_t chunk_disk_size = SizeWithPadding(chunk_size); + if (chunk_disk_size > riff_size) return WEBP_MUX_BAD_DATA; + if (chunk_disk_size > data_size) return WEBP_MUX_NOT_ENOUGH_DATA; + } + + // Data assignment. + chunk_data.bytes = data + CHUNK_HEADER_SIZE; + chunk_data.size = chunk_size; + return ChunkAssignData(chunk, &chunk_data, copy_data, GetLE32(data + 0)); +} + +int MuxImageFinalize(WebPMuxImage* const wpi) { + const WebPChunk* const img = wpi->img_; + const WebPData* const image = &img->data_; + const int is_lossless = (img->tag_ == kChunks[IDX_VP8L].tag); + int w, h; + int vp8l_has_alpha = 0; + const int ok = is_lossless ? + VP8LGetInfo(image->bytes, image->size, &w, &h, &vp8l_has_alpha) : + VP8GetInfo(image->bytes, image->size, image->size, &w, &h); + assert(img != NULL); + if (ok) { + // Ignore ALPH chunk accompanying VP8L. + if (is_lossless && (wpi->alpha_ != NULL)) { + ChunkDelete(wpi->alpha_); + wpi->alpha_ = NULL; + } + wpi->width_ = w; + wpi->height_ = h; + wpi->has_alpha_ = vp8l_has_alpha || (wpi->alpha_ != NULL); + } + return ok; +} + +static int MuxImageParse(const WebPChunk* const chunk, int copy_data, + WebPMuxImage* const wpi) { + const uint8_t* bytes = chunk->data_.bytes; + size_t size = chunk->data_.size; + const uint8_t* const last = (bytes == NULL) ? NULL : bytes + size; + WebPChunk subchunk; + size_t subchunk_size; + WebPChunk** unknown_chunk_list = &wpi->unknown_; + ChunkInit(&subchunk); + + assert(chunk->tag_ == kChunks[IDX_ANMF].tag); + assert(!wpi->is_partial_); + + // ANMF. + { + const size_t hdr_size = ANMF_CHUNK_SIZE; + const WebPData temp = { bytes, hdr_size }; + // Each of ANMF chunk contain a header at the beginning. So, its size should + // be at least 'hdr_size'. + if (size < hdr_size) goto Fail; + if (ChunkAssignData(&subchunk, &temp, copy_data, + chunk->tag_) != WEBP_MUX_OK) { + goto Fail; + } + } + if (ChunkSetHead(&subchunk, &wpi->header_) != WEBP_MUX_OK) goto Fail; + wpi->is_partial_ = 1; // Waiting for ALPH and/or VP8/VP8L chunks. + + // Rest of the chunks. + subchunk_size = ChunkDiskSize(&subchunk) - CHUNK_HEADER_SIZE; + bytes += subchunk_size; + size -= subchunk_size; + + while (bytes != last) { + ChunkInit(&subchunk); + if (ChunkVerifyAndAssign(&subchunk, bytes, size, size, + copy_data) != WEBP_MUX_OK) { + goto Fail; + } + switch (ChunkGetIdFromTag(subchunk.tag_)) { + case WEBP_CHUNK_ALPHA: + if (wpi->alpha_ != NULL) goto Fail; // Consecutive ALPH chunks. + if (ChunkSetHead(&subchunk, &wpi->alpha_) != WEBP_MUX_OK) goto Fail; + wpi->is_partial_ = 1; // Waiting for a VP8 chunk. + break; + case WEBP_CHUNK_IMAGE: + if (wpi->img_ != NULL) goto Fail; // Only 1 image chunk allowed. + if (ChunkSetHead(&subchunk, &wpi->img_) != WEBP_MUX_OK) goto Fail; + if (!MuxImageFinalize(wpi)) goto Fail; + wpi->is_partial_ = 0; // wpi is completely filled. + break; + case WEBP_CHUNK_UNKNOWN: + if (wpi->is_partial_) { + goto Fail; // Encountered an unknown chunk + // before some image chunks. + } + if (ChunkAppend(&subchunk, &unknown_chunk_list) != WEBP_MUX_OK) { + goto Fail; + } + break; + default: + goto Fail; + } + subchunk_size = ChunkDiskSize(&subchunk); + bytes += subchunk_size; + size -= subchunk_size; + } + if (wpi->is_partial_) goto Fail; + return 1; + + Fail: + ChunkRelease(&subchunk); + return 0; +} + +//------------------------------------------------------------------------------ +// Create a mux object from WebP-RIFF data. + +WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data, + int version) { + size_t riff_size; + uint32_t tag; + const uint8_t* end; + WebPMux* mux = NULL; + WebPMuxImage* wpi = NULL; + const uint8_t* data; + size_t size; + WebPChunk chunk; + // Stores the end of the chunk lists so that it is faster to append data to + // their ends. + WebPChunk** chunk_list_ends[WEBP_CHUNK_NIL + 1] = { NULL }; + ChunkInit(&chunk); + + if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_MUX_ABI_VERSION)) { + return NULL; // version mismatch + } + if (bitstream == NULL) return NULL; + + data = bitstream->bytes; + size = bitstream->size; + + if (data == NULL) return NULL; + if (size < RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE) return NULL; + if (GetLE32(data + 0) != MKFOURCC('R', 'I', 'F', 'F') || + GetLE32(data + CHUNK_HEADER_SIZE) != MKFOURCC('W', 'E', 'B', 'P')) { + return NULL; + } + + mux = WebPMuxNew(); + if (mux == NULL) return NULL; + + tag = GetLE32(data + RIFF_HEADER_SIZE); + if (tag != kChunks[IDX_VP8].tag && + tag != kChunks[IDX_VP8L].tag && + tag != kChunks[IDX_VP8X].tag) { + goto Err; // First chunk should be VP8, VP8L or VP8X. + } + + riff_size = GetLE32(data + TAG_SIZE); + if (riff_size > MAX_CHUNK_PAYLOAD) goto Err; + + // Note this padding is historical and differs from demux.c which does not + // pad the file size. + riff_size = SizeWithPadding(riff_size); + if (riff_size < CHUNK_HEADER_SIZE) goto Err; + if (riff_size > size) goto Err; + // There's no point in reading past the end of the RIFF chunk. + if (size > riff_size + CHUNK_HEADER_SIZE) { + size = riff_size + CHUNK_HEADER_SIZE; + } + + end = data + size; + data += RIFF_HEADER_SIZE; + size -= RIFF_HEADER_SIZE; + + wpi = (WebPMuxImage*)WebPSafeMalloc(1ULL, sizeof(*wpi)); + if (wpi == NULL) goto Err; + MuxImageInit(wpi); + + // Loop over chunks. + while (data != end) { + size_t data_size; + WebPChunkId id; + if (ChunkVerifyAndAssign(&chunk, data, size, riff_size, + copy_data) != WEBP_MUX_OK) { + goto Err; + } + data_size = ChunkDiskSize(&chunk); + id = ChunkGetIdFromTag(chunk.tag_); + switch (id) { + case WEBP_CHUNK_ALPHA: + if (wpi->alpha_ != NULL) goto Err; // Consecutive ALPH chunks. + if (ChunkSetHead(&chunk, &wpi->alpha_) != WEBP_MUX_OK) goto Err; + wpi->is_partial_ = 1; // Waiting for a VP8 chunk. + break; + case WEBP_CHUNK_IMAGE: + if (ChunkSetHead(&chunk, &wpi->img_) != WEBP_MUX_OK) goto Err; + if (!MuxImageFinalize(wpi)) goto Err; + wpi->is_partial_ = 0; // wpi is completely filled. + PushImage: + // Add this to mux->images_ list. + if (MuxImagePush(wpi, &mux->images_) != WEBP_MUX_OK) goto Err; + MuxImageInit(wpi); // Reset for reading next image. + break; + case WEBP_CHUNK_ANMF: + if (wpi->is_partial_) goto Err; // Previous wpi is still incomplete. + if (!MuxImageParse(&chunk, copy_data, wpi)) goto Err; + ChunkRelease(&chunk); + goto PushImage; + default: // A non-image chunk. + if (wpi->is_partial_) goto Err; // Encountered a non-image chunk before + // getting all chunks of an image. + if (chunk_list_ends[id] == NULL) { + chunk_list_ends[id] = + MuxGetChunkListFromId(mux, id); // List to add this chunk. + } + if (ChunkAppend(&chunk, &chunk_list_ends[id]) != WEBP_MUX_OK) goto Err; + if (id == WEBP_CHUNK_VP8X) { // grab global specs + if (data_size < CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE) goto Err; + mux->canvas_width_ = GetLE24(data + 12) + 1; + mux->canvas_height_ = GetLE24(data + 15) + 1; + } + break; + } + data += data_size; + size -= data_size; + ChunkInit(&chunk); + } + + // Incomplete image. + if (wpi->is_partial_) goto Err; + + // Validate mux if complete. + if (MuxValidate(mux) != WEBP_MUX_OK) goto Err; + + MuxImageDelete(wpi); + return mux; // All OK; + + Err: // Something bad happened. + ChunkRelease(&chunk); + MuxImageDelete(wpi); + WebPMuxDelete(mux); + return NULL; +} + +//------------------------------------------------------------------------------ +// Get API(s). + +// Validates that the given mux has a single image. +static WebPMuxError ValidateForSingleImage(const WebPMux* const mux) { + const int num_images = MuxImageCount(mux->images_, WEBP_CHUNK_IMAGE); + const int num_frames = MuxImageCount(mux->images_, WEBP_CHUNK_ANMF); + + if (num_images == 0) { + // No images in mux. + return WEBP_MUX_NOT_FOUND; + } else if (num_images == 1 && num_frames == 0) { + // Valid case (single image). + return WEBP_MUX_OK; + } else { + // Frame case OR an invalid mux. + return WEBP_MUX_INVALID_ARGUMENT; + } +} + +// Get the canvas width, height and flags after validating that VP8X/VP8/VP8L +// chunk and canvas size are valid. +static WebPMuxError MuxGetCanvasInfo(const WebPMux* const mux, + int* width, int* height, uint32_t* flags) { + int w, h; + uint32_t f = 0; + WebPData data; + assert(mux != NULL); + + // Check if VP8X chunk is present. + if (MuxGet(mux, IDX_VP8X, 1, &data) == WEBP_MUX_OK) { + if (data.size < VP8X_CHUNK_SIZE) return WEBP_MUX_BAD_DATA; + f = GetLE32(data.bytes + 0); + w = GetLE24(data.bytes + 4) + 1; + h = GetLE24(data.bytes + 7) + 1; + } else { + const WebPMuxImage* const wpi = mux->images_; + // Grab user-forced canvas size as default. + w = mux->canvas_width_; + h = mux->canvas_height_; + if (w == 0 && h == 0 && ValidateForSingleImage(mux) == WEBP_MUX_OK) { + // single image and not forced canvas size => use dimension of first frame + assert(wpi != NULL); + w = wpi->width_; + h = wpi->height_; + } + if (wpi != NULL) { + if (wpi->has_alpha_) f |= ALPHA_FLAG; + } + } + if (w * (uint64_t)h >= MAX_IMAGE_AREA) return WEBP_MUX_BAD_DATA; + + if (width != NULL) *width = w; + if (height != NULL) *height = h; + if (flags != NULL) *flags = f; + return WEBP_MUX_OK; +} + +WebPMuxError WebPMuxGetCanvasSize(const WebPMux* mux, int* width, int* height) { + if (mux == NULL || width == NULL || height == NULL) { + return WEBP_MUX_INVALID_ARGUMENT; + } + return MuxGetCanvasInfo(mux, width, height, NULL); +} + +WebPMuxError WebPMuxGetFeatures(const WebPMux* mux, uint32_t* flags) { + if (mux == NULL || flags == NULL) return WEBP_MUX_INVALID_ARGUMENT; + return MuxGetCanvasInfo(mux, NULL, NULL, flags); +} + +static uint8_t* EmitVP8XChunk(uint8_t* const dst, int width, + int height, uint32_t flags) { + const size_t vp8x_size = CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE; + assert(width >= 1 && height >= 1); + assert(width <= MAX_CANVAS_SIZE && height <= MAX_CANVAS_SIZE); + assert(width * (uint64_t)height < MAX_IMAGE_AREA); + PutLE32(dst, MKFOURCC('V', 'P', '8', 'X')); + PutLE32(dst + TAG_SIZE, VP8X_CHUNK_SIZE); + PutLE32(dst + CHUNK_HEADER_SIZE, flags); + PutLE24(dst + CHUNK_HEADER_SIZE + 4, width - 1); + PutLE24(dst + CHUNK_HEADER_SIZE + 7, height - 1); + return dst + vp8x_size; +} + +// Assemble a single image WebP bitstream from 'wpi'. +static WebPMuxError SynthesizeBitstream(const WebPMuxImage* const wpi, + WebPData* const bitstream) { + uint8_t* dst; + + // Allocate data. + const int need_vp8x = (wpi->alpha_ != NULL); + const size_t vp8x_size = need_vp8x ? CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE : 0; + const size_t alpha_size = need_vp8x ? ChunkDiskSize(wpi->alpha_) : 0; + // Note: No need to output ANMF chunk for a single image. + const size_t size = RIFF_HEADER_SIZE + vp8x_size + alpha_size + + ChunkDiskSize(wpi->img_); + uint8_t* const data = (uint8_t*)WebPSafeMalloc(1ULL, size); + if (data == NULL) return WEBP_MUX_MEMORY_ERROR; + + // There should be at most one alpha_ chunk and exactly one img_ chunk. + assert(wpi->alpha_ == NULL || wpi->alpha_->next_ == NULL); + assert(wpi->img_ != NULL && wpi->img_->next_ == NULL); + + // Main RIFF header. + dst = MuxEmitRiffHeader(data, size); + + if (need_vp8x) { + dst = EmitVP8XChunk(dst, wpi->width_, wpi->height_, ALPHA_FLAG); // VP8X. + dst = ChunkListEmit(wpi->alpha_, dst); // ALPH. + } + + // Bitstream. + dst = ChunkListEmit(wpi->img_, dst); + assert(dst == data + size); + + // Output. + bitstream->bytes = data; + bitstream->size = size; + return WEBP_MUX_OK; +} + +WebPMuxError WebPMuxGetChunk(const WebPMux* mux, const char fourcc[4], + WebPData* chunk_data) { + CHUNK_INDEX idx; + if (mux == NULL || fourcc == NULL || chunk_data == NULL) { + return WEBP_MUX_INVALID_ARGUMENT; + } + idx = ChunkGetIndexFromFourCC(fourcc); + if (IsWPI(kChunks[idx].id)) { // An image chunk. + return WEBP_MUX_INVALID_ARGUMENT; + } else if (idx != IDX_UNKNOWN) { // A known chunk type. + return MuxGet(mux, idx, 1, chunk_data); + } else { // An unknown chunk type. + const WebPChunk* const chunk = + ChunkSearchList(mux->unknown_, 1, ChunkGetTagFromFourCC(fourcc)); + if (chunk == NULL) return WEBP_MUX_NOT_FOUND; + *chunk_data = chunk->data_; + return WEBP_MUX_OK; + } +} + +static WebPMuxError MuxGetImageInternal(const WebPMuxImage* const wpi, + WebPMuxFrameInfo* const info) { + // Set some defaults for unrelated fields. + info->x_offset = 0; + info->y_offset = 0; + info->duration = 1; + info->dispose_method = WEBP_MUX_DISPOSE_NONE; + info->blend_method = WEBP_MUX_BLEND; + // Extract data for related fields. + info->id = ChunkGetIdFromTag(wpi->img_->tag_); + return SynthesizeBitstream(wpi, &info->bitstream); +} + +static WebPMuxError MuxGetFrameInternal(const WebPMuxImage* const wpi, + WebPMuxFrameInfo* const frame) { + const int is_frame = (wpi->header_->tag_ == kChunks[IDX_ANMF].tag); + const WebPData* frame_data; + if (!is_frame) return WEBP_MUX_INVALID_ARGUMENT; + assert(wpi->header_ != NULL); // Already checked by WebPMuxGetFrame(). + // Get frame chunk. + frame_data = &wpi->header_->data_; + if (frame_data->size < kChunks[IDX_ANMF].size) return WEBP_MUX_BAD_DATA; + // Extract info. + frame->x_offset = 2 * GetLE24(frame_data->bytes + 0); + frame->y_offset = 2 * GetLE24(frame_data->bytes + 3); + { + const uint8_t bits = frame_data->bytes[15]; + frame->duration = GetLE24(frame_data->bytes + 12); + frame->dispose_method = + (bits & 1) ? WEBP_MUX_DISPOSE_BACKGROUND : WEBP_MUX_DISPOSE_NONE; + frame->blend_method = (bits & 2) ? WEBP_MUX_NO_BLEND : WEBP_MUX_BLEND; + } + frame->id = ChunkGetIdFromTag(wpi->header_->tag_); + return SynthesizeBitstream(wpi, &frame->bitstream); +} + +WebPMuxError WebPMuxGetFrame( + const WebPMux* mux, uint32_t nth, WebPMuxFrameInfo* frame) { + WebPMuxError err; + WebPMuxImage* wpi; + + if (mux == NULL || frame == NULL) { + return WEBP_MUX_INVALID_ARGUMENT; + } + + // Get the nth WebPMuxImage. + err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, nth, &wpi); + if (err != WEBP_MUX_OK) return err; + + // Get frame info. + if (wpi->header_ == NULL) { + return MuxGetImageInternal(wpi, frame); + } else { + return MuxGetFrameInternal(wpi, frame); + } +} + +WebPMuxError WebPMuxGetAnimationParams(const WebPMux* mux, + WebPMuxAnimParams* params) { + WebPData anim; + WebPMuxError err; + + if (mux == NULL || params == NULL) return WEBP_MUX_INVALID_ARGUMENT; + + err = MuxGet(mux, IDX_ANIM, 1, &anim); + if (err != WEBP_MUX_OK) return err; + if (anim.size < kChunks[WEBP_CHUNK_ANIM].size) return WEBP_MUX_BAD_DATA; + params->bgcolor = GetLE32(anim.bytes); + params->loop_count = GetLE16(anim.bytes + 4); + + return WEBP_MUX_OK; +} + +// Get chunk index from chunk id. Returns IDX_NIL if not found. +static CHUNK_INDEX ChunkGetIndexFromId(WebPChunkId id) { + int i; + for (i = 0; kChunks[i].id != WEBP_CHUNK_NIL; ++i) { + if (id == kChunks[i].id) return (CHUNK_INDEX)i; + } + return IDX_NIL; +} + +// Count number of chunks matching 'tag' in the 'chunk_list'. +// If tag == NIL_TAG, any tag will be matched. +static int CountChunks(const WebPChunk* const chunk_list, uint32_t tag) { + int count = 0; + const WebPChunk* current; + for (current = chunk_list; current != NULL; current = current->next_) { + if (tag == NIL_TAG || current->tag_ == tag) { + count++; // Count chunks whose tags match. + } + } + return count; +} + +WebPMuxError WebPMuxNumChunks(const WebPMux* mux, + WebPChunkId id, int* num_elements) { + if (mux == NULL || num_elements == NULL) { + return WEBP_MUX_INVALID_ARGUMENT; + } + + if (IsWPI(id)) { + *num_elements = MuxImageCount(mux->images_, id); + } else { + WebPChunk* const* chunk_list = MuxGetChunkListFromId(mux, id); + const CHUNK_INDEX idx = ChunkGetIndexFromId(id); + *num_elements = CountChunks(*chunk_list, kChunks[idx].tag); + } + + return WEBP_MUX_OK; +} + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/src/utils/Makefile.am b/third-party/webp/libwebp/src/utils/Makefile.am new file mode 100644 index 0000000000..a0b7fe35e0 --- /dev/null +++ b/third-party/webp/libwebp/src/utils/Makefile.am @@ -0,0 +1,54 @@ +AM_CPPFLAGS += -I$(top_builddir) -I$(top_srcdir) +noinst_LTLIBRARIES = libwebputils.la + +if BUILD_LIBWEBPDECODER + noinst_LTLIBRARIES += libwebputilsdecode.la +endif + +common_HEADERS = ../webp/types.h +commondir = $(includedir)/webp + +noinst_HEADERS = +noinst_HEADERS += ../dsp/cpu.h +noinst_HEADERS += ../dsp/dsp.h +noinst_HEADERS += ../webp/decode.h +noinst_HEADERS += ../webp/encode.h +noinst_HEADERS += ../webp/format_constants.h + +COMMON_SOURCES = +COMMON_SOURCES += bit_reader_utils.c +COMMON_SOURCES += bit_reader_utils.h +COMMON_SOURCES += bit_reader_inl_utils.h +COMMON_SOURCES += color_cache_utils.c +COMMON_SOURCES += color_cache_utils.h +COMMON_SOURCES += endian_inl_utils.h +COMMON_SOURCES += filters_utils.c +COMMON_SOURCES += filters_utils.h +COMMON_SOURCES += huffman_utils.c +COMMON_SOURCES += huffman_utils.h +COMMON_SOURCES += palette.c +COMMON_SOURCES += palette.h +COMMON_SOURCES += quant_levels_dec_utils.c +COMMON_SOURCES += quant_levels_dec_utils.h +COMMON_SOURCES += rescaler_utils.c +COMMON_SOURCES += rescaler_utils.h +COMMON_SOURCES += random_utils.c +COMMON_SOURCES += random_utils.h +COMMON_SOURCES += thread_utils.c +COMMON_SOURCES += thread_utils.h +COMMON_SOURCES += utils.c +COMMON_SOURCES += utils.h + +ENC_SOURCES = +ENC_SOURCES += bit_writer_utils.c +ENC_SOURCES += bit_writer_utils.h +ENC_SOURCES += huffman_encode_utils.c +ENC_SOURCES += huffman_encode_utils.h +ENC_SOURCES += quant_levels_utils.c +ENC_SOURCES += quant_levels_utils.h + +libwebputils_la_SOURCES = $(COMMON_SOURCES) $(ENC_SOURCES) + +if BUILD_LIBWEBPDECODER + libwebputilsdecode_la_SOURCES = $(COMMON_SOURCES) +endif diff --git a/third-party/webp/libwebp/src/utils/bit_reader_inl_utils.h b/third-party/webp/libwebp/src/utils/bit_reader_inl_utils.h new file mode 100644 index 0000000000..24f3af7b54 --- /dev/null +++ b/third-party/webp/libwebp/src/utils/bit_reader_inl_utils.h @@ -0,0 +1,196 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Specific inlined methods for boolean decoder [VP8GetBit() ...] +// This file should be included by the .c sources that actually need to call +// these methods. +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_UTILS_BIT_READER_INL_UTILS_H_ +#define WEBP_UTILS_BIT_READER_INL_UTILS_H_ + +#ifdef HAVE_CONFIG_H +#include "src/webp/config.h" +#endif + +#include // for memcpy + +#include "src/dsp/dsp.h" +#include "src/utils/bit_reader_utils.h" +#include "src/utils/endian_inl_utils.h" +#include "src/utils/utils.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//------------------------------------------------------------------------------ +// Derived type lbit_t = natural type for memory I/O + +#if (BITS > 32) +typedef uint64_t lbit_t; +#elif (BITS > 16) +typedef uint32_t lbit_t; +#elif (BITS > 8) +typedef uint16_t lbit_t; +#else +typedef uint8_t lbit_t; +#endif + +extern const uint8_t kVP8Log2Range[128]; +extern const uint8_t kVP8NewRange[128]; + +// special case for the tail byte-reading +void VP8LoadFinalBytes(VP8BitReader* const br); + +//------------------------------------------------------------------------------ +// Inlined critical functions + +// makes sure br->value_ has at least BITS bits worth of data +static WEBP_UBSAN_IGNORE_UNDEF WEBP_INLINE +void VP8LoadNewBytes(VP8BitReader* WEBP_RESTRICT const br) { + assert(br != NULL && br->buf_ != NULL); + // Read 'BITS' bits at a time if possible. + if (br->buf_ < br->buf_max_) { + // convert memory type to register type (with some zero'ing!) + bit_t bits; +#if defined(WEBP_USE_MIPS32) + // This is needed because of un-aligned read. + lbit_t in_bits; + lbit_t* p_buf_ = (lbit_t*)br->buf_; + __asm__ volatile( + ".set push \n\t" + ".set at \n\t" + ".set macro \n\t" + "ulw %[in_bits], 0(%[p_buf_]) \n\t" + ".set pop \n\t" + : [in_bits]"=r"(in_bits) + : [p_buf_]"r"(p_buf_) + : "memory", "at" + ); +#else + lbit_t in_bits; + memcpy(&in_bits, br->buf_, sizeof(in_bits)); +#endif + br->buf_ += BITS >> 3; +#if !defined(WORDS_BIGENDIAN) +#if (BITS > 32) + bits = BSwap64(in_bits); + bits >>= 64 - BITS; +#elif (BITS >= 24) + bits = BSwap32(in_bits); + bits >>= (32 - BITS); +#elif (BITS == 16) + bits = BSwap16(in_bits); +#else // BITS == 8 + bits = (bit_t)in_bits; +#endif // BITS > 32 +#else // WORDS_BIGENDIAN + bits = (bit_t)in_bits; + if (BITS != 8 * sizeof(bit_t)) bits >>= (8 * sizeof(bit_t) - BITS); +#endif + br->value_ = bits | (br->value_ << BITS); + br->bits_ += BITS; + } else { + VP8LoadFinalBytes(br); // no need to be inlined + } +} + +// Read a bit with proba 'prob'. Speed-critical function! +static WEBP_INLINE int VP8GetBit(VP8BitReader* WEBP_RESTRICT const br, + int prob, const char label[]) { + // Don't move this declaration! It makes a big speed difference to store + // 'range' *before* calling VP8LoadNewBytes(), even if this function doesn't + // alter br->range_ value. + range_t range = br->range_; + if (br->bits_ < 0) { + VP8LoadNewBytes(br); + } + { + const int pos = br->bits_; + const range_t split = (range * prob) >> 8; + const range_t value = (range_t)(br->value_ >> pos); + const int bit = (value > split); + if (bit) { + range -= split; + br->value_ -= (bit_t)(split + 1) << pos; + } else { + range = split + 1; + } + { + const int shift = 7 ^ BitsLog2Floor(range); + range <<= shift; + br->bits_ -= shift; + } + br->range_ = range - 1; + BT_TRACK(br); + return bit; + } +} + +// simplified version of VP8GetBit() for prob=0x80 (note shift is always 1 here) +static WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW WEBP_INLINE +int VP8GetSigned(VP8BitReader* WEBP_RESTRICT const br, int v, + const char label[]) { + if (br->bits_ < 0) { + VP8LoadNewBytes(br); + } + { + const int pos = br->bits_; + const range_t split = br->range_ >> 1; + const range_t value = (range_t)(br->value_ >> pos); + const int32_t mask = (int32_t)(split - value) >> 31; // -1 or 0 + br->bits_ -= 1; + br->range_ += (range_t)mask; + br->range_ |= 1; + br->value_ -= (bit_t)((split + 1) & (uint32_t)mask) << pos; + BT_TRACK(br); + return (v ^ mask) - mask; + } +} + +static WEBP_INLINE int VP8GetBitAlt(VP8BitReader* WEBP_RESTRICT const br, + int prob, const char label[]) { + // Don't move this declaration! It makes a big speed difference to store + // 'range' *before* calling VP8LoadNewBytes(), even if this function doesn't + // alter br->range_ value. + range_t range = br->range_; + if (br->bits_ < 0) { + VP8LoadNewBytes(br); + } + { + const int pos = br->bits_; + const range_t split = (range * prob) >> 8; + const range_t value = (range_t)(br->value_ >> pos); + int bit; // Don't use 'const int bit = (value > split);", it's slower. + if (value > split) { + range -= split + 1; + br->value_ -= (bit_t)(split + 1) << pos; + bit = 1; + } else { + range = split; + bit = 0; + } + if (range <= (range_t)0x7e) { + const int shift = kVP8Log2Range[range]; + range = kVP8NewRange[range]; + br->bits_ -= shift; + } + br->range_ = range; + BT_TRACK(br); + return bit; + } +} + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_UTILS_BIT_READER_INL_UTILS_H_ diff --git a/third-party/webp/libwebp/src/utils/bit_reader_utils.c b/third-party/webp/libwebp/src/utils/bit_reader_utils.c new file mode 100644 index 0000000000..a26557aa49 --- /dev/null +++ b/third-party/webp/libwebp/src/utils/bit_reader_utils.c @@ -0,0 +1,299 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Boolean decoder non-inlined methods +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifdef HAVE_CONFIG_H +#include "src/webp/config.h" +#endif + +#include "src/dsp/cpu.h" +#include "src/utils/bit_reader_inl_utils.h" +#include "src/utils/utils.h" + +//------------------------------------------------------------------------------ +// VP8BitReader + +void VP8BitReaderSetBuffer(VP8BitReader* const br, + const uint8_t* const start, + size_t size) { + br->buf_ = start; + br->buf_end_ = start + size; + br->buf_max_ = + (size >= sizeof(lbit_t)) ? start + size - sizeof(lbit_t) + 1 + : start; +} + +void VP8InitBitReader(VP8BitReader* const br, + const uint8_t* const start, size_t size) { + assert(br != NULL); + assert(start != NULL); + assert(size < (1u << 31)); // limit ensured by format and upstream checks + br->range_ = 255 - 1; + br->value_ = 0; + br->bits_ = -8; // to load the very first 8bits + br->eof_ = 0; + VP8BitReaderSetBuffer(br, start, size); + VP8LoadNewBytes(br); +} + +void VP8RemapBitReader(VP8BitReader* const br, ptrdiff_t offset) { + if (br->buf_ != NULL) { + br->buf_ += offset; + br->buf_end_ += offset; + br->buf_max_ += offset; + } +} + +const uint8_t kVP8Log2Range[128] = { + 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0 +}; + +// range = ((range - 1) << kVP8Log2Range[range]) + 1 +const uint8_t kVP8NewRange[128] = { + 127, 127, 191, 127, 159, 191, 223, 127, + 143, 159, 175, 191, 207, 223, 239, 127, + 135, 143, 151, 159, 167, 175, 183, 191, + 199, 207, 215, 223, 231, 239, 247, 127, + 131, 135, 139, 143, 147, 151, 155, 159, + 163, 167, 171, 175, 179, 183, 187, 191, + 195, 199, 203, 207, 211, 215, 219, 223, + 227, 231, 235, 239, 243, 247, 251, 127, + 129, 131, 133, 135, 137, 139, 141, 143, + 145, 147, 149, 151, 153, 155, 157, 159, + 161, 163, 165, 167, 169, 171, 173, 175, + 177, 179, 181, 183, 185, 187, 189, 191, + 193, 195, 197, 199, 201, 203, 205, 207, + 209, 211, 213, 215, 217, 219, 221, 223, + 225, 227, 229, 231, 233, 235, 237, 239, + 241, 243, 245, 247, 249, 251, 253, 127 +}; + +void VP8LoadFinalBytes(VP8BitReader* const br) { + assert(br != NULL && br->buf_ != NULL); + // Only read 8bits at a time + if (br->buf_ < br->buf_end_) { + br->bits_ += 8; + br->value_ = (bit_t)(*br->buf_++) | (br->value_ << 8); + } else if (!br->eof_) { + br->value_ <<= 8; + br->bits_ += 8; + br->eof_ = 1; + } else { + br->bits_ = 0; // This is to avoid undefined behaviour with shifts. + } +} + +//------------------------------------------------------------------------------ +// Higher-level calls + +uint32_t VP8GetValue(VP8BitReader* const br, int bits, const char label[]) { + uint32_t v = 0; + while (bits-- > 0) { + v |= VP8GetBit(br, 0x80, label) << bits; + } + return v; +} + +int32_t VP8GetSignedValue(VP8BitReader* const br, int bits, + const char label[]) { + const int value = VP8GetValue(br, bits, label); + return VP8Get(br, label) ? -value : value; +} + +//------------------------------------------------------------------------------ +// VP8LBitReader + +#define VP8L_LOG8_WBITS 4 // Number of bytes needed to store VP8L_WBITS bits. + +#if defined(__arm__) || defined(_M_ARM) || WEBP_AARCH64 || \ + defined(__i386__) || defined(_M_IX86) || \ + defined(__x86_64__) || defined(_M_X64) +#define VP8L_USE_FAST_LOAD +#endif + +static const uint32_t kBitMask[VP8L_MAX_NUM_BIT_READ + 1] = { + 0, + 0x000001, 0x000003, 0x000007, 0x00000f, + 0x00001f, 0x00003f, 0x00007f, 0x0000ff, + 0x0001ff, 0x0003ff, 0x0007ff, 0x000fff, + 0x001fff, 0x003fff, 0x007fff, 0x00ffff, + 0x01ffff, 0x03ffff, 0x07ffff, 0x0fffff, + 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff +}; + +void VP8LInitBitReader(VP8LBitReader* const br, const uint8_t* const start, + size_t length) { + size_t i; + vp8l_val_t value = 0; + assert(br != NULL); + assert(start != NULL); + assert(length < 0xfffffff8u); // can't happen with a RIFF chunk. + + br->len_ = length; + br->val_ = 0; + br->bit_pos_ = 0; + br->eos_ = 0; + + if (length > sizeof(br->val_)) { + length = sizeof(br->val_); + } + for (i = 0; i < length; ++i) { + value |= (vp8l_val_t)start[i] << (8 * i); + } + br->val_ = value; + br->pos_ = length; + br->buf_ = start; +} + +void VP8LBitReaderSetBuffer(VP8LBitReader* const br, + const uint8_t* const buf, size_t len) { + assert(br != NULL); + assert(buf != NULL); + assert(len < 0xfffffff8u); // can't happen with a RIFF chunk. + br->buf_ = buf; + br->len_ = len; + // pos_ > len_ should be considered a param error. + br->eos_ = (br->pos_ > br->len_) || VP8LIsEndOfStream(br); +} + +static void VP8LSetEndOfStream(VP8LBitReader* const br) { + br->eos_ = 1; + br->bit_pos_ = 0; // To avoid undefined behaviour with shifts. +} + +// If not at EOS, reload up to VP8L_LBITS byte-by-byte +static void ShiftBytes(VP8LBitReader* const br) { + while (br->bit_pos_ >= 8 && br->pos_ < br->len_) { + br->val_ >>= 8; + br->val_ |= ((vp8l_val_t)br->buf_[br->pos_]) << (VP8L_LBITS - 8); + ++br->pos_; + br->bit_pos_ -= 8; + } + if (VP8LIsEndOfStream(br)) { + VP8LSetEndOfStream(br); + } +} + +void VP8LDoFillBitWindow(VP8LBitReader* const br) { + assert(br->bit_pos_ >= VP8L_WBITS); +#if defined(VP8L_USE_FAST_LOAD) + if (br->pos_ + sizeof(br->val_) < br->len_) { + br->val_ >>= VP8L_WBITS; + br->bit_pos_ -= VP8L_WBITS; + br->val_ |= (vp8l_val_t)HToLE32(WebPMemToUint32(br->buf_ + br->pos_)) << + (VP8L_LBITS - VP8L_WBITS); + br->pos_ += VP8L_LOG8_WBITS; + return; + } +#endif + ShiftBytes(br); // Slow path. +} + +uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits) { + assert(n_bits >= 0); + // Flag an error if end_of_stream or n_bits is more than allowed limit. + if (!br->eos_ && n_bits <= VP8L_MAX_NUM_BIT_READ) { + const uint32_t val = VP8LPrefetchBits(br) & kBitMask[n_bits]; + const int new_bits = br->bit_pos_ + n_bits; + br->bit_pos_ = new_bits; + ShiftBytes(br); + return val; + } else { + VP8LSetEndOfStream(br); + return 0; + } +} + +//------------------------------------------------------------------------------ +// Bit-tracing tool + +#if (BITTRACE > 0) + +#include // for atexit() +#include +#include + +#define MAX_NUM_LABELS 32 +static struct { + const char* label; + int size; + int count; +} kLabels[MAX_NUM_LABELS]; + +static int last_label = 0; +static int last_pos = 0; +static const uint8_t* buf_start = NULL; +static int init_done = 0; + +static void PrintBitTraces(void) { + int i; + int scale = 1; + int total = 0; + const char* units = "bits"; +#if (BITTRACE == 2) + scale = 8; + units = "bytes"; +#endif + for (i = 0; i < last_label; ++i) total += kLabels[i].size; + if (total < 1) total = 1; // avoid rounding errors + printf("=== Bit traces ===\n"); + for (i = 0; i < last_label; ++i) { + const int skip = 16 - (int)strlen(kLabels[i].label); + const int value = (kLabels[i].size + scale - 1) / scale; + assert(skip > 0); + printf("%s \%*s: %6d %s \t[%5.2f%%] [count: %7d]\n", + kLabels[i].label, skip, "", value, units, + 100.f * kLabels[i].size / total, + kLabels[i].count); + } + total = (total + scale - 1) / scale; + printf("Total: %d %s\n", total, units); +} + +void BitTrace(const struct VP8BitReader* const br, const char label[]) { + int i, pos; + if (!init_done) { + memset(kLabels, 0, sizeof(kLabels)); + atexit(PrintBitTraces); + buf_start = br->buf_; + init_done = 1; + } + pos = (int)(br->buf_ - buf_start) * 8 - br->bits_; + // if there's a too large jump, we've changed partition -> reset counter + if (abs(pos - last_pos) > 32) { + buf_start = br->buf_; + pos = 0; + last_pos = 0; + } + if (br->range_ >= 0x7f) pos += kVP8Log2Range[br->range_ - 0x7f]; + for (i = 0; i < last_label; ++i) { + if (!strcmp(label, kLabels[i].label)) break; + } + if (i == MAX_NUM_LABELS) abort(); // overflow! + kLabels[i].label = label; + kLabels[i].size += pos - last_pos; + kLabels[i].count += 1; + if (i == last_label) ++last_label; + last_pos = pos; +} + +#endif // BITTRACE > 0 + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/src/utils/bit_reader_utils.h b/third-party/webp/libwebp/src/utils/bit_reader_utils.h new file mode 100644 index 0000000000..25ff31e5d9 --- /dev/null +++ b/third-party/webp/libwebp/src/utils/bit_reader_utils.h @@ -0,0 +1,195 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Boolean decoder +// +// Author: Skal (pascal.massimino@gmail.com) +// Vikas Arora (vikaas.arora@gmail.com) + +#ifndef WEBP_UTILS_BIT_READER_UTILS_H_ +#define WEBP_UTILS_BIT_READER_UTILS_H_ + +#include +#ifdef _MSC_VER +#include // _byteswap_ulong +#endif +#include "src/dsp/cpu.h" +#include "src/webp/types.h" + +// Warning! This macro triggers quite some MACRO wizardry around func signature! +#if !defined(BITTRACE) +#define BITTRACE 0 // 0 = off, 1 = print bits, 2 = print bytes +#endif + +#if (BITTRACE > 0) +struct VP8BitReader; +extern void BitTrace(const struct VP8BitReader* const br, const char label[]); +#define BT_TRACK(br) BitTrace(br, label) +#define VP8Get(BR, L) VP8GetValue(BR, 1, L) +#else +#define BT_TRACK(br) +// We'll REMOVE the 'const char label[]' from all signatures and calls (!!): +#define VP8GetValue(BR, N, L) VP8GetValue(BR, N) +#define VP8Get(BR, L) VP8GetValue(BR, 1, L) +#define VP8GetSignedValue(BR, N, L) VP8GetSignedValue(BR, N) +#define VP8GetBit(BR, P, L) VP8GetBit(BR, P) +#define VP8GetBitAlt(BR, P, L) VP8GetBitAlt(BR, P) +#define VP8GetSigned(BR, V, L) VP8GetSigned(BR, V) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// The Boolean decoder needs to maintain infinite precision on the value_ field. +// However, since range_ is only 8bit, we only need an active window of 8 bits +// for value_. Left bits (MSB) gets zeroed and shifted away when value_ falls +// below 128, range_ is updated, and fresh bits read from the bitstream are +// brought in as LSB. To avoid reading the fresh bits one by one (slow), we +// cache BITS of them ahead. The total of (BITS + 8) bits must fit into a +// natural register (with type bit_t). To fetch BITS bits from bitstream we +// use a type lbit_t. +// +// BITS can be any multiple of 8 from 8 to 56 (inclusive). +// Pick values that fit natural register size. + +#if defined(__i386__) || defined(_M_IX86) // x86 32bit +#define BITS 24 +#elif defined(__x86_64__) || defined(_M_X64) // x86 64bit +#define BITS 56 +#elif defined(__arm__) || defined(_M_ARM) // ARM +#define BITS 24 +#elif WEBP_AARCH64 // ARM 64bit +#define BITS 56 +#elif defined(__mips__) // MIPS +#define BITS 24 +#else // reasonable default +#define BITS 24 +#endif + +//------------------------------------------------------------------------------ +// Derived types and constants: +// bit_t = natural register type for storing 'value_' (which is BITS+8 bits) +// range_t = register for 'range_' (which is 8bits only) + +#if (BITS > 24) +typedef uint64_t bit_t; +#else +typedef uint32_t bit_t; +#endif + +typedef uint32_t range_t; + +//------------------------------------------------------------------------------ +// Bitreader + +typedef struct VP8BitReader VP8BitReader; +struct VP8BitReader { + // boolean decoder (keep the field ordering as is!) + bit_t value_; // current value + range_t range_; // current range minus 1. In [127, 254] interval. + int bits_; // number of valid bits left + // read buffer + const uint8_t* buf_; // next byte to be read + const uint8_t* buf_end_; // end of read buffer + const uint8_t* buf_max_; // max packed-read position on buffer + int eof_; // true if input is exhausted +}; + +// Initialize the bit reader and the boolean decoder. +void VP8InitBitReader(VP8BitReader* const br, + const uint8_t* const start, size_t size); +// Sets the working read buffer. +void VP8BitReaderSetBuffer(VP8BitReader* const br, + const uint8_t* const start, size_t size); + +// Update internal pointers to displace the byte buffer by the +// relative offset 'offset'. +void VP8RemapBitReader(VP8BitReader* const br, ptrdiff_t offset); + +// return the next value made of 'num_bits' bits +uint32_t VP8GetValue(VP8BitReader* const br, int num_bits, const char label[]); + +// return the next value with sign-extension. +int32_t VP8GetSignedValue(VP8BitReader* const br, int num_bits, + const char label[]); + +// bit_reader_inl.h will implement the following methods: +// static WEBP_INLINE int VP8GetBit(VP8BitReader* const br, int prob, ...) +// static WEBP_INLINE int VP8GetSigned(VP8BitReader* const br, int v, ...) +// and should be included by the .c files that actually need them. +// This is to avoid recompiling the whole library whenever this file is touched, +// and also allowing platform-specific ad-hoc hacks. + +// ----------------------------------------------------------------------------- +// Bitreader for lossless format + +// maximum number of bits (inclusive) the bit-reader can handle: +#define VP8L_MAX_NUM_BIT_READ 24 + +#define VP8L_LBITS 64 // Number of bits prefetched (= bit-size of vp8l_val_t). +#define VP8L_WBITS 32 // Minimum number of bytes ready after VP8LFillBitWindow. + +typedef uint64_t vp8l_val_t; // right now, this bit-reader can only use 64bit. + +typedef struct { + vp8l_val_t val_; // pre-fetched bits + const uint8_t* buf_; // input byte buffer + size_t len_; // buffer length + size_t pos_; // byte position in buf_ + int bit_pos_; // current bit-reading position in val_ + int eos_; // true if a bit was read past the end of buffer +} VP8LBitReader; + +void VP8LInitBitReader(VP8LBitReader* const br, + const uint8_t* const start, + size_t length); + +// Sets a new data buffer. +void VP8LBitReaderSetBuffer(VP8LBitReader* const br, + const uint8_t* const buffer, size_t length); + +// Reads the specified number of bits from read buffer. +// Flags an error in case end_of_stream or n_bits is more than the allowed limit +// of VP8L_MAX_NUM_BIT_READ (inclusive). +// Flags eos_ if this read attempt is going to cross the read buffer. +uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits); + +// Return the prefetched bits, so they can be looked up. +static WEBP_INLINE uint32_t VP8LPrefetchBits(VP8LBitReader* const br) { + return (uint32_t)(br->val_ >> (br->bit_pos_ & (VP8L_LBITS - 1))); +} + +// Returns true if there was an attempt at reading bit past the end of +// the buffer. Doesn't set br->eos_ flag. +static WEBP_INLINE int VP8LIsEndOfStream(const VP8LBitReader* const br) { + assert(br->pos_ <= br->len_); + return br->eos_ || ((br->pos_ == br->len_) && (br->bit_pos_ > VP8L_LBITS)); +} + +// For jumping over a number of bits in the bit stream when accessed with +// VP8LPrefetchBits and VP8LFillBitWindow. +// This function does *not* set br->eos_, since it's speed-critical. +// Use with extreme care! +static WEBP_INLINE void VP8LSetBitPos(VP8LBitReader* const br, int val) { + br->bit_pos_ = val; +} + +// Advances the read buffer by 4 bytes to make room for reading next 32 bits. +// Speed critical, but infrequent part of the code can be non-inlined. +extern void VP8LDoFillBitWindow(VP8LBitReader* const br); +static WEBP_INLINE void VP8LFillBitWindow(VP8LBitReader* const br) { + if (br->bit_pos_ >= VP8L_WBITS) VP8LDoFillBitWindow(br); +} + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_UTILS_BIT_READER_UTILS_H_ diff --git a/third-party/webp/libwebp/src/utils/bit_writer_utils.c b/third-party/webp/libwebp/src/utils/bit_writer_utils.c new file mode 100644 index 0000000000..2f408508f1 --- /dev/null +++ b/third-party/webp/libwebp/src/utils/bit_writer_utils.c @@ -0,0 +1,347 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Bit writing and boolean coder +// +// Author: Skal (pascal.massimino@gmail.com) +// Vikas Arora (vikaas.arora@gmail.com) + +#include +#include // for memcpy() +#include + +#include "src/utils/bit_writer_utils.h" +#include "src/utils/endian_inl_utils.h" +#include "src/utils/utils.h" + +//------------------------------------------------------------------------------ +// VP8BitWriter + +static int BitWriterResize(VP8BitWriter* const bw, size_t extra_size) { + uint8_t* new_buf; + size_t new_size; + const uint64_t needed_size_64b = (uint64_t)bw->pos_ + extra_size; + const size_t needed_size = (size_t)needed_size_64b; + if (needed_size_64b != needed_size) { + bw->error_ = 1; + return 0; + } + if (needed_size <= bw->max_pos_) return 1; + // If the following line wraps over 32bit, the test just after will catch it. + new_size = 2 * bw->max_pos_; + if (new_size < needed_size) new_size = needed_size; + if (new_size < 1024) new_size = 1024; + new_buf = (uint8_t*)WebPSafeMalloc(1ULL, new_size); + if (new_buf == NULL) { + bw->error_ = 1; + return 0; + } + if (bw->pos_ > 0) { + assert(bw->buf_ != NULL); + memcpy(new_buf, bw->buf_, bw->pos_); + } + WebPSafeFree(bw->buf_); + bw->buf_ = new_buf; + bw->max_pos_ = new_size; + return 1; +} + +static void Flush(VP8BitWriter* const bw) { + const int s = 8 + bw->nb_bits_; + const int32_t bits = bw->value_ >> s; + assert(bw->nb_bits_ >= 0); + bw->value_ -= bits << s; + bw->nb_bits_ -= 8; + if ((bits & 0xff) != 0xff) { + size_t pos = bw->pos_; + if (!BitWriterResize(bw, bw->run_ + 1)) { + return; + } + if (bits & 0x100) { // overflow -> propagate carry over pending 0xff's + if (pos > 0) bw->buf_[pos - 1]++; + } + if (bw->run_ > 0) { + const int value = (bits & 0x100) ? 0x00 : 0xff; + for (; bw->run_ > 0; --bw->run_) bw->buf_[pos++] = value; + } + bw->buf_[pos++] = bits & 0xff; + bw->pos_ = pos; + } else { + bw->run_++; // delay writing of bytes 0xff, pending eventual carry. + } +} + +//------------------------------------------------------------------------------ +// renormalization + +static const uint8_t kNorm[128] = { // renorm_sizes[i] = 8 - log2(i) + 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0 +}; + +// range = ((range + 1) << kVP8Log2Range[range]) - 1 +static const uint8_t kNewRange[128] = { + 127, 127, 191, 127, 159, 191, 223, 127, 143, 159, 175, 191, 207, 223, 239, + 127, 135, 143, 151, 159, 167, 175, 183, 191, 199, 207, 215, 223, 231, 239, + 247, 127, 131, 135, 139, 143, 147, 151, 155, 159, 163, 167, 171, 175, 179, + 183, 187, 191, 195, 199, 203, 207, 211, 215, 219, 223, 227, 231, 235, 239, + 243, 247, 251, 127, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, + 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 179, + 181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201, 203, 205, 207, 209, + 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, 235, 237, 239, + 241, 243, 245, 247, 249, 251, 253, 127 +}; + +int VP8PutBit(VP8BitWriter* const bw, int bit, int prob) { + const int split = (bw->range_ * prob) >> 8; + if (bit) { + bw->value_ += split + 1; + bw->range_ -= split + 1; + } else { + bw->range_ = split; + } + if (bw->range_ < 127) { // emit 'shift' bits out and renormalize + const int shift = kNorm[bw->range_]; + bw->range_ = kNewRange[bw->range_]; + bw->value_ <<= shift; + bw->nb_bits_ += shift; + if (bw->nb_bits_ > 0) Flush(bw); + } + return bit; +} + +int VP8PutBitUniform(VP8BitWriter* const bw, int bit) { + const int split = bw->range_ >> 1; + if (bit) { + bw->value_ += split + 1; + bw->range_ -= split + 1; + } else { + bw->range_ = split; + } + if (bw->range_ < 127) { + bw->range_ = kNewRange[bw->range_]; + bw->value_ <<= 1; + bw->nb_bits_ += 1; + if (bw->nb_bits_ > 0) Flush(bw); + } + return bit; +} + +void VP8PutBits(VP8BitWriter* const bw, uint32_t value, int nb_bits) { + uint32_t mask; + assert(nb_bits > 0 && nb_bits < 32); + for (mask = 1u << (nb_bits - 1); mask; mask >>= 1) { + VP8PutBitUniform(bw, value & mask); + } +} + +void VP8PutSignedBits(VP8BitWriter* const bw, int value, int nb_bits) { + if (!VP8PutBitUniform(bw, value != 0)) return; + if (value < 0) { + VP8PutBits(bw, ((-value) << 1) | 1, nb_bits + 1); + } else { + VP8PutBits(bw, value << 1, nb_bits + 1); + } +} + +//------------------------------------------------------------------------------ + +int VP8BitWriterInit(VP8BitWriter* const bw, size_t expected_size) { + bw->range_ = 255 - 1; + bw->value_ = 0; + bw->run_ = 0; + bw->nb_bits_ = -8; + bw->pos_ = 0; + bw->max_pos_ = 0; + bw->error_ = 0; + bw->buf_ = NULL; + return (expected_size > 0) ? BitWriterResize(bw, expected_size) : 1; +} + +uint8_t* VP8BitWriterFinish(VP8BitWriter* const bw) { + VP8PutBits(bw, 0, 9 - bw->nb_bits_); + bw->nb_bits_ = 0; // pad with zeroes + Flush(bw); + return bw->buf_; +} + +int VP8BitWriterAppend(VP8BitWriter* const bw, + const uint8_t* data, size_t size) { + assert(data != NULL); + if (bw->nb_bits_ != -8) return 0; // Flush() must have been called + if (!BitWriterResize(bw, size)) return 0; + memcpy(bw->buf_ + bw->pos_, data, size); + bw->pos_ += size; + return 1; +} + +void VP8BitWriterWipeOut(VP8BitWriter* const bw) { + if (bw != NULL) { + WebPSafeFree(bw->buf_); + memset(bw, 0, sizeof(*bw)); + } +} + +//------------------------------------------------------------------------------ +// VP8LBitWriter + +// This is the minimum amount of size the memory buffer is guaranteed to grow +// when extra space is needed. +#define MIN_EXTRA_SIZE (32768ULL) + +// Returns 1 on success. +static int VP8LBitWriterResize(VP8LBitWriter* const bw, size_t extra_size) { + uint8_t* allocated_buf; + size_t allocated_size; + const size_t max_bytes = bw->end_ - bw->buf_; + const size_t current_size = bw->cur_ - bw->buf_; + const uint64_t size_required_64b = (uint64_t)current_size + extra_size; + const size_t size_required = (size_t)size_required_64b; + if (size_required != size_required_64b) { + bw->error_ = 1; + return 0; + } + if (max_bytes > 0 && size_required <= max_bytes) return 1; + allocated_size = (3 * max_bytes) >> 1; + if (allocated_size < size_required) allocated_size = size_required; + // make allocated size multiple of 1k + allocated_size = (((allocated_size >> 10) + 1) << 10); + allocated_buf = (uint8_t*)WebPSafeMalloc(1ULL, allocated_size); + if (allocated_buf == NULL) { + bw->error_ = 1; + return 0; + } + if (current_size > 0) { + memcpy(allocated_buf, bw->buf_, current_size); + } + WebPSafeFree(bw->buf_); + bw->buf_ = allocated_buf; + bw->cur_ = bw->buf_ + current_size; + bw->end_ = bw->buf_ + allocated_size; + return 1; +} + +int VP8LBitWriterInit(VP8LBitWriter* const bw, size_t expected_size) { + memset(bw, 0, sizeof(*bw)); + return VP8LBitWriterResize(bw, expected_size); +} + +int VP8LBitWriterClone(const VP8LBitWriter* const src, + VP8LBitWriter* const dst) { + const size_t current_size = src->cur_ - src->buf_; + assert(src->cur_ >= src->buf_ && src->cur_ <= src->end_); + if (!VP8LBitWriterResize(dst, current_size)) return 0; + memcpy(dst->buf_, src->buf_, current_size); + dst->bits_ = src->bits_; + dst->used_ = src->used_; + dst->error_ = src->error_; + dst->cur_ = dst->buf_ + current_size; + return 1; +} + +void VP8LBitWriterWipeOut(VP8LBitWriter* const bw) { + if (bw != NULL) { + WebPSafeFree(bw->buf_); + memset(bw, 0, sizeof(*bw)); + } +} + +void VP8LBitWriterReset(const VP8LBitWriter* const bw_init, + VP8LBitWriter* const bw) { + bw->bits_ = bw_init->bits_; + bw->used_ = bw_init->used_; + bw->cur_ = bw->buf_ + (bw_init->cur_ - bw_init->buf_); + assert(bw->cur_ <= bw->end_); + bw->error_ = bw_init->error_; +} + +void VP8LBitWriterSwap(VP8LBitWriter* const src, VP8LBitWriter* const dst) { + const VP8LBitWriter tmp = *src; + *src = *dst; + *dst = tmp; +} + +void VP8LPutBitsFlushBits(VP8LBitWriter* const bw) { + // If needed, make some room by flushing some bits out. + if (bw->cur_ + VP8L_WRITER_BYTES > bw->end_) { + const uint64_t extra_size = (bw->end_ - bw->buf_) + MIN_EXTRA_SIZE; + if (!CheckSizeOverflow(extra_size) || + !VP8LBitWriterResize(bw, (size_t)extra_size)) { + bw->cur_ = bw->buf_; + bw->error_ = 1; + return; + } + } + *(vp8l_wtype_t*)bw->cur_ = (vp8l_wtype_t)WSWAP((vp8l_wtype_t)bw->bits_); + bw->cur_ += VP8L_WRITER_BYTES; + bw->bits_ >>= VP8L_WRITER_BITS; + bw->used_ -= VP8L_WRITER_BITS; +} + +void VP8LPutBitsInternal(VP8LBitWriter* const bw, uint32_t bits, int n_bits) { + assert(n_bits <= 32); + // That's the max we can handle: + assert(sizeof(vp8l_wtype_t) == 2); + if (n_bits > 0) { + vp8l_atype_t lbits = bw->bits_; + int used = bw->used_; + // Special case of overflow handling for 32bit accumulator (2-steps flush). +#if VP8L_WRITER_BITS == 16 + if (used + n_bits >= VP8L_WRITER_MAX_BITS) { + // Fill up all the VP8L_WRITER_MAX_BITS so it can be flushed out below. + const int shift = VP8L_WRITER_MAX_BITS - used; + lbits |= (vp8l_atype_t)bits << used; + used = VP8L_WRITER_MAX_BITS; + n_bits -= shift; + bits >>= shift; + assert(n_bits <= VP8L_WRITER_MAX_BITS); + } +#endif + // If needed, make some room by flushing some bits out. + while (used >= VP8L_WRITER_BITS) { + if (bw->cur_ + VP8L_WRITER_BYTES > bw->end_) { + const uint64_t extra_size = (bw->end_ - bw->buf_) + MIN_EXTRA_SIZE; + if (!CheckSizeOverflow(extra_size) || + !VP8LBitWriterResize(bw, (size_t)extra_size)) { + bw->cur_ = bw->buf_; + bw->error_ = 1; + return; + } + } + *(vp8l_wtype_t*)bw->cur_ = (vp8l_wtype_t)WSWAP((vp8l_wtype_t)lbits); + bw->cur_ += VP8L_WRITER_BYTES; + lbits >>= VP8L_WRITER_BITS; + used -= VP8L_WRITER_BITS; + } + bw->bits_ = lbits | ((vp8l_atype_t)bits << used); + bw->used_ = used + n_bits; + } +} + +uint8_t* VP8LBitWriterFinish(VP8LBitWriter* const bw) { + // flush leftover bits + if (VP8LBitWriterResize(bw, (bw->used_ + 7) >> 3)) { + while (bw->used_ > 0) { + *bw->cur_++ = (uint8_t)bw->bits_; + bw->bits_ >>= 8; + bw->used_ -= 8; + } + bw->used_ = 0; + } + return bw->buf_; +} + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/src/utils/bit_writer_utils.h b/third-party/webp/libwebp/src/utils/bit_writer_utils.h new file mode 100644 index 0000000000..b9d5102a5a --- /dev/null +++ b/third-party/webp/libwebp/src/utils/bit_writer_utils.h @@ -0,0 +1,154 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Bit writing and boolean coder +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_UTILS_BIT_WRITER_UTILS_H_ +#define WEBP_UTILS_BIT_WRITER_UTILS_H_ + +#include "src/webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//------------------------------------------------------------------------------ +// Bit-writing + +typedef struct VP8BitWriter VP8BitWriter; +struct VP8BitWriter { + int32_t range_; // range-1 + int32_t value_; + int run_; // number of outstanding bits + int nb_bits_; // number of pending bits + uint8_t* buf_; // internal buffer. Re-allocated regularly. Not owned. + size_t pos_; + size_t max_pos_; + int error_; // true in case of error +}; + +// Initialize the object. Allocates some initial memory based on expected_size. +int VP8BitWriterInit(VP8BitWriter* const bw, size_t expected_size); +// Finalize the bitstream coding. Returns a pointer to the internal buffer. +uint8_t* VP8BitWriterFinish(VP8BitWriter* const bw); +// Release any pending memory and zeroes the object. Not a mandatory call. +// Only useful in case of error, when the internal buffer hasn't been grabbed! +void VP8BitWriterWipeOut(VP8BitWriter* const bw); + +int VP8PutBit(VP8BitWriter* const bw, int bit, int prob); +int VP8PutBitUniform(VP8BitWriter* const bw, int bit); +void VP8PutBits(VP8BitWriter* const bw, uint32_t value, int nb_bits); +void VP8PutSignedBits(VP8BitWriter* const bw, int value, int nb_bits); + +// Appends some bytes to the internal buffer. Data is copied. +int VP8BitWriterAppend(VP8BitWriter* const bw, + const uint8_t* data, size_t size); + +// return approximate write position (in bits) +static WEBP_INLINE uint64_t VP8BitWriterPos(const VP8BitWriter* const bw) { + const uint64_t nb_bits = 8 + bw->nb_bits_; // bw->nb_bits_ is <= 0, note + return (bw->pos_ + bw->run_) * 8 + nb_bits; +} + +// Returns a pointer to the internal buffer. +static WEBP_INLINE uint8_t* VP8BitWriterBuf(const VP8BitWriter* const bw) { + return bw->buf_; +} +// Returns the size of the internal buffer. +static WEBP_INLINE size_t VP8BitWriterSize(const VP8BitWriter* const bw) { + return bw->pos_; +} + +//------------------------------------------------------------------------------ +// VP8LBitWriter + +#if defined(__x86_64__) || defined(_M_X64) // 64bit +typedef uint64_t vp8l_atype_t; // accumulator type +typedef uint32_t vp8l_wtype_t; // writing type +#define WSWAP HToLE32 +#define VP8L_WRITER_BYTES 4 // sizeof(vp8l_wtype_t) +#define VP8L_WRITER_BITS 32 // 8 * sizeof(vp8l_wtype_t) +#define VP8L_WRITER_MAX_BITS 64 // 8 * sizeof(vp8l_atype_t) +#else +typedef uint32_t vp8l_atype_t; +typedef uint16_t vp8l_wtype_t; +#define WSWAP HToLE16 +#define VP8L_WRITER_BYTES 2 +#define VP8L_WRITER_BITS 16 +#define VP8L_WRITER_MAX_BITS 32 +#endif + +typedef struct { + vp8l_atype_t bits_; // bit accumulator + int used_; // number of bits used in accumulator + uint8_t* buf_; // start of buffer + uint8_t* cur_; // current write position + uint8_t* end_; // end of buffer + + // After all bits are written (VP8LBitWriterFinish()), the caller must observe + // the state of error_. A value of 1 indicates that a memory allocation + // failure has happened during bit writing. A value of 0 indicates successful + // writing of bits. + int error_; +} VP8LBitWriter; + +static WEBP_INLINE size_t VP8LBitWriterNumBytes(const VP8LBitWriter* const bw) { + return (bw->cur_ - bw->buf_) + ((bw->used_ + 7) >> 3); +} + +// Returns false in case of memory allocation error. +int VP8LBitWriterInit(VP8LBitWriter* const bw, size_t expected_size); +// Returns false in case of memory allocation error. +int VP8LBitWriterClone(const VP8LBitWriter* const src, + VP8LBitWriter* const dst); +// Finalize the bitstream coding. Returns a pointer to the internal buffer. +uint8_t* VP8LBitWriterFinish(VP8LBitWriter* const bw); +// Release any pending memory and zeroes the object. +void VP8LBitWriterWipeOut(VP8LBitWriter* const bw); +// Resets the cursor of the BitWriter bw to when it was like in bw_init. +void VP8LBitWriterReset(const VP8LBitWriter* const bw_init, + VP8LBitWriter* const bw); +// Swaps the memory held by two BitWriters. +void VP8LBitWriterSwap(VP8LBitWriter* const src, VP8LBitWriter* const dst); + +// Internal function for VP8LPutBits flushing 32 bits from the written state. +void VP8LPutBitsFlushBits(VP8LBitWriter* const bw); + +// PutBits internal function used in the 16 bit vp8l_wtype_t case. +void VP8LPutBitsInternal(VP8LBitWriter* const bw, uint32_t bits, int n_bits); + +// This function writes bits into bytes in increasing addresses (little endian), +// and within a byte least-significant-bit first. +// This function can write up to 32 bits in one go, but VP8LBitReader can only +// read 24 bits max (VP8L_MAX_NUM_BIT_READ). +// VP8LBitWriter's error_ flag is set in case of memory allocation error. +static WEBP_INLINE void VP8LPutBits(VP8LBitWriter* const bw, + uint32_t bits, int n_bits) { + if (sizeof(vp8l_wtype_t) == 4) { + if (n_bits > 0) { + if (bw->used_ >= 32) { + VP8LPutBitsFlushBits(bw); + } + bw->bits_ |= (vp8l_atype_t)bits << bw->used_; + bw->used_ += n_bits; + } + } else { + VP8LPutBitsInternal(bw, bits, n_bits); + } +} + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_UTILS_BIT_WRITER_UTILS_H_ diff --git a/third-party/webp/libwebp/src/utils/color_cache_utils.c b/third-party/webp/libwebp/src/utils/color_cache_utils.c new file mode 100644 index 0000000000..7b5222b6e5 --- /dev/null +++ b/third-party/webp/libwebp/src/utils/color_cache_utils.c @@ -0,0 +1,49 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Color Cache for WebP Lossless +// +// Author: Jyrki Alakuijala (jyrki@google.com) + +#include +#include +#include +#include "src/utils/color_cache_utils.h" +#include "src/utils/utils.h" + +//------------------------------------------------------------------------------ +// VP8LColorCache. + +int VP8LColorCacheInit(VP8LColorCache* const color_cache, int hash_bits) { + const int hash_size = 1 << hash_bits; + assert(color_cache != NULL); + assert(hash_bits > 0); + color_cache->colors_ = (uint32_t*)WebPSafeCalloc( + (uint64_t)hash_size, sizeof(*color_cache->colors_)); + if (color_cache->colors_ == NULL) return 0; + color_cache->hash_shift_ = 32 - hash_bits; + color_cache->hash_bits_ = hash_bits; + return 1; +} + +void VP8LColorCacheClear(VP8LColorCache* const color_cache) { + if (color_cache != NULL) { + WebPSafeFree(color_cache->colors_); + color_cache->colors_ = NULL; + } +} + +void VP8LColorCacheCopy(const VP8LColorCache* const src, + VP8LColorCache* const dst) { + assert(src != NULL); + assert(dst != NULL); + assert(src->hash_bits_ == dst->hash_bits_); + memcpy(dst->colors_, src->colors_, + ((size_t)1u << dst->hash_bits_) * sizeof(*dst->colors_)); +} diff --git a/third-party/webp/libwebp/src/utils/color_cache_utils.h b/third-party/webp/libwebp/src/utils/color_cache_utils.h new file mode 100644 index 0000000000..b45d47c2d5 --- /dev/null +++ b/third-party/webp/libwebp/src/utils/color_cache_utils.h @@ -0,0 +1,89 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Color Cache for WebP Lossless +// +// Authors: Jyrki Alakuijala (jyrki@google.com) +// Urvang Joshi (urvang@google.com) + +#ifndef WEBP_UTILS_COLOR_CACHE_UTILS_H_ +#define WEBP_UTILS_COLOR_CACHE_UTILS_H_ + +#include + +#include "src/dsp/dsp.h" +#include "src/webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Main color cache struct. +typedef struct { + uint32_t* colors_; // color entries + int hash_shift_; // Hash shift: 32 - hash_bits_. + int hash_bits_; +} VP8LColorCache; + +static const uint32_t kHashMul = 0x1e35a7bdu; + +static WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW WEBP_INLINE +int VP8LHashPix(uint32_t argb, int shift) { + return (int)((argb * kHashMul) >> shift); +} + +static WEBP_INLINE uint32_t VP8LColorCacheLookup( + const VP8LColorCache* const cc, uint32_t key) { + assert((key >> cc->hash_bits_) == 0u); + return cc->colors_[key]; +} + +static WEBP_INLINE void VP8LColorCacheSet(const VP8LColorCache* const cc, + uint32_t key, uint32_t argb) { + assert((key >> cc->hash_bits_) == 0u); + cc->colors_[key] = argb; +} + +static WEBP_INLINE void VP8LColorCacheInsert(const VP8LColorCache* const cc, + uint32_t argb) { + const int key = VP8LHashPix(argb, cc->hash_shift_); + cc->colors_[key] = argb; +} + +static WEBP_INLINE int VP8LColorCacheGetIndex(const VP8LColorCache* const cc, + uint32_t argb) { + return VP8LHashPix(argb, cc->hash_shift_); +} + +// Return the key if cc contains argb, and -1 otherwise. +static WEBP_INLINE int VP8LColorCacheContains(const VP8LColorCache* const cc, + uint32_t argb) { + const int key = VP8LHashPix(argb, cc->hash_shift_); + return (cc->colors_[key] == argb) ? key : -1; +} + +//------------------------------------------------------------------------------ + +// Initializes the color cache with 'hash_bits' bits for the keys. +// Returns false in case of memory error. +int VP8LColorCacheInit(VP8LColorCache* const color_cache, int hash_bits); + +void VP8LColorCacheCopy(const VP8LColorCache* const src, + VP8LColorCache* const dst); + +// Delete the memory associated to color cache. +void VP8LColorCacheClear(VP8LColorCache* const color_cache); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} +#endif + +#endif // WEBP_UTILS_COLOR_CACHE_UTILS_H_ diff --git a/third-party/webp/libwebp/src/utils/endian_inl_utils.h b/third-party/webp/libwebp/src/utils/endian_inl_utils.h new file mode 100644 index 0000000000..3630a293bf --- /dev/null +++ b/third-party/webp/libwebp/src/utils/endian_inl_utils.h @@ -0,0 +1,93 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Endian related functions. + +#ifndef WEBP_UTILS_ENDIAN_INL_UTILS_H_ +#define WEBP_UTILS_ENDIAN_INL_UTILS_H_ + +#ifdef HAVE_CONFIG_H +#include "src/webp/config.h" +#endif + +#include "src/dsp/dsp.h" +#include "src/webp/types.h" + +#if defined(WORDS_BIGENDIAN) +#define HToLE32 BSwap32 +#define HToLE16 BSwap16 +#else +#define HToLE32(x) (x) +#define HToLE16(x) (x) +#endif + +#if !defined(HAVE_CONFIG_H) +#if LOCAL_GCC_PREREQ(4,8) || __has_builtin(__builtin_bswap16) +#define HAVE_BUILTIN_BSWAP16 +#endif +#if LOCAL_GCC_PREREQ(4,3) || __has_builtin(__builtin_bswap32) +#define HAVE_BUILTIN_BSWAP32 +#endif +#if LOCAL_GCC_PREREQ(4,3) || __has_builtin(__builtin_bswap64) +#define HAVE_BUILTIN_BSWAP64 +#endif +#endif // !HAVE_CONFIG_H + +static WEBP_INLINE uint16_t BSwap16(uint16_t x) { +#if defined(HAVE_BUILTIN_BSWAP16) + return __builtin_bswap16(x); +#elif defined(_MSC_VER) + return _byteswap_ushort(x); +#else + // gcc will recognize a 'rorw $8, ...' here: + return (x >> 8) | ((x & 0xff) << 8); +#endif // HAVE_BUILTIN_BSWAP16 +} + +static WEBP_INLINE uint32_t BSwap32(uint32_t x) { +#if defined(WEBP_USE_MIPS32_R2) + uint32_t ret; + __asm__ volatile ( + "wsbh %[ret], %[x] \n\t" + "rotr %[ret], %[ret], 16 \n\t" + : [ret]"=r"(ret) + : [x]"r"(x) + ); + return ret; +#elif defined(HAVE_BUILTIN_BSWAP32) + return __builtin_bswap32(x); +#elif defined(__i386__) || defined(__x86_64__) + uint32_t swapped_bytes; + __asm__ volatile("bswap %0" : "=r"(swapped_bytes) : "0"(x)); + return swapped_bytes; +#elif defined(_MSC_VER) + return (uint32_t)_byteswap_ulong(x); +#else + return (x >> 24) | ((x >> 8) & 0xff00) | ((x << 8) & 0xff0000) | (x << 24); +#endif // HAVE_BUILTIN_BSWAP32 +} + +static WEBP_INLINE uint64_t BSwap64(uint64_t x) { +#if defined(HAVE_BUILTIN_BSWAP64) + return __builtin_bswap64(x); +#elif defined(__x86_64__) + uint64_t swapped_bytes; + __asm__ volatile("bswapq %0" : "=r"(swapped_bytes) : "0"(x)); + return swapped_bytes; +#elif defined(_MSC_VER) + return (uint64_t)_byteswap_uint64(x); +#else // generic code for swapping 64-bit values (suggested by bdb@) + x = ((x & 0xffffffff00000000ull) >> 32) | ((x & 0x00000000ffffffffull) << 32); + x = ((x & 0xffff0000ffff0000ull) >> 16) | ((x & 0x0000ffff0000ffffull) << 16); + x = ((x & 0xff00ff00ff00ff00ull) >> 8) | ((x & 0x00ff00ff00ff00ffull) << 8); + return x; +#endif // HAVE_BUILTIN_BSWAP64 +} + +#endif // WEBP_UTILS_ENDIAN_INL_UTILS_H_ diff --git a/third-party/webp/libwebp/src/utils/filters_utils.c b/third-party/webp/libwebp/src/utils/filters_utils.c new file mode 100644 index 0000000000..bbc2c34d93 --- /dev/null +++ b/third-party/webp/libwebp/src/utils/filters_utils.c @@ -0,0 +1,76 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// filter estimation +// +// Author: Urvang (urvang@google.com) + +#include "src/utils/filters_utils.h" +#include +#include + +// ----------------------------------------------------------------------------- +// Quick estimate of a potentially interesting filter mode to try. + +#define SMAX 16 +#define SDIFF(a, b) (abs((a) - (b)) >> 4) // Scoring diff, in [0..SMAX) + +static WEBP_INLINE int GradientPredictor(uint8_t a, uint8_t b, uint8_t c) { + const int g = a + b - c; + return ((g & ~0xff) == 0) ? g : (g < 0) ? 0 : 255; // clip to 8bit +} + +WEBP_FILTER_TYPE WebPEstimateBestFilter(const uint8_t* data, + int width, int height, int stride) { + int i, j; + int bins[WEBP_FILTER_LAST][SMAX]; + memset(bins, 0, sizeof(bins)); + + // We only sample every other pixels. That's enough. + for (j = 2; j < height - 1; j += 2) { + const uint8_t* const p = data + j * stride; + int mean = p[0]; + for (i = 2; i < width - 1; i += 2) { + const int diff0 = SDIFF(p[i], mean); + const int diff1 = SDIFF(p[i], p[i - 1]); + const int diff2 = SDIFF(p[i], p[i - width]); + const int grad_pred = + GradientPredictor(p[i - 1], p[i - width], p[i - width - 1]); + const int diff3 = SDIFF(p[i], grad_pred); + bins[WEBP_FILTER_NONE][diff0] = 1; + bins[WEBP_FILTER_HORIZONTAL][diff1] = 1; + bins[WEBP_FILTER_VERTICAL][diff2] = 1; + bins[WEBP_FILTER_GRADIENT][diff3] = 1; + mean = (3 * mean + p[i] + 2) >> 2; + } + } + { + int filter; + WEBP_FILTER_TYPE best_filter = WEBP_FILTER_NONE; + int best_score = 0x7fffffff; + for (filter = WEBP_FILTER_NONE; filter < WEBP_FILTER_LAST; ++filter) { + int score = 0; + for (i = 0; i < SMAX; ++i) { + if (bins[filter][i] > 0) { + score += i; + } + } + if (score < best_score) { + best_score = score; + best_filter = (WEBP_FILTER_TYPE)filter; + } + } + return best_filter; + } +} + +#undef SMAX +#undef SDIFF + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/src/utils/filters_utils.h b/third-party/webp/libwebp/src/utils/filters_utils.h new file mode 100644 index 0000000000..61da66e212 --- /dev/null +++ b/third-party/webp/libwebp/src/utils/filters_utils.h @@ -0,0 +1,32 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Spatial prediction using various filters +// +// Author: Urvang (urvang@google.com) + +#ifndef WEBP_UTILS_FILTERS_UTILS_H_ +#define WEBP_UTILS_FILTERS_UTILS_H_ + +#include "src/webp/types.h" +#include "src/dsp/dsp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Fast estimate of a potentially good filter. +WEBP_FILTER_TYPE WebPEstimateBestFilter(const uint8_t* data, + int width, int height, int stride); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_UTILS_FILTERS_UTILS_H_ diff --git a/third-party/webp/libwebp/src/utils/huffman_encode_utils.c b/third-party/webp/libwebp/src/utils/huffman_encode_utils.c new file mode 100644 index 0000000000..585db91951 --- /dev/null +++ b/third-party/webp/libwebp/src/utils/huffman_encode_utils.c @@ -0,0 +1,416 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Jyrki Alakuijala (jyrki@google.com) +// +// Entropy encoding (Huffman) for webp lossless. + +#include +#include +#include +#include "src/utils/huffman_encode_utils.h" +#include "src/utils/utils.h" +#include "src/webp/format_constants.h" + +// ----------------------------------------------------------------------------- +// Util function to optimize the symbol map for RLE coding + +// Heuristics for selecting the stride ranges to collapse. +static int ValuesShouldBeCollapsedToStrideAverage(int a, int b) { + return abs(a - b) < 4; +} + +// Change the population counts in a way that the consequent +// Huffman tree compression, especially its RLE-part, give smaller output. +static void OptimizeHuffmanForRle(int length, uint8_t* const good_for_rle, + uint32_t* const counts) { + // 1) Let's make the Huffman code more compatible with rle encoding. + int i; + for (; length >= 0; --length) { + if (length == 0) { + return; // All zeros. + } + if (counts[length - 1] != 0) { + // Now counts[0..length - 1] does not have trailing zeros. + break; + } + } + // 2) Let's mark all population counts that already can be encoded + // with an rle code. + { + // Let's not spoil any of the existing good rle codes. + // Mark any seq of 0's that is longer as 5 as a good_for_rle. + // Mark any seq of non-0's that is longer as 7 as a good_for_rle. + uint32_t symbol = counts[0]; + int stride = 0; + for (i = 0; i < length + 1; ++i) { + if (i == length || counts[i] != symbol) { + if ((symbol == 0 && stride >= 5) || + (symbol != 0 && stride >= 7)) { + int k; + for (k = 0; k < stride; ++k) { + good_for_rle[i - k - 1] = 1; + } + } + stride = 1; + if (i != length) { + symbol = counts[i]; + } + } else { + ++stride; + } + } + } + // 3) Let's replace those population counts that lead to more rle codes. + { + uint32_t stride = 0; + uint32_t limit = counts[0]; + uint32_t sum = 0; + for (i = 0; i < length + 1; ++i) { + if (i == length || good_for_rle[i] || + (i != 0 && good_for_rle[i - 1]) || + !ValuesShouldBeCollapsedToStrideAverage(counts[i], limit)) { + if (stride >= 4 || (stride >= 3 && sum == 0)) { + uint32_t k; + // The stride must end, collapse what we have, if we have enough (4). + uint32_t count = (sum + stride / 2) / stride; + if (count < 1) { + count = 1; + } + if (sum == 0) { + // Don't make an all zeros stride to be upgraded to ones. + count = 0; + } + for (k = 0; k < stride; ++k) { + // We don't want to change value at counts[i], + // that is already belonging to the next stride. Thus - 1. + counts[i - k - 1] = count; + } + } + stride = 0; + sum = 0; + if (i < length - 3) { + // All interesting strides have a count of at least 4, + // at least when non-zeros. + limit = (counts[i] + counts[i + 1] + + counts[i + 2] + counts[i + 3] + 2) / 4; + } else if (i < length) { + limit = counts[i]; + } else { + limit = 0; + } + } + ++stride; + if (i != length) { + sum += counts[i]; + if (stride >= 4) { + limit = (sum + stride / 2) / stride; + } + } + } + } +} + +// A comparer function for two Huffman trees: sorts first by 'total count' +// (more comes first), and then by 'value' (more comes first). +static int CompareHuffmanTrees(const void* ptr1, const void* ptr2) { + const HuffmanTree* const t1 = (const HuffmanTree*)ptr1; + const HuffmanTree* const t2 = (const HuffmanTree*)ptr2; + if (t1->total_count_ > t2->total_count_) { + return -1; + } else if (t1->total_count_ < t2->total_count_) { + return 1; + } else { + assert(t1->value_ != t2->value_); + return (t1->value_ < t2->value_) ? -1 : 1; + } +} + +static void SetBitDepths(const HuffmanTree* const tree, + const HuffmanTree* const pool, + uint8_t* const bit_depths, int level) { + if (tree->pool_index_left_ >= 0) { + SetBitDepths(&pool[tree->pool_index_left_], pool, bit_depths, level + 1); + SetBitDepths(&pool[tree->pool_index_right_], pool, bit_depths, level + 1); + } else { + bit_depths[tree->value_] = level; + } +} + +// Create an optimal Huffman tree. +// +// (data,length): population counts. +// tree_limit: maximum bit depth (inclusive) of the codes. +// bit_depths[]: how many bits are used for the symbol. +// +// Returns 0 when an error has occurred. +// +// The catch here is that the tree cannot be arbitrarily deep +// +// count_limit is the value that is to be faked as the minimum value +// and this minimum value is raised until the tree matches the +// maximum length requirement. +// +// This algorithm is not of excellent performance for very long data blocks, +// especially when population counts are longer than 2**tree_limit, but +// we are not planning to use this with extremely long blocks. +// +// See https://en.wikipedia.org/wiki/Huffman_coding +static void GenerateOptimalTree(const uint32_t* const histogram, + int histogram_size, + HuffmanTree* tree, int tree_depth_limit, + uint8_t* const bit_depths) { + uint32_t count_min; + HuffmanTree* tree_pool; + int tree_size_orig = 0; + int i; + + for (i = 0; i < histogram_size; ++i) { + if (histogram[i] != 0) { + ++tree_size_orig; + } + } + + if (tree_size_orig == 0) { // pretty optimal already! + return; + } + + tree_pool = tree + tree_size_orig; + + // For block sizes with less than 64k symbols we never need to do a + // second iteration of this loop. + // If we actually start running inside this loop a lot, we would perhaps + // be better off with the Katajainen algorithm. + assert(tree_size_orig <= (1 << (tree_depth_limit - 1))); + for (count_min = 1; ; count_min *= 2) { + int tree_size = tree_size_orig; + // We need to pack the Huffman tree in tree_depth_limit bits. + // So, we try by faking histogram entries to be at least 'count_min'. + int idx = 0; + int j; + for (j = 0; j < histogram_size; ++j) { + if (histogram[j] != 0) { + const uint32_t count = + (histogram[j] < count_min) ? count_min : histogram[j]; + tree[idx].total_count_ = count; + tree[idx].value_ = j; + tree[idx].pool_index_left_ = -1; + tree[idx].pool_index_right_ = -1; + ++idx; + } + } + + // Build the Huffman tree. + qsort(tree, tree_size, sizeof(*tree), CompareHuffmanTrees); + + if (tree_size > 1) { // Normal case. + int tree_pool_size = 0; + while (tree_size > 1) { // Finish when we have only one root. + uint32_t count; + tree_pool[tree_pool_size++] = tree[tree_size - 1]; + tree_pool[tree_pool_size++] = tree[tree_size - 2]; + count = tree_pool[tree_pool_size - 1].total_count_ + + tree_pool[tree_pool_size - 2].total_count_; + tree_size -= 2; + { + // Search for the insertion point. + int k; + for (k = 0; k < tree_size; ++k) { + if (tree[k].total_count_ <= count) { + break; + } + } + memmove(tree + (k + 1), tree + k, (tree_size - k) * sizeof(*tree)); + tree[k].total_count_ = count; + tree[k].value_ = -1; + + tree[k].pool_index_left_ = tree_pool_size - 1; + tree[k].pool_index_right_ = tree_pool_size - 2; + tree_size = tree_size + 1; + } + } + SetBitDepths(&tree[0], tree_pool, bit_depths, 0); + } else if (tree_size == 1) { // Trivial case: only one element. + bit_depths[tree[0].value_] = 1; + } + + { + // Test if this Huffman tree satisfies our 'tree_depth_limit' criteria. + int max_depth = bit_depths[0]; + for (j = 1; j < histogram_size; ++j) { + if (max_depth < bit_depths[j]) { + max_depth = bit_depths[j]; + } + } + if (max_depth <= tree_depth_limit) { + break; + } + } + } +} + +// ----------------------------------------------------------------------------- +// Coding of the Huffman tree values + +static HuffmanTreeToken* CodeRepeatedValues(int repetitions, + HuffmanTreeToken* tokens, + int value, int prev_value) { + assert(value <= MAX_ALLOWED_CODE_LENGTH); + if (value != prev_value) { + tokens->code = value; + tokens->extra_bits = 0; + ++tokens; + --repetitions; + } + while (repetitions >= 1) { + if (repetitions < 3) { + int i; + for (i = 0; i < repetitions; ++i) { + tokens->code = value; + tokens->extra_bits = 0; + ++tokens; + } + break; + } else if (repetitions < 7) { + tokens->code = 16; + tokens->extra_bits = repetitions - 3; + ++tokens; + break; + } else { + tokens->code = 16; + tokens->extra_bits = 3; + ++tokens; + repetitions -= 6; + } + } + return tokens; +} + +static HuffmanTreeToken* CodeRepeatedZeros(int repetitions, + HuffmanTreeToken* tokens) { + while (repetitions >= 1) { + if (repetitions < 3) { + int i; + for (i = 0; i < repetitions; ++i) { + tokens->code = 0; // 0-value + tokens->extra_bits = 0; + ++tokens; + } + break; + } else if (repetitions < 11) { + tokens->code = 17; + tokens->extra_bits = repetitions - 3; + ++tokens; + break; + } else if (repetitions < 139) { + tokens->code = 18; + tokens->extra_bits = repetitions - 11; + ++tokens; + break; + } else { + tokens->code = 18; + tokens->extra_bits = 0x7f; // 138 repeated 0s + ++tokens; + repetitions -= 138; + } + } + return tokens; +} + +int VP8LCreateCompressedHuffmanTree(const HuffmanTreeCode* const tree, + HuffmanTreeToken* tokens, int max_tokens) { + HuffmanTreeToken* const starting_token = tokens; + HuffmanTreeToken* const ending_token = tokens + max_tokens; + const int depth_size = tree->num_symbols; + int prev_value = 8; // 8 is the initial value for rle. + int i = 0; + assert(tokens != NULL); + while (i < depth_size) { + const int value = tree->code_lengths[i]; + int k = i + 1; + int runs; + while (k < depth_size && tree->code_lengths[k] == value) ++k; + runs = k - i; + if (value == 0) { + tokens = CodeRepeatedZeros(runs, tokens); + } else { + tokens = CodeRepeatedValues(runs, tokens, value, prev_value); + prev_value = value; + } + i += runs; + assert(tokens <= ending_token); + } + (void)ending_token; // suppress 'unused variable' warning + return (int)(tokens - starting_token); +} + +// ----------------------------------------------------------------------------- + +// Pre-reversed 4-bit values. +static const uint8_t kReversedBits[16] = { + 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, + 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf +}; + +static uint32_t ReverseBits(int num_bits, uint32_t bits) { + uint32_t retval = 0; + int i = 0; + while (i < num_bits) { + i += 4; + retval |= kReversedBits[bits & 0xf] << (MAX_ALLOWED_CODE_LENGTH + 1 - i); + bits >>= 4; + } + retval >>= (MAX_ALLOWED_CODE_LENGTH + 1 - num_bits); + return retval; +} + +// Get the actual bit values for a tree of bit depths. +static void ConvertBitDepthsToSymbols(HuffmanTreeCode* const tree) { + // 0 bit-depth means that the symbol does not exist. + int i; + int len; + uint32_t next_code[MAX_ALLOWED_CODE_LENGTH + 1]; + int depth_count[MAX_ALLOWED_CODE_LENGTH + 1] = { 0 }; + + assert(tree != NULL); + len = tree->num_symbols; + for (i = 0; i < len; ++i) { + const int code_length = tree->code_lengths[i]; + assert(code_length <= MAX_ALLOWED_CODE_LENGTH); + ++depth_count[code_length]; + } + depth_count[0] = 0; // ignore unused symbol + next_code[0] = 0; + { + uint32_t code = 0; + for (i = 1; i <= MAX_ALLOWED_CODE_LENGTH; ++i) { + code = (code + depth_count[i - 1]) << 1; + next_code[i] = code; + } + } + for (i = 0; i < len; ++i) { + const int code_length = tree->code_lengths[i]; + tree->codes[i] = ReverseBits(code_length, next_code[code_length]++); + } +} + +// ----------------------------------------------------------------------------- +// Main entry point + +void VP8LCreateHuffmanTree(uint32_t* const histogram, int tree_depth_limit, + uint8_t* const buf_rle, HuffmanTree* const huff_tree, + HuffmanTreeCode* const huff_code) { + const int num_symbols = huff_code->num_symbols; + memset(buf_rle, 0, num_symbols * sizeof(*buf_rle)); + OptimizeHuffmanForRle(num_symbols, buf_rle, histogram); + GenerateOptimalTree(histogram, num_symbols, huff_tree, tree_depth_limit, + huff_code->code_lengths); + // Create the actual bit codes for the bit lengths. + ConvertBitDepthsToSymbols(huff_code); +} diff --git a/third-party/webp/libwebp/src/utils/huffman_encode_utils.h b/third-party/webp/libwebp/src/utils/huffman_encode_utils.h new file mode 100644 index 0000000000..3f7f1d8074 --- /dev/null +++ b/third-party/webp/libwebp/src/utils/huffman_encode_utils.h @@ -0,0 +1,60 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Jyrki Alakuijala (jyrki@google.com) +// +// Entropy encoding (Huffman) for webp lossless + +#ifndef WEBP_UTILS_HUFFMAN_ENCODE_UTILS_H_ +#define WEBP_UTILS_HUFFMAN_ENCODE_UTILS_H_ + +#include "src/webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Struct for holding the tree header in coded form. +typedef struct { + uint8_t code; // value (0..15) or escape code (16,17,18) + uint8_t extra_bits; // extra bits for escape codes +} HuffmanTreeToken; + +// Struct to represent the tree codes (depth and bits array). +typedef struct { + int num_symbols; // Number of symbols. + uint8_t* code_lengths; // Code lengths of the symbols. + uint16_t* codes; // Symbol Codes. +} HuffmanTreeCode; + +// Struct to represent the Huffman tree. +typedef struct { + uint32_t total_count_; // Symbol frequency. + int value_; // Symbol value. + int pool_index_left_; // Index for the left sub-tree. + int pool_index_right_; // Index for the right sub-tree. +} HuffmanTree; + +// Turn the Huffman tree into a token sequence. +// Returns the number of tokens used. +int VP8LCreateCompressedHuffmanTree(const HuffmanTreeCode* const tree, + HuffmanTreeToken* tokens, int max_tokens); + +// Create an optimized tree, and tokenize it. +// 'buf_rle' and 'huff_tree' are pre-allocated and the 'tree' is the constructed +// huffman code tree. +void VP8LCreateHuffmanTree(uint32_t* const histogram, int tree_depth_limit, + uint8_t* const buf_rle, HuffmanTree* const huff_tree, + HuffmanTreeCode* const huff_code); + +#ifdef __cplusplus +} +#endif + +#endif // WEBP_UTILS_HUFFMAN_ENCODE_UTILS_H_ diff --git a/third-party/webp/libwebp/src/utils/huffman_utils.c b/third-party/webp/libwebp/src/utils/huffman_utils.c new file mode 100644 index 0000000000..cf73abd437 --- /dev/null +++ b/third-party/webp/libwebp/src/utils/huffman_utils.c @@ -0,0 +1,296 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Utilities for building and looking up Huffman trees. +// +// Author: Urvang Joshi (urvang@google.com) + +#include +#include +#include +#include "src/utils/huffman_utils.h" +#include "src/utils/utils.h" +#include "src/webp/format_constants.h" + +// Huffman data read via DecodeImageStream is represented in two (red and green) +// bytes. +#define MAX_HTREE_GROUPS 0x10000 + +HTreeGroup* VP8LHtreeGroupsNew(int num_htree_groups) { + HTreeGroup* const htree_groups = + (HTreeGroup*)WebPSafeMalloc(num_htree_groups, sizeof(*htree_groups)); + if (htree_groups == NULL) { + return NULL; + } + assert(num_htree_groups <= MAX_HTREE_GROUPS); + return htree_groups; +} + +void VP8LHtreeGroupsFree(HTreeGroup* const htree_groups) { + if (htree_groups != NULL) { + WebPSafeFree(htree_groups); + } +} + +// Returns reverse(reverse(key, len) + 1, len), where reverse(key, len) is the +// bit-wise reversal of the len least significant bits of key. +static WEBP_INLINE uint32_t GetNextKey(uint32_t key, int len) { + uint32_t step = 1 << (len - 1); + while (key & step) { + step >>= 1; + } + return step ? (key & (step - 1)) + step : key; +} + +// Stores code in table[0], table[step], table[2*step], ..., table[end]. +// Assumes that end is an integer multiple of step. +static WEBP_INLINE void ReplicateValue(HuffmanCode* table, + int step, int end, + HuffmanCode code) { + assert(end % step == 0); + do { + end -= step; + table[end] = code; + } while (end > 0); +} + +// Returns the table width of the next 2nd level table. count is the histogram +// of bit lengths for the remaining symbols, len is the code length of the next +// processed symbol +static WEBP_INLINE int NextTableBitSize(const int* const count, + int len, int root_bits) { + int left = 1 << (len - root_bits); + while (len < MAX_ALLOWED_CODE_LENGTH) { + left -= count[len]; + if (left <= 0) break; + ++len; + left <<= 1; + } + return len - root_bits; +} + +// sorted[code_lengths_size] is a pre-allocated array for sorting symbols +// by code length. +static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits, + const int code_lengths[], int code_lengths_size, + uint16_t sorted[]) { + HuffmanCode* table = root_table; // next available space in table + int total_size = 1 << root_bits; // total size root table + 2nd level table + int len; // current code length + int symbol; // symbol index in original or sorted table + // number of codes of each length: + int count[MAX_ALLOWED_CODE_LENGTH + 1] = { 0 }; + // offsets in sorted table for each length: + int offset[MAX_ALLOWED_CODE_LENGTH + 1]; + + assert(code_lengths_size != 0); + assert(code_lengths != NULL); + assert((root_table != NULL && sorted != NULL) || + (root_table == NULL && sorted == NULL)); + assert(root_bits > 0); + + // Build histogram of code lengths. + for (symbol = 0; symbol < code_lengths_size; ++symbol) { + if (code_lengths[symbol] > MAX_ALLOWED_CODE_LENGTH) { + return 0; + } + ++count[code_lengths[symbol]]; + } + + // Error, all code lengths are zeros. + if (count[0] == code_lengths_size) { + return 0; + } + + // Generate offsets into sorted symbol table by code length. + offset[1] = 0; + for (len = 1; len < MAX_ALLOWED_CODE_LENGTH; ++len) { + if (count[len] > (1 << len)) { + return 0; + } + offset[len + 1] = offset[len] + count[len]; + } + + // Sort symbols by length, by symbol order within each length. + for (symbol = 0; symbol < code_lengths_size; ++symbol) { + const int symbol_code_length = code_lengths[symbol]; + if (code_lengths[symbol] > 0) { + if (sorted != NULL) { + sorted[offset[symbol_code_length]++] = symbol; + } else { + offset[symbol_code_length]++; + } + } + } + + // Special case code with only one value. + if (offset[MAX_ALLOWED_CODE_LENGTH] == 1) { + if (sorted != NULL) { + HuffmanCode code; + code.bits = 0; + code.value = (uint16_t)sorted[0]; + ReplicateValue(table, 1, total_size, code); + } + return total_size; + } + + { + int step; // step size to replicate values in current table + uint32_t low = 0xffffffffu; // low bits for current root entry + uint32_t mask = total_size - 1; // mask for low bits + uint32_t key = 0; // reversed prefix code + int num_nodes = 1; // number of Huffman tree nodes + int num_open = 1; // number of open branches in current tree level + int table_bits = root_bits; // key length of current table + int table_size = 1 << table_bits; // size of current table + symbol = 0; + // Fill in root table. + for (len = 1, step = 2; len <= root_bits; ++len, step <<= 1) { + num_open <<= 1; + num_nodes += num_open; + num_open -= count[len]; + if (num_open < 0) { + return 0; + } + if (root_table == NULL) continue; + for (; count[len] > 0; --count[len]) { + HuffmanCode code; + code.bits = (uint8_t)len; + code.value = (uint16_t)sorted[symbol++]; + ReplicateValue(&table[key], step, table_size, code); + key = GetNextKey(key, len); + } + } + + // Fill in 2nd level tables and add pointers to root table. + for (len = root_bits + 1, step = 2; len <= MAX_ALLOWED_CODE_LENGTH; + ++len, step <<= 1) { + num_open <<= 1; + num_nodes += num_open; + num_open -= count[len]; + if (num_open < 0) { + return 0; + } + for (; count[len] > 0; --count[len]) { + HuffmanCode code; + if ((key & mask) != low) { + if (root_table != NULL) table += table_size; + table_bits = NextTableBitSize(count, len, root_bits); + table_size = 1 << table_bits; + total_size += table_size; + low = key & mask; + if (root_table != NULL) { + root_table[low].bits = (uint8_t)(table_bits + root_bits); + root_table[low].value = (uint16_t)((table - root_table) - low); + } + } + if (root_table != NULL) { + code.bits = (uint8_t)(len - root_bits); + code.value = (uint16_t)sorted[symbol++]; + ReplicateValue(&table[key >> root_bits], step, table_size, code); + } + key = GetNextKey(key, len); + } + } + + // Check if tree is full. + if (num_nodes != 2 * offset[MAX_ALLOWED_CODE_LENGTH] - 1) { + return 0; + } + } + + return total_size; +} + +// Maximum code_lengths_size is 2328 (reached for 11-bit color_cache_bits). +// More commonly, the value is around ~280. +#define MAX_CODE_LENGTHS_SIZE \ + ((1 << MAX_CACHE_BITS) + NUM_LITERAL_CODES + NUM_LENGTH_CODES) +// Cut-off value for switching between heap and stack allocation. +#define SORTED_SIZE_CUTOFF 512 +int VP8LBuildHuffmanTable(HuffmanTables* const root_table, int root_bits, + const int code_lengths[], int code_lengths_size) { + const int total_size = + BuildHuffmanTable(NULL, root_bits, code_lengths, code_lengths_size, NULL); + assert(code_lengths_size <= MAX_CODE_LENGTHS_SIZE); + if (total_size == 0 || root_table == NULL) return total_size; + + if (root_table->curr_segment->curr_table + total_size >= + root_table->curr_segment->start + root_table->curr_segment->size) { + // If 'root_table' does not have enough memory, allocate a new segment. + // The available part of root_table->curr_segment is left unused because we + // need a contiguous buffer. + const int segment_size = root_table->curr_segment->size; + struct HuffmanTablesSegment* next = + (HuffmanTablesSegment*)WebPSafeMalloc(1, sizeof(*next)); + if (next == NULL) return 0; + // Fill the new segment. + // We need at least 'total_size' but if that value is small, it is better to + // allocate a big chunk to prevent more allocations later. 'segment_size' is + // therefore chosen (any other arbitrary value could be chosen). + next->size = total_size > segment_size ? total_size : segment_size; + next->start = + (HuffmanCode*)WebPSafeMalloc(next->size, sizeof(*next->start)); + if (next->start == NULL) { + WebPSafeFree(next); + return 0; + } + next->curr_table = next->start; + next->next = NULL; + // Point to the new segment. + root_table->curr_segment->next = next; + root_table->curr_segment = next; + } + if (code_lengths_size <= SORTED_SIZE_CUTOFF) { + // use local stack-allocated array. + uint16_t sorted[SORTED_SIZE_CUTOFF]; + BuildHuffmanTable(root_table->curr_segment->curr_table, root_bits, + code_lengths, code_lengths_size, sorted); + } else { // rare case. Use heap allocation. + uint16_t* const sorted = + (uint16_t*)WebPSafeMalloc(code_lengths_size, sizeof(*sorted)); + if (sorted == NULL) return 0; + BuildHuffmanTable(root_table->curr_segment->curr_table, root_bits, + code_lengths, code_lengths_size, sorted); + WebPSafeFree(sorted); + } + return total_size; +} + +int VP8LHuffmanTablesAllocate(int size, HuffmanTables* huffman_tables) { + // Have 'segment' point to the first segment for now, 'root'. + HuffmanTablesSegment* const root = &huffman_tables->root; + huffman_tables->curr_segment = root; + // Allocate root. + root->start = (HuffmanCode*)WebPSafeMalloc(size, sizeof(*root->start)); + if (root->start == NULL) return 0; + root->curr_table = root->start; + root->next = NULL; + root->size = size; + return 1; +} + +void VP8LHuffmanTablesDeallocate(HuffmanTables* const huffman_tables) { + HuffmanTablesSegment *current, *next; + if (huffman_tables == NULL) return; + // Free the root node. + current = &huffman_tables->root; + next = current->next; + WebPSafeFree(current->start); + current->start = NULL; + current->next = NULL; + current = next; + // Free the following nodes. + while (current != NULL) { + next = current->next; + WebPSafeFree(current->start); + WebPSafeFree(current); + current = next; + } +} diff --git a/third-party/webp/libwebp/src/utils/huffman_utils.h b/third-party/webp/libwebp/src/utils/huffman_utils.h new file mode 100644 index 0000000000..98415c5328 --- /dev/null +++ b/third-party/webp/libwebp/src/utils/huffman_utils.h @@ -0,0 +1,111 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Utilities for building and looking up Huffman trees. +// +// Author: Urvang Joshi (urvang@google.com) + +#ifndef WEBP_UTILS_HUFFMAN_UTILS_H_ +#define WEBP_UTILS_HUFFMAN_UTILS_H_ + +#include +#include "src/webp/format_constants.h" +#include "src/webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define HUFFMAN_TABLE_BITS 8 +#define HUFFMAN_TABLE_MASK ((1 << HUFFMAN_TABLE_BITS) - 1) + +#define LENGTHS_TABLE_BITS 7 +#define LENGTHS_TABLE_MASK ((1 << LENGTHS_TABLE_BITS) - 1) + + +// Huffman lookup table entry +typedef struct { + uint8_t bits; // number of bits used for this symbol + uint16_t value; // symbol value or table offset +} HuffmanCode; + +// long version for holding 32b values +typedef struct { + int bits; // number of bits used for this symbol, + // or an impossible value if not a literal code. + uint32_t value; // 32b packed ARGB value if literal, + // or non-literal symbol otherwise +} HuffmanCode32; + +// Contiguous memory segment of HuffmanCodes. +typedef struct HuffmanTablesSegment { + HuffmanCode* start; + // Pointer to where we are writing into the segment. Starts at 'start' and + // cannot go beyond 'start' + 'size'. + HuffmanCode* curr_table; + // Pointer to the next segment in the chain. + struct HuffmanTablesSegment* next; + int size; +} HuffmanTablesSegment; + +// Chained memory segments of HuffmanCodes. +typedef struct HuffmanTables { + HuffmanTablesSegment root; + // Currently processed segment. At first, this is 'root'. + HuffmanTablesSegment* curr_segment; +} HuffmanTables; + +// Allocates a HuffmanTables with 'size' contiguous HuffmanCodes. Returns 0 on +// memory allocation error, 1 otherwise. +int VP8LHuffmanTablesAllocate(int size, HuffmanTables* huffman_tables); +void VP8LHuffmanTablesDeallocate(HuffmanTables* const huffman_tables); + +#define HUFFMAN_PACKED_BITS 6 +#define HUFFMAN_PACKED_TABLE_SIZE (1u << HUFFMAN_PACKED_BITS) + +// Huffman table group. +// Includes special handling for the following cases: +// - is_trivial_literal: one common literal base for RED/BLUE/ALPHA (not GREEN) +// - is_trivial_code: only 1 code (no bit is read from bitstream) +// - use_packed_table: few enough literal symbols, so all the bit codes +// can fit into a small look-up table packed_table[] +// The common literal base, if applicable, is stored in 'literal_arb'. +typedef struct HTreeGroup HTreeGroup; +struct HTreeGroup { + HuffmanCode* htrees[HUFFMAN_CODES_PER_META_CODE]; + int is_trivial_literal; // True, if huffman trees for Red, Blue & Alpha + // Symbols are trivial (have a single code). + uint32_t literal_arb; // If is_trivial_literal is true, this is the + // ARGB value of the pixel, with Green channel + // being set to zero. + int is_trivial_code; // true if is_trivial_literal with only one code + int use_packed_table; // use packed table below for short literal code + // table mapping input bits to a packed values, or escape case to literal code + HuffmanCode32 packed_table[HUFFMAN_PACKED_TABLE_SIZE]; +}; + +// Creates the instance of HTreeGroup with specified number of tree-groups. +HTreeGroup* VP8LHtreeGroupsNew(int num_htree_groups); + +// Releases the memory allocated for HTreeGroup. +void VP8LHtreeGroupsFree(HTreeGroup* const htree_groups); + +// Builds Huffman lookup table assuming code lengths are in symbol order. +// The 'code_lengths' is pre-allocated temporary memory buffer used for creating +// the huffman table. +// Returns built table size or 0 in case of error (invalid tree or +// memory error). +int VP8LBuildHuffmanTable(HuffmanTables* const root_table, int root_bits, + const int code_lengths[], int code_lengths_size); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_UTILS_HUFFMAN_UTILS_H_ diff --git a/third-party/webp/libwebp/src/utils/palette.c b/third-party/webp/libwebp/src/utils/palette.c new file mode 100644 index 0000000000..515da21019 --- /dev/null +++ b/third-party/webp/libwebp/src/utils/palette.c @@ -0,0 +1,402 @@ +// Copyright 2023 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Utilities for palette analysis. +// +// Author: Vincent Rabaud (vrabaud@google.com) + +#include "src/utils/palette.h" + +#include +#include + +#include "src/dsp/lossless_common.h" +#include "src/utils/color_cache_utils.h" +#include "src/utils/utils.h" +#include "src/webp/encode.h" +#include "src/webp/format_constants.h" + +// ----------------------------------------------------------------------------- + +// Palette reordering for smaller sum of deltas (and for smaller storage). + +static int PaletteCompareColorsForQsort(const void* p1, const void* p2) { + const uint32_t a = WebPMemToUint32((uint8_t*)p1); + const uint32_t b = WebPMemToUint32((uint8_t*)p2); + assert(a != b); + return (a < b) ? -1 : 1; +} + +static WEBP_INLINE uint32_t PaletteComponentDistance(uint32_t v) { + return (v <= 128) ? v : (256 - v); +} + +// Computes a value that is related to the entropy created by the +// palette entry diff. +// +// Note that the last & 0xff is a no-operation in the next statement, but +// removed by most compilers and is here only for regularity of the code. +static WEBP_INLINE uint32_t PaletteColorDistance(uint32_t col1, uint32_t col2) { + const uint32_t diff = VP8LSubPixels(col1, col2); + const int kMoreWeightForRGBThanForAlpha = 9; + uint32_t score; + score = PaletteComponentDistance((diff >> 0) & 0xff); + score += PaletteComponentDistance((diff >> 8) & 0xff); + score += PaletteComponentDistance((diff >> 16) & 0xff); + score *= kMoreWeightForRGBThanForAlpha; + score += PaletteComponentDistance((diff >> 24) & 0xff); + return score; +} + +static WEBP_INLINE void SwapColor(uint32_t* const col1, uint32_t* const col2) { + const uint32_t tmp = *col1; + *col1 = *col2; + *col2 = tmp; +} + +int SearchColorNoIdx(const uint32_t sorted[], uint32_t color, int num_colors) { + int low = 0, hi = num_colors; + if (sorted[low] == color) return low; // loop invariant: sorted[low] != color + while (1) { + const int mid = (low + hi) >> 1; + if (sorted[mid] == color) { + return mid; + } else if (sorted[mid] < color) { + low = mid; + } else { + hi = mid; + } + } + assert(0); + return 0; +} + +void PrepareMapToPalette(const uint32_t palette[], uint32_t num_colors, + uint32_t sorted[], uint32_t idx_map[]) { + uint32_t i; + memcpy(sorted, palette, num_colors * sizeof(*sorted)); + qsort(sorted, num_colors, sizeof(*sorted), PaletteCompareColorsForQsort); + for (i = 0; i < num_colors; ++i) { + idx_map[SearchColorNoIdx(sorted, palette[i], num_colors)] = i; + } +} + +//------------------------------------------------------------------------------ + +#define COLOR_HASH_SIZE (MAX_PALETTE_SIZE * 4) +#define COLOR_HASH_RIGHT_SHIFT 22 // 32 - log2(COLOR_HASH_SIZE). + +int GetColorPalette(const WebPPicture* const pic, uint32_t* const palette) { + int i; + int x, y; + int num_colors = 0; + uint8_t in_use[COLOR_HASH_SIZE] = {0}; + uint32_t colors[COLOR_HASH_SIZE] = {0}; + const uint32_t* argb = pic->argb; + const int width = pic->width; + const int height = pic->height; + uint32_t last_pix = ~argb[0]; // so we're sure that last_pix != argb[0] + assert(pic != NULL); + assert(pic->use_argb); + + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + int key; + if (argb[x] == last_pix) { + continue; + } + last_pix = argb[x]; + key = VP8LHashPix(last_pix, COLOR_HASH_RIGHT_SHIFT); + while (1) { + if (!in_use[key]) { + colors[key] = last_pix; + in_use[key] = 1; + ++num_colors; + if (num_colors > MAX_PALETTE_SIZE) { + return MAX_PALETTE_SIZE + 1; // Exact count not needed. + } + break; + } else if (colors[key] == last_pix) { + break; // The color is already there. + } else { + // Some other color sits here, so do linear conflict resolution. + ++key; + key &= (COLOR_HASH_SIZE - 1); // Key mask. + } + } + } + argb += pic->argb_stride; + } + + if (palette != NULL) { // Fill the colors into palette. + num_colors = 0; + for (i = 0; i < COLOR_HASH_SIZE; ++i) { + if (in_use[i]) { + palette[num_colors] = colors[i]; + ++num_colors; + } + } + qsort(palette, num_colors, sizeof(*palette), PaletteCompareColorsForQsort); + } + return num_colors; +} + +#undef COLOR_HASH_SIZE +#undef COLOR_HASH_RIGHT_SHIFT + +// ----------------------------------------------------------------------------- + +// The palette has been sorted by alpha. This function checks if the other +// components of the palette have a monotonic development with regards to +// position in the palette. If all have monotonic development, there is +// no benefit to re-organize them greedily. A monotonic development +// would be spotted in green-only situations (like lossy alpha) or gray-scale +// images. +static int PaletteHasNonMonotonousDeltas(const uint32_t* const palette, + int num_colors) { + uint32_t predict = 0x000000; + int i; + uint8_t sign_found = 0x00; + for (i = 0; i < num_colors; ++i) { + const uint32_t diff = VP8LSubPixels(palette[i], predict); + const uint8_t rd = (diff >> 16) & 0xff; + const uint8_t gd = (diff >> 8) & 0xff; + const uint8_t bd = (diff >> 0) & 0xff; + if (rd != 0x00) { + sign_found |= (rd < 0x80) ? 1 : 2; + } + if (gd != 0x00) { + sign_found |= (gd < 0x80) ? 8 : 16; + } + if (bd != 0x00) { + sign_found |= (bd < 0x80) ? 64 : 128; + } + predict = palette[i]; + } + return (sign_found & (sign_found << 1)) != 0; // two consequent signs. +} + +static void PaletteSortMinimizeDeltas(const uint32_t* const palette_sorted, + int num_colors, uint32_t* const palette) { + uint32_t predict = 0x00000000; + int i, k; + memcpy(palette, palette_sorted, num_colors * sizeof(*palette)); + if (!PaletteHasNonMonotonousDeltas(palette_sorted, num_colors)) return; + // Find greedily always the closest color of the predicted color to minimize + // deltas in the palette. This reduces storage needs since the + // palette is stored with delta encoding. + for (i = 0; i < num_colors; ++i) { + int best_ix = i; + uint32_t best_score = ~0U; + for (k = i; k < num_colors; ++k) { + const uint32_t cur_score = PaletteColorDistance(palette[k], predict); + if (best_score > cur_score) { + best_score = cur_score; + best_ix = k; + } + } + SwapColor(&palette[best_ix], &palette[i]); + predict = palette[i]; + } +} + +// ----------------------------------------------------------------------------- +// Modified Zeng method from "A Survey on Palette Reordering +// Methods for Improving the Compression of Color-Indexed Images" by Armando J. +// Pinho and Antonio J. R. Neves. + +// Finds the biggest cooccurrence in the matrix. +static void CoOccurrenceFindMax(const uint32_t* const cooccurrence, + uint32_t num_colors, uint8_t* const c1, + uint8_t* const c2) { + // Find the index that is most frequently located adjacent to other + // (different) indexes. + uint32_t best_sum = 0u; + uint32_t i, j, best_cooccurrence; + *c1 = 0u; + for (i = 0; i < num_colors; ++i) { + uint32_t sum = 0; + for (j = 0; j < num_colors; ++j) sum += cooccurrence[i * num_colors + j]; + if (sum > best_sum) { + best_sum = sum; + *c1 = i; + } + } + // Find the index that is most frequently found adjacent to *c1. + *c2 = 0u; + best_cooccurrence = 0u; + for (i = 0; i < num_colors; ++i) { + if (cooccurrence[*c1 * num_colors + i] > best_cooccurrence) { + best_cooccurrence = cooccurrence[*c1 * num_colors + i]; + *c2 = i; + } + } + assert(*c1 != *c2); +} + +// Builds the cooccurrence matrix +static int CoOccurrenceBuild(const WebPPicture* const pic, + const uint32_t* const palette, uint32_t num_colors, + uint32_t* cooccurrence) { + uint32_t *lines, *line_top, *line_current, *line_tmp; + int x, y; + const uint32_t* src = pic->argb; + uint32_t prev_pix = ~src[0]; + uint32_t prev_idx = 0u; + uint32_t idx_map[MAX_PALETTE_SIZE] = {0}; + uint32_t palette_sorted[MAX_PALETTE_SIZE]; + lines = (uint32_t*)WebPSafeMalloc(2 * pic->width, sizeof(*lines)); + if (lines == NULL) { + return 0; + } + line_top = &lines[0]; + line_current = &lines[pic->width]; + PrepareMapToPalette(palette, num_colors, palette_sorted, idx_map); + for (y = 0; y < pic->height; ++y) { + for (x = 0; x < pic->width; ++x) { + const uint32_t pix = src[x]; + if (pix != prev_pix) { + prev_idx = idx_map[SearchColorNoIdx(palette_sorted, pix, num_colors)]; + prev_pix = pix; + } + line_current[x] = prev_idx; + // 4-connectivity is what works best as mentioned in "On the relation + // between Memon's and the modified Zeng's palette reordering methods". + if (x > 0 && prev_idx != line_current[x - 1]) { + const uint32_t left_idx = line_current[x - 1]; + ++cooccurrence[prev_idx * num_colors + left_idx]; + ++cooccurrence[left_idx * num_colors + prev_idx]; + } + if (y > 0 && prev_idx != line_top[x]) { + const uint32_t top_idx = line_top[x]; + ++cooccurrence[prev_idx * num_colors + top_idx]; + ++cooccurrence[top_idx * num_colors + prev_idx]; + } + } + line_tmp = line_top; + line_top = line_current; + line_current = line_tmp; + src += pic->argb_stride; + } + WebPSafeFree(lines); + return 1; +} + +struct Sum { + uint8_t index; + uint32_t sum; +}; + +static int PaletteSortModifiedZeng(const WebPPicture* const pic, + const uint32_t* const palette_in, + uint32_t num_colors, + uint32_t* const palette) { + uint32_t i, j, ind; + uint8_t remapping[MAX_PALETTE_SIZE]; + uint32_t* cooccurrence; + struct Sum sums[MAX_PALETTE_SIZE]; + uint32_t first, last; + uint32_t num_sums; + // TODO(vrabaud) check whether one color images should use palette or not. + if (num_colors <= 1) return 1; + // Build the co-occurrence matrix. + cooccurrence = + (uint32_t*)WebPSafeCalloc(num_colors * num_colors, sizeof(*cooccurrence)); + if (cooccurrence == NULL) { + return 0; + } + if (!CoOccurrenceBuild(pic, palette_in, num_colors, cooccurrence)) { + WebPSafeFree(cooccurrence); + return 0; + } + + // Initialize the mapping list with the two best indices. + CoOccurrenceFindMax(cooccurrence, num_colors, &remapping[0], &remapping[1]); + + // We need to append and prepend to the list of remapping. To this end, we + // actually define the next start/end of the list as indices in a vector (with + // a wrap around when the end is reached). + first = 0; + last = 1; + num_sums = num_colors - 2; // -2 because we know the first two values + if (num_sums > 0) { + // Initialize the sums with the first two remappings and find the best one + struct Sum* best_sum = &sums[0]; + best_sum->index = 0u; + best_sum->sum = 0u; + for (i = 0, j = 0; i < num_colors; ++i) { + if (i == remapping[0] || i == remapping[1]) continue; + sums[j].index = i; + sums[j].sum = cooccurrence[i * num_colors + remapping[0]] + + cooccurrence[i * num_colors + remapping[1]]; + if (sums[j].sum > best_sum->sum) best_sum = &sums[j]; + ++j; + } + + while (num_sums > 0) { + const uint8_t best_index = best_sum->index; + // Compute delta to know if we need to prepend or append the best index. + int32_t delta = 0; + const int32_t n = num_colors - num_sums; + for (ind = first, j = 0; (ind + j) % num_colors != last + 1; ++j) { + const uint16_t l_j = remapping[(ind + j) % num_colors]; + delta += (n - 1 - 2 * (int32_t)j) * + (int32_t)cooccurrence[best_index * num_colors + l_j]; + } + if (delta > 0) { + first = (first == 0) ? num_colors - 1 : first - 1; + remapping[first] = best_index; + } else { + ++last; + remapping[last] = best_index; + } + // Remove best_sum from sums. + *best_sum = sums[num_sums - 1]; + --num_sums; + // Update all the sums and find the best one. + best_sum = &sums[0]; + for (i = 0; i < num_sums; ++i) { + sums[i].sum += cooccurrence[best_index * num_colors + sums[i].index]; + if (sums[i].sum > best_sum->sum) best_sum = &sums[i]; + } + } + } + assert((last + 1) % num_colors == first); + WebPSafeFree(cooccurrence); + + // Re-map the palette. + for (i = 0; i < num_colors; ++i) { + palette[i] = palette_in[remapping[(first + i) % num_colors]]; + } + return 1; +} + +// ----------------------------------------------------------------------------- + +int PaletteSort(PaletteSorting method, const struct WebPPicture* const pic, + const uint32_t* const palette_sorted, uint32_t num_colors, + uint32_t* const palette) { + switch (method) { + case kSortedDefault: + // Nothing to do, we have already sorted the palette. + memcpy(palette, palette_sorted, num_colors * sizeof(*palette)); + return 1; + case kMinimizeDelta: + PaletteSortMinimizeDeltas(palette_sorted, num_colors, palette); + return 1; + case kModifiedZeng: + return PaletteSortModifiedZeng(pic, palette_sorted, num_colors, palette); + case kUnusedPalette: + case kPaletteSortingNum: + break; + } + + assert(0); + return 0; +} diff --git a/third-party/webp/libwebp/src/utils/palette.h b/third-party/webp/libwebp/src/utils/palette.h new file mode 100644 index 0000000000..34479e463f --- /dev/null +++ b/third-party/webp/libwebp/src/utils/palette.h @@ -0,0 +1,60 @@ +// Copyright 2023 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Utilities for palette analysis. +// +// Author: Vincent Rabaud (vrabaud@google.com) + +#ifndef WEBP_UTILS_PALETTE_H_ +#define WEBP_UTILS_PALETTE_H_ + +#include "src/webp/types.h" + +struct WebPPicture; + +// The different ways a palette can be sorted. +typedef enum PaletteSorting { + kSortedDefault = 0, + // Sorts by minimizing L1 deltas between consecutive colors, giving more + // weight to RGB colors. + kMinimizeDelta = 1, + // Implements the modified Zeng method from "A Survey on Palette Reordering + // Methods for Improving the Compression of Color-Indexed Images" by Armando + // J. Pinho and Antonio J. R. Neves. + kModifiedZeng = 2, + kUnusedPalette = 3, + kPaletteSortingNum = 4 +} PaletteSorting; + +// Returns the index of 'color' in the sorted palette 'sorted' of size +// 'num_colors'. +int SearchColorNoIdx(const uint32_t sorted[], uint32_t color, int num_colors); + +// Sort palette in increasing order and prepare an inverse mapping array. +void PrepareMapToPalette(const uint32_t palette[], uint32_t num_colors, + uint32_t sorted[], uint32_t idx_map[]); + +// Returns count of unique colors in 'pic', assuming pic->use_argb is true. +// If the unique color count is more than MAX_PALETTE_SIZE, returns +// MAX_PALETTE_SIZE+1. +// If 'palette' is not NULL and the number of unique colors is less than or +// equal to MAX_PALETTE_SIZE, also outputs the actual unique colors into +// 'palette' in a sorted order. Note: 'palette' is assumed to be an array +// already allocated with at least MAX_PALETTE_SIZE elements. +int GetColorPalette(const struct WebPPicture* const pic, + uint32_t* const palette); + +// Sorts the palette according to the criterion defined by 'method'. +// 'palette_sorted' is the input palette sorted lexicographically, as done in +// PrepareMapToPalette. Returns 0 on memory allocation error. +int PaletteSort(PaletteSorting method, const struct WebPPicture* const pic, + const uint32_t* const palette_sorted, uint32_t num_colors, + uint32_t* const palette); + +#endif // WEBP_UTILS_PALETTE_H_ diff --git a/third-party/webp/libwebp/src/utils/quant_levels_dec_utils.c b/third-party/webp/libwebp/src/utils/quant_levels_dec_utils.c new file mode 100644 index 0000000000..97e7893704 --- /dev/null +++ b/third-party/webp/libwebp/src/utils/quant_levels_dec_utils.c @@ -0,0 +1,291 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Implement gradient smoothing: we replace a current alpha value by its +// surrounding average if it's close enough (that is: the change will be less +// than the minimum distance between two quantized level). +// We use sliding window for computing the 2d moving average. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/utils/quant_levels_dec_utils.h" + +#include // for memset + +#include "src/utils/utils.h" + +// #define USE_DITHERING // uncomment to enable ordered dithering (not vital) + +#define FIX 16 // fix-point precision for averaging +#define LFIX 2 // extra precision for look-up table +#define LUT_SIZE ((1 << (8 + LFIX)) - 1) // look-up table size + +#if defined(USE_DITHERING) + +#define DFIX 4 // extra precision for ordered dithering +#define DSIZE 4 // dithering size (must be a power of two) +// cf. https://en.wikipedia.org/wiki/Ordered_dithering +static const uint8_t kOrderedDither[DSIZE][DSIZE] = { + { 0, 8, 2, 10 }, // coefficients are in DFIX fixed-point precision + { 12, 4, 14, 6 }, + { 3, 11, 1, 9 }, + { 15, 7, 13, 5 } +}; + +#else +#define DFIX 0 +#endif + +typedef struct { + int width_, height_; // dimension + int stride_; // stride in bytes + int row_; // current input row being processed + uint8_t* src_; // input pointer + uint8_t* dst_; // output pointer + + int radius_; // filter radius (=delay) + int scale_; // normalization factor, in FIX bits precision + + void* mem_; // all memory + + // various scratch buffers + uint16_t* start_; + uint16_t* cur_; + uint16_t* end_; + uint16_t* top_; + uint16_t* average_; + + // input levels distribution + int num_levels_; // number of quantized levels + int min_, max_; // min and max level values + int min_level_dist_; // smallest distance between two consecutive levels + + int16_t* correction_; // size = 1 + 2*LUT_SIZE -> ~4k memory +} SmoothParams; + +//------------------------------------------------------------------------------ + +#define CLIP_8b_MASK (int)(~0U << (8 + DFIX)) +static WEBP_INLINE uint8_t clip_8b(int v) { + return (!(v & CLIP_8b_MASK)) ? (uint8_t)(v >> DFIX) : (v < 0) ? 0u : 255u; +} +#undef CLIP_8b_MASK + +// vertical accumulation +static void VFilter(SmoothParams* const p) { + const uint8_t* src = p->src_; + const int w = p->width_; + uint16_t* const cur = p->cur_; + const uint16_t* const top = p->top_; + uint16_t* const out = p->end_; + uint16_t sum = 0; // all arithmetic is modulo 16bit + int x; + + for (x = 0; x < w; ++x) { + uint16_t new_value; + sum += src[x]; + new_value = top[x] + sum; + out[x] = new_value - cur[x]; // vertical sum of 'r' pixels. + cur[x] = new_value; + } + // move input pointers one row down + p->top_ = p->cur_; + p->cur_ += w; + if (p->cur_ == p->end_) p->cur_ = p->start_; // roll-over + // We replicate edges, as it's somewhat easier as a boundary condition. + // That's why we don't update the 'src' pointer on top/bottom area: + if (p->row_ >= 0 && p->row_ < p->height_ - 1) { + p->src_ += p->stride_; + } +} + +// horizontal accumulation. We use mirror replication of missing pixels, as it's +// a little easier to implement (surprisingly). +static void HFilter(SmoothParams* const p) { + const uint16_t* const in = p->end_; + uint16_t* const out = p->average_; + const uint32_t scale = p->scale_; + const int w = p->width_; + const int r = p->radius_; + + int x; + for (x = 0; x <= r; ++x) { // left mirroring + const uint16_t delta = in[x + r - 1] + in[r - x]; + out[x] = (delta * scale) >> FIX; + } + for (; x < w - r; ++x) { // bulk middle run + const uint16_t delta = in[x + r] - in[x - r - 1]; + out[x] = (delta * scale) >> FIX; + } + for (; x < w; ++x) { // right mirroring + const uint16_t delta = + 2 * in[w - 1] - in[2 * w - 2 - r - x] - in[x - r - 1]; + out[x] = (delta * scale) >> FIX; + } +} + +// emit one filtered output row +static void ApplyFilter(SmoothParams* const p) { + const uint16_t* const average = p->average_; + const int w = p->width_; + const int16_t* const correction = p->correction_; +#if defined(USE_DITHERING) + const uint8_t* const dither = kOrderedDither[p->row_ % DSIZE]; +#endif + uint8_t* const dst = p->dst_; + int x; + for (x = 0; x < w; ++x) { + const int v = dst[x]; + if (v < p->max_ && v > p->min_) { + const int c = (v << DFIX) + correction[average[x] - (v << LFIX)]; +#if defined(USE_DITHERING) + dst[x] = clip_8b(c + dither[x % DSIZE]); +#else + dst[x] = clip_8b(c); +#endif + } + } + p->dst_ += p->stride_; // advance output pointer +} + +//------------------------------------------------------------------------------ +// Initialize correction table + +static void InitCorrectionLUT(int16_t* const lut, int min_dist) { + // The correction curve is: + // f(x) = x for x <= threshold2 + // f(x) = 0 for x >= threshold1 + // and a linear interpolation for range x=[threshold2, threshold1] + // (along with f(-x) = -f(x) symmetry). + // Note that: threshold2 = 3/4 * threshold1 + const int threshold1 = min_dist << LFIX; + const int threshold2 = (3 * threshold1) >> 2; + const int max_threshold = threshold2 << DFIX; + const int delta = threshold1 - threshold2; + int i; + for (i = 1; i <= LUT_SIZE; ++i) { + int c = (i <= threshold2) ? (i << DFIX) + : (i < threshold1) ? max_threshold * (threshold1 - i) / delta + : 0; + c >>= LFIX; + lut[+i] = +c; + lut[-i] = -c; + } + lut[0] = 0; +} + +static void CountLevels(SmoothParams* const p) { + int i, j, last_level; + uint8_t used_levels[256] = { 0 }; + const uint8_t* data = p->src_; + p->min_ = 255; + p->max_ = 0; + for (j = 0; j < p->height_; ++j) { + for (i = 0; i < p->width_; ++i) { + const int v = data[i]; + if (v < p->min_) p->min_ = v; + if (v > p->max_) p->max_ = v; + used_levels[v] = 1; + } + data += p->stride_; + } + // Compute the mininum distance between two non-zero levels. + p->min_level_dist_ = p->max_ - p->min_; + last_level = -1; + for (i = 0; i < 256; ++i) { + if (used_levels[i]) { + ++p->num_levels_; + if (last_level >= 0) { + const int level_dist = i - last_level; + if (level_dist < p->min_level_dist_) { + p->min_level_dist_ = level_dist; + } + } + last_level = i; + } + } +} + +// Initialize all params. +static int InitParams(uint8_t* const data, int width, int height, int stride, + int radius, SmoothParams* const p) { + const int R = 2 * radius + 1; // total size of the kernel + + const size_t size_scratch_m = (R + 1) * width * sizeof(*p->start_); + const size_t size_m = width * sizeof(*p->average_); + const size_t size_lut = (1 + 2 * LUT_SIZE) * sizeof(*p->correction_); + const size_t total_size = size_scratch_m + size_m + size_lut; + uint8_t* mem = (uint8_t*)WebPSafeMalloc(1U, total_size); + + if (mem == NULL) return 0; + p->mem_ = (void*)mem; + + p->start_ = (uint16_t*)mem; + p->cur_ = p->start_; + p->end_ = p->start_ + R * width; + p->top_ = p->end_ - width; + memset(p->top_, 0, width * sizeof(*p->top_)); + mem += size_scratch_m; + + p->average_ = (uint16_t*)mem; + mem += size_m; + + p->width_ = width; + p->height_ = height; + p->stride_ = stride; + p->src_ = data; + p->dst_ = data; + p->radius_ = radius; + p->scale_ = (1 << (FIX + LFIX)) / (R * R); // normalization constant + p->row_ = -radius; + + // analyze the input distribution so we can best-fit the threshold + CountLevels(p); + + // correction table + p->correction_ = ((int16_t*)mem) + LUT_SIZE; + InitCorrectionLUT(p->correction_, p->min_level_dist_); + + return 1; +} + +static void CleanupParams(SmoothParams* const p) { + WebPSafeFree(p->mem_); +} + +int WebPDequantizeLevels(uint8_t* const data, int width, int height, int stride, + int strength) { + int radius = 4 * strength / 100; + + if (strength < 0 || strength > 100) return 0; + if (data == NULL || width <= 0 || height <= 0) return 0; // bad params + + // limit the filter size to not exceed the image dimensions + if (2 * radius + 1 > width) radius = (width - 1) >> 1; + if (2 * radius + 1 > height) radius = (height - 1) >> 1; + + if (radius > 0) { + SmoothParams p; + memset(&p, 0, sizeof(p)); + if (!InitParams(data, width, height, stride, radius, &p)) return 0; + if (p.num_levels_ > 2) { + for (; p.row_ < p.height_; ++p.row_) { + VFilter(&p); // accumulate average of input + // Need to wait few rows in order to prime the filter, + // before emitting some output. + if (p.row_ >= p.radius_) { + HFilter(&p); + ApplyFilter(&p); + } + } + } + CleanupParams(&p); + } + return 1; +} diff --git a/third-party/webp/libwebp/src/utils/quant_levels_dec_utils.h b/third-party/webp/libwebp/src/utils/quant_levels_dec_utils.h new file mode 100644 index 0000000000..327f19f336 --- /dev/null +++ b/third-party/webp/libwebp/src/utils/quant_levels_dec_utils.h @@ -0,0 +1,35 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Alpha plane de-quantization utility +// +// Author: Vikas Arora (vikasa@google.com) + +#ifndef WEBP_UTILS_QUANT_LEVELS_DEC_UTILS_H_ +#define WEBP_UTILS_QUANT_LEVELS_DEC_UTILS_H_ + +#include "src/webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Apply post-processing to input 'data' of size 'width'x'height' assuming that +// the source was quantized to a reduced number of levels. 'stride' is in bytes. +// Strength is in [0..100] and controls the amount of dithering applied. +// Returns false in case of error (data is NULL, invalid parameters, +// malloc failure, ...). +int WebPDequantizeLevels(uint8_t* const data, int width, int height, int stride, + int strength); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_UTILS_QUANT_LEVELS_DEC_UTILS_H_ diff --git a/third-party/webp/libwebp/src/utils/quant_levels_utils.c b/third-party/webp/libwebp/src/utils/quant_levels_utils.c new file mode 100644 index 0000000000..d65ad3c29d --- /dev/null +++ b/third-party/webp/libwebp/src/utils/quant_levels_utils.c @@ -0,0 +1,140 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Quantize levels for specified number of quantization-levels ([2, 256]). +// Min and max values are preserved (usual 0 and 255 for alpha plane). +// +// Author: Skal (pascal.massimino@gmail.com) + +#include + +#include "src/utils/quant_levels_utils.h" + +#define NUM_SYMBOLS 256 + +#define MAX_ITER 6 // Maximum number of convergence steps. +#define ERROR_THRESHOLD 1e-4 // MSE stopping criterion. + +// ----------------------------------------------------------------------------- +// Quantize levels. + +int QuantizeLevels(uint8_t* const data, int width, int height, + int num_levels, uint64_t* const sse) { + int freq[NUM_SYMBOLS] = { 0 }; + int q_level[NUM_SYMBOLS] = { 0 }; + double inv_q_level[NUM_SYMBOLS] = { 0 }; + int min_s = 255, max_s = 0; + const size_t data_size = height * width; + int i, num_levels_in, iter; + double last_err = 1.e38, err = 0.; + const double err_threshold = ERROR_THRESHOLD * data_size; + + if (data == NULL) { + return 0; + } + + if (width <= 0 || height <= 0) { + return 0; + } + + if (num_levels < 2 || num_levels > 256) { + return 0; + } + + { + size_t n; + num_levels_in = 0; + for (n = 0; n < data_size; ++n) { + num_levels_in += (freq[data[n]] == 0); + if (min_s > data[n]) min_s = data[n]; + if (max_s < data[n]) max_s = data[n]; + ++freq[data[n]]; + } + } + + if (num_levels_in <= num_levels) goto End; // nothing to do! + + // Start with uniformly spread centroids. + for (i = 0; i < num_levels; ++i) { + inv_q_level[i] = min_s + (double)(max_s - min_s) * i / (num_levels - 1); + } + + // Fixed values. Won't be changed. + q_level[min_s] = 0; + q_level[max_s] = num_levels - 1; + assert(inv_q_level[0] == min_s); + assert(inv_q_level[num_levels - 1] == max_s); + + // k-Means iterations. + for (iter = 0; iter < MAX_ITER; ++iter) { + double q_sum[NUM_SYMBOLS] = { 0 }; + double q_count[NUM_SYMBOLS] = { 0 }; + int s, slot = 0; + + // Assign classes to representatives. + for (s = min_s; s <= max_s; ++s) { + // Keep track of the nearest neighbour 'slot' + while (slot < num_levels - 1 && + 2 * s > inv_q_level[slot] + inv_q_level[slot + 1]) { + ++slot; + } + if (freq[s] > 0) { + q_sum[slot] += s * freq[s]; + q_count[slot] += freq[s]; + } + q_level[s] = slot; + } + + // Assign new representatives to classes. + if (num_levels > 2) { + for (slot = 1; slot < num_levels - 1; ++slot) { + const double count = q_count[slot]; + if (count > 0.) { + inv_q_level[slot] = q_sum[slot] / count; + } + } + } + + // Compute convergence error. + err = 0.; + for (s = min_s; s <= max_s; ++s) { + const double error = s - inv_q_level[q_level[s]]; + err += freq[s] * error * error; + } + + // Check for convergence: we stop as soon as the error is no + // longer improving. + if (last_err - err < err_threshold) break; + last_err = err; + } + + // Remap the alpha plane to quantized values. + { + // double->int rounding operation can be costly, so we do it + // once for all before remapping. We also perform the data[] -> slot + // mapping, while at it (avoid one indirection in the final loop). + uint8_t map[NUM_SYMBOLS]; + int s; + size_t n; + for (s = min_s; s <= max_s; ++s) { + const int slot = q_level[s]; + map[s] = (uint8_t)(inv_q_level[slot] + .5); + } + // Final pass. + for (n = 0; n < data_size; ++n) { + data[n] = map[data[n]]; + } + } + End: + // Store sum of squared error if needed. + if (sse != NULL) *sse = (uint64_t)err; + + return 1; +} + diff --git a/third-party/webp/libwebp/src/utils/quant_levels_utils.h b/third-party/webp/libwebp/src/utils/quant_levels_utils.h new file mode 100644 index 0000000000..9ee3ea0075 --- /dev/null +++ b/third-party/webp/libwebp/src/utils/quant_levels_utils.h @@ -0,0 +1,36 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Alpha plane quantization utility +// +// Author: Vikas Arora (vikasa@google.com) + +#ifndef WEBP_UTILS_QUANT_LEVELS_UTILS_H_ +#define WEBP_UTILS_QUANT_LEVELS_UTILS_H_ + +#include + +#include "src/webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Replace the input 'data' of size 'width'x'height' with 'num-levels' +// quantized values. If not NULL, 'sse' will contain the sum of squared error. +// Valid range for 'num_levels' is [2, 256]. +// Returns false in case of error (data is NULL, or parameters are invalid). +int QuantizeLevels(uint8_t* const data, int width, int height, int num_levels, + uint64_t* const sse); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_UTILS_QUANT_LEVELS_UTILS_H_ diff --git a/third-party/webp/libwebp/src/utils/random_utils.c b/third-party/webp/libwebp/src/utils/random_utils.c new file mode 100644 index 0000000000..7edb3fefbb --- /dev/null +++ b/third-party/webp/libwebp/src/utils/random_utils.c @@ -0,0 +1,43 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Pseudo-random utilities +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include "src/utils/random_utils.h" + +//------------------------------------------------------------------------------ + +// 31b-range values +static const uint32_t kRandomTable[VP8_RANDOM_TABLE_SIZE] = { + 0x0de15230, 0x03b31886, 0x775faccb, 0x1c88626a, 0x68385c55, 0x14b3b828, + 0x4a85fef8, 0x49ddb84b, 0x64fcf397, 0x5c550289, 0x4a290000, 0x0d7ec1da, + 0x5940b7ab, 0x5492577d, 0x4e19ca72, 0x38d38c69, 0x0c01ee65, 0x32a1755f, + 0x5437f652, 0x5abb2c32, 0x0faa57b1, 0x73f533e7, 0x685feeda, 0x7563cce2, + 0x6e990e83, 0x4730a7ed, 0x4fc0d9c6, 0x496b153c, 0x4f1403fa, 0x541afb0c, + 0x73990b32, 0x26d7cb1c, 0x6fcc3706, 0x2cbb77d8, 0x75762f2a, 0x6425ccdd, + 0x24b35461, 0x0a7d8715, 0x220414a8, 0x141ebf67, 0x56b41583, 0x73e502e3, + 0x44cab16f, 0x28264d42, 0x73baaefb, 0x0a50ebed, 0x1d6ab6fb, 0x0d3ad40b, + 0x35db3b68, 0x2b081e83, 0x77ce6b95, 0x5181e5f0, 0x78853bbc, 0x009f9494, + 0x27e5ed3c +}; + +void VP8InitRandom(VP8Random* const rg, float dithering) { + memcpy(rg->tab_, kRandomTable, sizeof(rg->tab_)); + rg->index1_ = 0; + rg->index2_ = 31; + rg->amp_ = (dithering < 0.0) ? 0 + : (dithering > 1.0) ? (1 << VP8_RANDOM_DITHER_FIX) + : (uint32_t)((1 << VP8_RANDOM_DITHER_FIX) * dithering); +} + +//------------------------------------------------------------------------------ + diff --git a/third-party/webp/libwebp/src/utils/random_utils.h b/third-party/webp/libwebp/src/utils/random_utils.h new file mode 100644 index 0000000000..a5006f84f7 --- /dev/null +++ b/third-party/webp/libwebp/src/utils/random_utils.h @@ -0,0 +1,63 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Pseudo-random utilities +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_UTILS_RANDOM_UTILS_H_ +#define WEBP_UTILS_RANDOM_UTILS_H_ + +#include +#include "src/webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define VP8_RANDOM_DITHER_FIX 8 // fixed-point precision for dithering +#define VP8_RANDOM_TABLE_SIZE 55 + +typedef struct { + int index1_, index2_; + uint32_t tab_[VP8_RANDOM_TABLE_SIZE]; + int amp_; +} VP8Random; + +// Initializes random generator with an amplitude 'dithering' in range [0..1]. +void VP8InitRandom(VP8Random* const rg, float dithering); + +// Returns a centered pseudo-random number with 'num_bits' amplitude. +// (uses D.Knuth's Difference-based random generator). +// 'amp' is in VP8_RANDOM_DITHER_FIX fixed-point precision. +static WEBP_INLINE int VP8RandomBits2(VP8Random* const rg, int num_bits, + int amp) { + int diff; + assert(num_bits + VP8_RANDOM_DITHER_FIX <= 31); + diff = rg->tab_[rg->index1_] - rg->tab_[rg->index2_]; + if (diff < 0) diff += (1u << 31); + rg->tab_[rg->index1_] = diff; + if (++rg->index1_ == VP8_RANDOM_TABLE_SIZE) rg->index1_ = 0; + if (++rg->index2_ == VP8_RANDOM_TABLE_SIZE) rg->index2_ = 0; + // sign-extend, 0-center + diff = (int)((uint32_t)diff << 1) >> (32 - num_bits); + diff = (diff * amp) >> VP8_RANDOM_DITHER_FIX; // restrict range + diff += 1 << (num_bits - 1); // shift back to 0.5-center + return diff; +} + +static WEBP_INLINE int VP8RandomBits(VP8Random* const rg, int num_bits) { + return VP8RandomBits2(rg, num_bits, rg->amp_); +} + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_UTILS_RANDOM_UTILS_H_ diff --git a/third-party/webp/libwebp/src/utils/rescaler_utils.c b/third-party/webp/libwebp/src/utils/rescaler_utils.c new file mode 100644 index 0000000000..a0581a14b1 --- /dev/null +++ b/third-party/webp/libwebp/src/utils/rescaler_utils.c @@ -0,0 +1,160 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Rescaling functions +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include +#include +#include +#include "src/dsp/dsp.h" +#include "src/utils/rescaler_utils.h" +#include "src/utils/utils.h" + +//------------------------------------------------------------------------------ + +int WebPRescalerInit(WebPRescaler* const rescaler, + int src_width, int src_height, + uint8_t* const dst, + int dst_width, int dst_height, int dst_stride, + int num_channels, rescaler_t* const work) { + const int x_add = src_width, x_sub = dst_width; + const int y_add = src_height, y_sub = dst_height; + const uint64_t total_size = 2ull * dst_width * num_channels * sizeof(*work); + if (!CheckSizeOverflow(total_size)) return 0; + + rescaler->x_expand = (src_width < dst_width); + rescaler->y_expand = (src_height < dst_height); + rescaler->src_width = src_width; + rescaler->src_height = src_height; + rescaler->dst_width = dst_width; + rescaler->dst_height = dst_height; + rescaler->src_y = 0; + rescaler->dst_y = 0; + rescaler->dst = dst; + rescaler->dst_stride = dst_stride; + rescaler->num_channels = num_channels; + + // for 'x_expand', we use bilinear interpolation + rescaler->x_add = rescaler->x_expand ? (x_sub - 1) : x_add; + rescaler->x_sub = rescaler->x_expand ? (x_add - 1) : x_sub; + if (!rescaler->x_expand) { // fx_scale is not used otherwise + rescaler->fx_scale = WEBP_RESCALER_FRAC(1, rescaler->x_sub); + } + // vertical scaling parameters + rescaler->y_add = rescaler->y_expand ? y_add - 1 : y_add; + rescaler->y_sub = rescaler->y_expand ? y_sub - 1 : y_sub; + rescaler->y_accum = rescaler->y_expand ? rescaler->y_sub : rescaler->y_add; + if (!rescaler->y_expand) { + // This is WEBP_RESCALER_FRAC(dst_height, x_add * y_add) without the cast. + // Its value is <= WEBP_RESCALER_ONE, because dst_height <= rescaler->y_add + // and rescaler->x_add >= 1; + const uint64_t num = (uint64_t)dst_height * WEBP_RESCALER_ONE; + const uint64_t den = (uint64_t)rescaler->x_add * rescaler->y_add; + const uint64_t ratio = num / den; + if (ratio != (uint32_t)ratio) { + // When ratio == WEBP_RESCALER_ONE, we can't represent the ratio with the + // current fixed-point precision. This happens when src_height == + // rescaler->y_add (which == src_height), and rescaler->x_add == 1. + // => We special-case fxy_scale = 0, in WebPRescalerExportRow(). + rescaler->fxy_scale = 0; + } else { + rescaler->fxy_scale = (uint32_t)ratio; + } + rescaler->fy_scale = WEBP_RESCALER_FRAC(1, rescaler->y_sub); + } else { + rescaler->fy_scale = WEBP_RESCALER_FRAC(1, rescaler->x_add); + // rescaler->fxy_scale is unused here. + } + rescaler->irow = work; + rescaler->frow = work + num_channels * dst_width; + memset(work, 0, (size_t)total_size); + + WebPRescalerDspInit(); + return 1; +} + +int WebPRescalerGetScaledDimensions(int src_width, int src_height, + int* const scaled_width, + int* const scaled_height) { + assert(scaled_width != NULL); + assert(scaled_height != NULL); + { + int width = *scaled_width; + int height = *scaled_height; + const int max_size = INT_MAX / 2; + + // if width is unspecified, scale original proportionally to height ratio. + if (width == 0 && src_height > 0) { + width = + (int)(((uint64_t)src_width * height + src_height - 1) / src_height); + } + // if height is unspecified, scale original proportionally to width ratio. + if (height == 0 && src_width > 0) { + height = + (int)(((uint64_t)src_height * width + src_width - 1) / src_width); + } + // Check if the overall dimensions still make sense. + if (width <= 0 || height <= 0 || width > max_size || height > max_size) { + return 0; + } + + *scaled_width = width; + *scaled_height = height; + return 1; + } +} + +//------------------------------------------------------------------------------ +// all-in-one calls + +int WebPRescaleNeededLines(const WebPRescaler* const rescaler, + int max_num_lines) { + const int num_lines = + (rescaler->y_accum + rescaler->y_sub - 1) / rescaler->y_sub; + return (num_lines > max_num_lines) ? max_num_lines : num_lines; +} + +int WebPRescalerImport(WebPRescaler* const rescaler, int num_lines, + const uint8_t* src, int src_stride) { + int total_imported = 0; + while (total_imported < num_lines && + !WebPRescalerHasPendingOutput(rescaler)) { + if (rescaler->y_expand) { + rescaler_t* const tmp = rescaler->irow; + rescaler->irow = rescaler->frow; + rescaler->frow = tmp; + } + WebPRescalerImportRow(rescaler, src); + if (!rescaler->y_expand) { // Accumulate the contribution of the new row. + int x; + for (x = 0; x < rescaler->num_channels * rescaler->dst_width; ++x) { + rescaler->irow[x] += rescaler->frow[x]; + } + } + ++rescaler->src_y; + src += src_stride; + ++total_imported; + rescaler->y_accum -= rescaler->y_sub; + } + return total_imported; +} + +int WebPRescalerExport(WebPRescaler* const rescaler) { + int total_exported = 0; + while (WebPRescalerHasPendingOutput(rescaler)) { + WebPRescalerExportRow(rescaler); + ++total_exported; + } + return total_exported; +} + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/src/utils/rescaler_utils.h b/third-party/webp/libwebp/src/utils/rescaler_utils.h new file mode 100644 index 0000000000..ef201ef86c --- /dev/null +++ b/third-party/webp/libwebp/src/utils/rescaler_utils.h @@ -0,0 +1,102 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Rescaling functions +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_UTILS_RESCALER_UTILS_H_ +#define WEBP_UTILS_RESCALER_UTILS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "src/webp/types.h" + +#define WEBP_RESCALER_RFIX 32 // fixed-point precision for multiplies +#define WEBP_RESCALER_ONE (1ull << WEBP_RESCALER_RFIX) +#define WEBP_RESCALER_FRAC(x, y) \ + ((uint32_t)(((uint64_t)(x) << WEBP_RESCALER_RFIX) / (y))) + +// Structure used for on-the-fly rescaling +typedef uint32_t rescaler_t; // type for side-buffer +typedef struct WebPRescaler WebPRescaler; +struct WebPRescaler { + int x_expand; // true if we're expanding in the x direction + int y_expand; // true if we're expanding in the y direction + int num_channels; // bytes to jump between pixels + uint32_t fx_scale; // fixed-point scaling factors + uint32_t fy_scale; // '' + uint32_t fxy_scale; // '' + int y_accum; // vertical accumulator + int y_add, y_sub; // vertical increments + int x_add, x_sub; // horizontal increments + int src_width, src_height; // source dimensions + int dst_width, dst_height; // destination dimensions + int src_y, dst_y; // row counters for input and output + uint8_t* dst; + int dst_stride; + rescaler_t* irow, *frow; // work buffer +}; + +// Initialize a rescaler given scratch area 'work' and dimensions of src & dst. +// Returns false in case of error. +int WebPRescalerInit(WebPRescaler* const rescaler, + int src_width, int src_height, + uint8_t* const dst, + int dst_width, int dst_height, int dst_stride, + int num_channels, + rescaler_t* const work); + +// If either 'scaled_width' or 'scaled_height' (but not both) is 0 the value +// will be calculated preserving the aspect ratio, otherwise the values are +// left unmodified. Returns true on success, false if either value is 0 after +// performing the scaling calculation. +int WebPRescalerGetScaledDimensions(int src_width, int src_height, + int* const scaled_width, + int* const scaled_height); + +// Returns the number of input lines needed next to produce one output line, +// considering that the maximum available input lines are 'max_num_lines'. +int WebPRescaleNeededLines(const WebPRescaler* const rescaler, + int max_num_lines); + +// Import multiple rows over all channels, until at least one row is ready to +// be exported. Returns the actual number of lines that were imported. +int WebPRescalerImport(WebPRescaler* const rescaler, int num_rows, + const uint8_t* src, int src_stride); + +// Export as many rows as possible. Return the numbers of rows written. +int WebPRescalerExport(WebPRescaler* const rescaler); + +// Return true if input is finished +static WEBP_INLINE +int WebPRescalerInputDone(const WebPRescaler* const rescaler) { + return (rescaler->src_y >= rescaler->src_height); +} +// Return true if output is finished +static WEBP_INLINE +int WebPRescalerOutputDone(const WebPRescaler* const rescaler) { + return (rescaler->dst_y >= rescaler->dst_height); +} + +// Return true if there are pending output rows ready. +static WEBP_INLINE +int WebPRescalerHasPendingOutput(const WebPRescaler* const rescaler) { + return !WebPRescalerOutputDone(rescaler) && (rescaler->y_accum <= 0); +} + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_UTILS_RESCALER_UTILS_H_ diff --git a/third-party/webp/libwebp/src/utils/thread_utils.c b/third-party/webp/libwebp/src/utils/thread_utils.c new file mode 100644 index 0000000000..4e470e17ac --- /dev/null +++ b/third-party/webp/libwebp/src/utils/thread_utils.c @@ -0,0 +1,369 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Multi-threaded worker +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include // for memset() +#include "src/utils/thread_utils.h" +#include "src/utils/utils.h" + +#ifdef WEBP_USE_THREAD + +#if defined(_WIN32) + +#include +typedef HANDLE pthread_t; +typedef CRITICAL_SECTION pthread_mutex_t; + +#if _WIN32_WINNT >= 0x0600 // Windows Vista / Server 2008 or greater +#define USE_WINDOWS_CONDITION_VARIABLE +typedef CONDITION_VARIABLE pthread_cond_t; +#else +typedef struct { + HANDLE waiting_sem_; + HANDLE received_sem_; + HANDLE signal_event_; +} pthread_cond_t; +#endif // _WIN32_WINNT >= 0x600 + +#ifndef WINAPI_FAMILY_PARTITION +#define WINAPI_PARTITION_DESKTOP 1 +#define WINAPI_FAMILY_PARTITION(x) x +#endif + +#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +#define USE_CREATE_THREAD +#endif + +#else // !_WIN32 + +#include + +#endif // _WIN32 + +typedef struct { + pthread_mutex_t mutex_; + pthread_cond_t condition_; + pthread_t thread_; +} WebPWorkerImpl; + +#if defined(_WIN32) + +//------------------------------------------------------------------------------ +// simplistic pthread emulation layer + +#include + +// _beginthreadex requires __stdcall +#define THREADFN unsigned int __stdcall +#define THREAD_RETURN(val) (unsigned int)((DWORD_PTR)val) + +#if _WIN32_WINNT >= 0x0501 // Windows XP or greater +#define WaitForSingleObject(obj, timeout) \ + WaitForSingleObjectEx(obj, timeout, FALSE /*bAlertable*/) +#endif + +static int pthread_create(pthread_t* const thread, const void* attr, + unsigned int (__stdcall* start)(void*), void* arg) { + (void)attr; +#ifdef USE_CREATE_THREAD + *thread = CreateThread(NULL, /* lpThreadAttributes */ + 0, /* dwStackSize */ + start, + arg, + 0, /* dwStackSize */ + NULL); /* lpThreadId */ +#else + *thread = (pthread_t)_beginthreadex(NULL, /* void *security */ + 0, /* unsigned stack_size */ + start, + arg, + 0, /* unsigned initflag */ + NULL); /* unsigned *thrdaddr */ +#endif + if (*thread == NULL) return 1; + SetThreadPriority(*thread, THREAD_PRIORITY_ABOVE_NORMAL); + return 0; +} + +static int pthread_join(pthread_t thread, void** value_ptr) { + (void)value_ptr; + return (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0 || + CloseHandle(thread) == 0); +} + +// Mutex +static int pthread_mutex_init(pthread_mutex_t* const mutex, void* mutexattr) { + (void)mutexattr; +#if _WIN32_WINNT >= 0x0600 // Windows Vista / Server 2008 or greater + InitializeCriticalSectionEx(mutex, 0 /*dwSpinCount*/, 0 /*Flags*/); +#else + InitializeCriticalSection(mutex); +#endif + return 0; +} + +static int pthread_mutex_lock(pthread_mutex_t* const mutex) { + EnterCriticalSection(mutex); + return 0; +} + +static int pthread_mutex_unlock(pthread_mutex_t* const mutex) { + LeaveCriticalSection(mutex); + return 0; +} + +static int pthread_mutex_destroy(pthread_mutex_t* const mutex) { + DeleteCriticalSection(mutex); + return 0; +} + +// Condition +static int pthread_cond_destroy(pthread_cond_t* const condition) { + int ok = 1; +#ifdef USE_WINDOWS_CONDITION_VARIABLE + (void)condition; +#else + ok &= (CloseHandle(condition->waiting_sem_) != 0); + ok &= (CloseHandle(condition->received_sem_) != 0); + ok &= (CloseHandle(condition->signal_event_) != 0); +#endif + return !ok; +} + +static int pthread_cond_init(pthread_cond_t* const condition, void* cond_attr) { + (void)cond_attr; +#ifdef USE_WINDOWS_CONDITION_VARIABLE + InitializeConditionVariable(condition); +#else + condition->waiting_sem_ = CreateSemaphore(NULL, 0, 1, NULL); + condition->received_sem_ = CreateSemaphore(NULL, 0, 1, NULL); + condition->signal_event_ = CreateEvent(NULL, FALSE, FALSE, NULL); + if (condition->waiting_sem_ == NULL || + condition->received_sem_ == NULL || + condition->signal_event_ == NULL) { + pthread_cond_destroy(condition); + return 1; + } +#endif + return 0; +} + +static int pthread_cond_signal(pthread_cond_t* const condition) { + int ok = 1; +#ifdef USE_WINDOWS_CONDITION_VARIABLE + WakeConditionVariable(condition); +#else + if (WaitForSingleObject(condition->waiting_sem_, 0) == WAIT_OBJECT_0) { + // a thread is waiting in pthread_cond_wait: allow it to be notified + ok = SetEvent(condition->signal_event_); + // wait until the event is consumed so the signaler cannot consume + // the event via its own pthread_cond_wait. + ok &= (WaitForSingleObject(condition->received_sem_, INFINITE) != + WAIT_OBJECT_0); + } +#endif + return !ok; +} + +static int pthread_cond_wait(pthread_cond_t* const condition, + pthread_mutex_t* const mutex) { + int ok; +#ifdef USE_WINDOWS_CONDITION_VARIABLE + ok = SleepConditionVariableCS(condition, mutex, INFINITE); +#else + // note that there is a consumer available so the signal isn't dropped in + // pthread_cond_signal + if (!ReleaseSemaphore(condition->waiting_sem_, 1, NULL)) return 1; + // now unlock the mutex so pthread_cond_signal may be issued + pthread_mutex_unlock(mutex); + ok = (WaitForSingleObject(condition->signal_event_, INFINITE) == + WAIT_OBJECT_0); + ok &= ReleaseSemaphore(condition->received_sem_, 1, NULL); + pthread_mutex_lock(mutex); +#endif + return !ok; +} + +#else // !_WIN32 +# define THREADFN void* +# define THREAD_RETURN(val) val +#endif // _WIN32 + +//------------------------------------------------------------------------------ + +static THREADFN ThreadLoop(void* ptr) { + WebPWorker* const worker = (WebPWorker*)ptr; + WebPWorkerImpl* const impl = (WebPWorkerImpl*)worker->impl_; + int done = 0; + while (!done) { + pthread_mutex_lock(&impl->mutex_); + while (worker->status_ == OK) { // wait in idling mode + pthread_cond_wait(&impl->condition_, &impl->mutex_); + } + if (worker->status_ == WORK) { + WebPGetWorkerInterface()->Execute(worker); + worker->status_ = OK; + } else if (worker->status_ == NOT_OK) { // finish the worker + done = 1; + } + // signal to the main thread that we're done (for Sync()) + // Note the associated mutex does not need to be held when signaling the + // condition. Unlocking the mutex first may improve performance in some + // implementations, avoiding the case where the waiting thread can't + // reacquire the mutex when woken. + pthread_mutex_unlock(&impl->mutex_); + pthread_cond_signal(&impl->condition_); + } + return THREAD_RETURN(NULL); // Thread is finished +} + +// main thread state control +static void ChangeState(WebPWorker* const worker, WebPWorkerStatus new_status) { + // No-op when attempting to change state on a thread that didn't come up. + // Checking status_ without acquiring the lock first would result in a data + // race. + WebPWorkerImpl* const impl = (WebPWorkerImpl*)worker->impl_; + if (impl == NULL) return; + + pthread_mutex_lock(&impl->mutex_); + if (worker->status_ >= OK) { + // wait for the worker to finish + while (worker->status_ != OK) { + pthread_cond_wait(&impl->condition_, &impl->mutex_); + } + // assign new status and release the working thread if needed + if (new_status != OK) { + worker->status_ = new_status; + // Note the associated mutex does not need to be held when signaling the + // condition. Unlocking the mutex first may improve performance in some + // implementations, avoiding the case where the waiting thread can't + // reacquire the mutex when woken. + pthread_mutex_unlock(&impl->mutex_); + pthread_cond_signal(&impl->condition_); + return; + } + } + pthread_mutex_unlock(&impl->mutex_); +} + +#endif // WEBP_USE_THREAD + +//------------------------------------------------------------------------------ + +static void Init(WebPWorker* const worker) { + memset(worker, 0, sizeof(*worker)); + worker->status_ = NOT_OK; +} + +static int Sync(WebPWorker* const worker) { +#ifdef WEBP_USE_THREAD + ChangeState(worker, OK); +#endif + assert(worker->status_ <= OK); + return !worker->had_error; +} + +static int Reset(WebPWorker* const worker) { + int ok = 1; + worker->had_error = 0; + if (worker->status_ < OK) { +#ifdef WEBP_USE_THREAD + WebPWorkerImpl* const impl = + (WebPWorkerImpl*)WebPSafeCalloc(1, sizeof(WebPWorkerImpl)); + worker->impl_ = (void*)impl; + if (worker->impl_ == NULL) { + return 0; + } + if (pthread_mutex_init(&impl->mutex_, NULL)) { + goto Error; + } + if (pthread_cond_init(&impl->condition_, NULL)) { + pthread_mutex_destroy(&impl->mutex_); + goto Error; + } + pthread_mutex_lock(&impl->mutex_); + ok = !pthread_create(&impl->thread_, NULL, ThreadLoop, worker); + if (ok) worker->status_ = OK; + pthread_mutex_unlock(&impl->mutex_); + if (!ok) { + pthread_mutex_destroy(&impl->mutex_); + pthread_cond_destroy(&impl->condition_); + Error: + WebPSafeFree(impl); + worker->impl_ = NULL; + return 0; + } +#else + worker->status_ = OK; +#endif + } else if (worker->status_ > OK) { + ok = Sync(worker); + } + assert(!ok || (worker->status_ == OK)); + return ok; +} + +static void Execute(WebPWorker* const worker) { + if (worker->hook != NULL) { + worker->had_error |= !worker->hook(worker->data1, worker->data2); + } +} + +static void Launch(WebPWorker* const worker) { +#ifdef WEBP_USE_THREAD + ChangeState(worker, WORK); +#else + Execute(worker); +#endif +} + +static void End(WebPWorker* const worker) { +#ifdef WEBP_USE_THREAD + if (worker->impl_ != NULL) { + WebPWorkerImpl* const impl = (WebPWorkerImpl*)worker->impl_; + ChangeState(worker, NOT_OK); + pthread_join(impl->thread_, NULL); + pthread_mutex_destroy(&impl->mutex_); + pthread_cond_destroy(&impl->condition_); + WebPSafeFree(impl); + worker->impl_ = NULL; + } +#else + worker->status_ = NOT_OK; + assert(worker->impl_ == NULL); +#endif + assert(worker->status_ == NOT_OK); +} + +//------------------------------------------------------------------------------ + +static WebPWorkerInterface g_worker_interface = { + Init, Reset, Sync, Launch, Execute, End +}; + +int WebPSetWorkerInterface(const WebPWorkerInterface* const winterface) { + if (winterface == NULL || + winterface->Init == NULL || winterface->Reset == NULL || + winterface->Sync == NULL || winterface->Launch == NULL || + winterface->Execute == NULL || winterface->End == NULL) { + return 0; + } + g_worker_interface = *winterface; + return 1; +} + +const WebPWorkerInterface* WebPGetWorkerInterface(void) { + return &g_worker_interface; +} + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/src/utils/thread_utils.h b/third-party/webp/libwebp/src/utils/thread_utils.h new file mode 100644 index 0000000000..29ad49f74b --- /dev/null +++ b/third-party/webp/libwebp/src/utils/thread_utils.h @@ -0,0 +1,90 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Multi-threaded worker +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_UTILS_THREAD_UTILS_H_ +#define WEBP_UTILS_THREAD_UTILS_H_ + +#ifdef HAVE_CONFIG_H +#include "src/webp/config.h" +#endif + +#include "src/webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// State of the worker thread object +typedef enum { + NOT_OK = 0, // object is unusable + OK, // ready to work + WORK // busy finishing the current task +} WebPWorkerStatus; + +// Function to be called by the worker thread. Takes two opaque pointers as +// arguments (data1 and data2), and should return false in case of error. +typedef int (*WebPWorkerHook)(void*, void*); + +// Synchronization object used to launch job in the worker thread +typedef struct { + void* impl_; // platform-dependent implementation worker details + WebPWorkerStatus status_; + WebPWorkerHook hook; // hook to call + void* data1; // first argument passed to 'hook' + void* data2; // second argument passed to 'hook' + int had_error; // return value of the last call to 'hook' +} WebPWorker; + +// The interface for all thread-worker related functions. All these functions +// must be implemented. +typedef struct { + // Must be called first, before any other method. + void (*Init)(WebPWorker* const worker); + // Must be called to initialize the object and spawn the thread. Re-entrant. + // Will potentially launch the thread. Returns false in case of error. + int (*Reset)(WebPWorker* const worker); + // Makes sure the previous work is finished. Returns true if worker->had_error + // was not set and no error condition was triggered by the working thread. + int (*Sync)(WebPWorker* const worker); + // Triggers the thread to call hook() with data1 and data2 arguments. These + // hook/data1/data2 values can be changed at any time before calling this + // function, but not be changed afterward until the next call to Sync(). + void (*Launch)(WebPWorker* const worker); + // This function is similar to Launch() except that it calls the + // hook directly instead of using a thread. Convenient to bypass the thread + // mechanism while still using the WebPWorker structs. Sync() must + // still be called afterward (for error reporting). + void (*Execute)(WebPWorker* const worker); + // Kill the thread and terminate the object. To use the object again, one + // must call Reset() again. + void (*End)(WebPWorker* const worker); +} WebPWorkerInterface; + +// Install a new set of threading functions, overriding the defaults. This +// should be done before any workers are started, i.e., before any encoding or +// decoding takes place. The contents of the interface struct are copied, it +// is safe to free the corresponding memory after this call. This function is +// not thread-safe. Return false in case of invalid pointer or methods. +WEBP_EXTERN int WebPSetWorkerInterface( + const WebPWorkerInterface* const winterface); + +// Retrieve the currently set thread worker interface. +WEBP_EXTERN const WebPWorkerInterface* WebPGetWorkerInterface(void); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_UTILS_THREAD_UTILS_H_ diff --git a/third-party/webp/libwebp/src/utils/utils.c b/third-party/webp/libwebp/src/utils/utils.c new file mode 100644 index 0000000000..408ce88f67 --- /dev/null +++ b/third-party/webp/libwebp/src/utils/utils.c @@ -0,0 +1,282 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Misc. common utility functions +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/utils/utils.h" + +#include +#include // for memcpy() + +#include "src/utils/palette.h" +#include "src/webp/encode.h" + +// If PRINT_MEM_INFO is defined, extra info (like total memory used, number of +// alloc/free etc) is printed. For debugging/tuning purpose only (it's slow, +// and not multi-thread safe!). +// An interesting alternative is valgrind's 'massif' tool: +// https://valgrind.org/docs/manual/ms-manual.html +// Here is an example command line: +/* valgrind --tool=massif --massif-out-file=massif.out \ + --stacks=yes --alloc-fn=WebPSafeMalloc --alloc-fn=WebPSafeCalloc + ms_print massif.out +*/ +// In addition: +// * if PRINT_MEM_TRAFFIC is defined, all the details of the malloc/free cycles +// are printed. +// * if MALLOC_FAIL_AT is defined, the global environment variable +// $MALLOC_FAIL_AT is used to simulate a memory error when calloc or malloc +// is called for the nth time. Example usage: +// export MALLOC_FAIL_AT=50 && ./examples/cwebp input.png +// * if MALLOC_LIMIT is defined, the global environment variable $MALLOC_LIMIT +// sets the maximum amount of memory (in bytes) made available to libwebp. +// This can be used to emulate environment with very limited memory. +// Example: export MALLOC_LIMIT=64000000 && ./examples/dwebp picture.webp + +// #define PRINT_MEM_INFO +// #define PRINT_MEM_TRAFFIC +// #define MALLOC_FAIL_AT +// #define MALLOC_LIMIT + +//------------------------------------------------------------------------------ +// Checked memory allocation + +#if defined(PRINT_MEM_INFO) + +#include + +static int num_malloc_calls = 0; +static int num_calloc_calls = 0; +static int num_free_calls = 0; +static int countdown_to_fail = 0; // 0 = off + +typedef struct MemBlock MemBlock; +struct MemBlock { + void* ptr_; + size_t size_; + MemBlock* next_; +}; + +static MemBlock* all_blocks = NULL; +static size_t total_mem = 0; +static size_t total_mem_allocated = 0; +static size_t high_water_mark = 0; +static size_t mem_limit = 0; + +static int exit_registered = 0; + +static void PrintMemInfo(void) { + fprintf(stderr, "\nMEMORY INFO:\n"); + fprintf(stderr, "num calls to: malloc = %4d\n", num_malloc_calls); + fprintf(stderr, " calloc = %4d\n", num_calloc_calls); + fprintf(stderr, " free = %4d\n", num_free_calls); + fprintf(stderr, "total_mem: %u\n", (uint32_t)total_mem); + fprintf(stderr, "total_mem allocated: %u\n", (uint32_t)total_mem_allocated); + fprintf(stderr, "high-water mark: %u\n", (uint32_t)high_water_mark); + while (all_blocks != NULL) { + MemBlock* b = all_blocks; + all_blocks = b->next_; + free(b); + } +} + +static void Increment(int* const v) { + if (!exit_registered) { +#if defined(MALLOC_FAIL_AT) + { + const char* const malloc_fail_at_str = getenv("MALLOC_FAIL_AT"); + if (malloc_fail_at_str != NULL) { + countdown_to_fail = atoi(malloc_fail_at_str); + } + } +#endif +#if defined(MALLOC_LIMIT) + { + const char* const malloc_limit_str = getenv("MALLOC_LIMIT"); +#if MALLOC_LIMIT > 1 + mem_limit = (size_t)MALLOC_LIMIT; +#endif + if (malloc_limit_str != NULL) { + mem_limit = atoi(malloc_limit_str); + } + } +#endif + (void)countdown_to_fail; + (void)mem_limit; + atexit(PrintMemInfo); + exit_registered = 1; + } + ++*v; +} + +static void AddMem(void* ptr, size_t size) { + if (ptr != NULL) { + MemBlock* const b = (MemBlock*)malloc(sizeof(*b)); + if (b == NULL) abort(); + b->next_ = all_blocks; + all_blocks = b; + b->ptr_ = ptr; + b->size_ = size; + total_mem += size; + total_mem_allocated += size; +#if defined(PRINT_MEM_TRAFFIC) +#if defined(MALLOC_FAIL_AT) + fprintf(stderr, "fail-count: %5d [mem=%u]\n", + num_malloc_calls + num_calloc_calls, (uint32_t)total_mem); +#else + fprintf(stderr, "Mem: %u (+%u)\n", (uint32_t)total_mem, (uint32_t)size); +#endif +#endif + if (total_mem > high_water_mark) high_water_mark = total_mem; + } +} + +static void SubMem(void* ptr) { + if (ptr != NULL) { + MemBlock** b = &all_blocks; + // Inefficient search, but that's just for debugging. + while (*b != NULL && (*b)->ptr_ != ptr) b = &(*b)->next_; + if (*b == NULL) { + fprintf(stderr, "Invalid pointer free! (%p)\n", ptr); + abort(); + } + { + MemBlock* const block = *b; + *b = block->next_; + total_mem -= block->size_; +#if defined(PRINT_MEM_TRAFFIC) + fprintf(stderr, "Mem: %u (-%u)\n", + (uint32_t)total_mem, (uint32_t)block->size_); +#endif + free(block); + } + } +} + +#else +#define Increment(v) do {} while (0) +#define AddMem(p, s) do {} while (0) +#define SubMem(p) do {} while (0) +#endif + +// Returns 0 in case of overflow of nmemb * size. +static int CheckSizeArgumentsOverflow(uint64_t nmemb, size_t size) { + const uint64_t total_size = nmemb * size; + if (nmemb == 0) return 1; + if ((uint64_t)size > WEBP_MAX_ALLOCABLE_MEMORY / nmemb) return 0; + if (!CheckSizeOverflow(total_size)) return 0; +#if defined(PRINT_MEM_INFO) && defined(MALLOC_FAIL_AT) + if (countdown_to_fail > 0 && --countdown_to_fail == 0) { + return 0; // fake fail! + } +#endif +#if defined(PRINT_MEM_INFO) && defined(MALLOC_LIMIT) + if (mem_limit > 0) { + const uint64_t new_total_mem = (uint64_t)total_mem + total_size; + if (!CheckSizeOverflow(new_total_mem) || + new_total_mem > mem_limit) { + return 0; // fake fail! + } + } +#endif + + return 1; +} + +void* WebPSafeMalloc(uint64_t nmemb, size_t size) { + void* ptr; + Increment(&num_malloc_calls); + if (!CheckSizeArgumentsOverflow(nmemb, size)) return NULL; + assert(nmemb * size > 0); + ptr = malloc((size_t)(nmemb * size)); + AddMem(ptr, (size_t)(nmemb * size)); + return ptr; +} + +void* WebPSafeCalloc(uint64_t nmemb, size_t size) { + void* ptr; + Increment(&num_calloc_calls); + if (!CheckSizeArgumentsOverflow(nmemb, size)) return NULL; + assert(nmemb * size > 0); + ptr = calloc((size_t)nmemb, size); + AddMem(ptr, (size_t)(nmemb * size)); + return ptr; +} + +void WebPSafeFree(void* const ptr) { + if (ptr != NULL) { + Increment(&num_free_calls); + SubMem(ptr); + } + free(ptr); +} + +// Public API functions. + +void* WebPMalloc(size_t size) { + return WebPSafeMalloc(1, size); +} + +void WebPFree(void* ptr) { + WebPSafeFree(ptr); +} + +//------------------------------------------------------------------------------ + +void WebPCopyPlane(const uint8_t* src, int src_stride, + uint8_t* dst, int dst_stride, int width, int height) { + assert(src != NULL && dst != NULL); + assert(abs(src_stride) >= width && abs(dst_stride) >= width); + while (height-- > 0) { + memcpy(dst, src, width); + src += src_stride; + dst += dst_stride; + } +} + +void WebPCopyPixels(const WebPPicture* const src, WebPPicture* const dst) { + assert(src != NULL && dst != NULL); + assert(src->width == dst->width && src->height == dst->height); + assert(src->use_argb && dst->use_argb); + WebPCopyPlane((uint8_t*)src->argb, 4 * src->argb_stride, (uint8_t*)dst->argb, + 4 * dst->argb_stride, 4 * src->width, src->height); +} + +//------------------------------------------------------------------------------ + +int WebPGetColorPalette(const WebPPicture* const pic, uint32_t* const palette) { + return GetColorPalette(pic, palette); +} + +//------------------------------------------------------------------------------ + +#if defined(WEBP_NEED_LOG_TABLE_8BIT) +const uint8_t WebPLogTable8bit[256] = { // 31 ^ clz(i) + 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 +}; +#endif + +//------------------------------------------------------------------------------ diff --git a/third-party/webp/libwebp/src/utils/utils.h b/third-party/webp/libwebp/src/utils/utils.h new file mode 100644 index 0000000000..b2241fbf9b --- /dev/null +++ b/third-party/webp/libwebp/src/utils/utils.h @@ -0,0 +1,209 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Misc. common utility functions +// +// Authors: Skal (pascal.massimino@gmail.com) +// Urvang (urvang@google.com) + +#ifndef WEBP_UTILS_UTILS_H_ +#define WEBP_UTILS_UTILS_H_ + +#ifdef HAVE_CONFIG_H +#include "src/webp/config.h" +#endif + +#include + +#include "src/webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//------------------------------------------------------------------------------ +// Memory allocation + +// This is the maximum memory amount that libwebp will ever try to allocate. +#ifndef WEBP_MAX_ALLOCABLE_MEMORY +#if SIZE_MAX > (1ULL << 34) +#define WEBP_MAX_ALLOCABLE_MEMORY (1ULL << 34) +#else +// For 32-bit targets keep this below INT_MAX to avoid valgrind warnings. +#define WEBP_MAX_ALLOCABLE_MEMORY ((1ULL << 31) - (1 << 16)) +#endif +#endif // WEBP_MAX_ALLOCABLE_MEMORY + +static WEBP_INLINE int CheckSizeOverflow(uint64_t size) { + return size == (size_t)size; +} + +// size-checking safe malloc/calloc: verify that the requested size is not too +// large, or return NULL. You don't need to call these for constructs like +// malloc(sizeof(foo)), but only if there's picture-dependent size involved +// somewhere (like: malloc(num_pixels * sizeof(*something))). That's why this +// safe malloc() borrows the signature from calloc(), pointing at the dangerous +// underlying multiply involved. +WEBP_EXTERN void* WebPSafeMalloc(uint64_t nmemb, size_t size); +// Note that WebPSafeCalloc() expects the second argument type to be 'size_t' +// in order to favor the "calloc(num_foo, sizeof(foo))" pattern. +WEBP_EXTERN void* WebPSafeCalloc(uint64_t nmemb, size_t size); + +// Companion deallocation function to the above allocations. +WEBP_EXTERN void WebPSafeFree(void* const ptr); + +//------------------------------------------------------------------------------ +// Alignment + +#define WEBP_ALIGN_CST 31 +#define WEBP_ALIGN(PTR) (((uintptr_t)(PTR) + WEBP_ALIGN_CST) & \ + ~(uintptr_t)WEBP_ALIGN_CST) + +#include +// memcpy() is the safe way of moving potentially unaligned 32b memory. +static WEBP_INLINE uint32_t WebPMemToUint32(const uint8_t* const ptr) { + uint32_t A; + memcpy(&A, ptr, sizeof(A)); + return A; +} + +static WEBP_INLINE int32_t WebPMemToInt32(const uint8_t* const ptr) { + return (int32_t)WebPMemToUint32(ptr); +} + +static WEBP_INLINE void WebPUint32ToMem(uint8_t* const ptr, uint32_t val) { + memcpy(ptr, &val, sizeof(val)); +} + +static WEBP_INLINE void WebPInt32ToMem(uint8_t* const ptr, int val) { + WebPUint32ToMem(ptr, (uint32_t)val); +} + +//------------------------------------------------------------------------------ +// Reading/writing data. + +// Read 16, 24 or 32 bits stored in little-endian order. +static WEBP_INLINE int GetLE16(const uint8_t* const data) { + return (int)(data[0] << 0) | (data[1] << 8); +} + +static WEBP_INLINE int GetLE24(const uint8_t* const data) { + return GetLE16(data) | (data[2] << 16); +} + +static WEBP_INLINE uint32_t GetLE32(const uint8_t* const data) { + return GetLE16(data) | ((uint32_t)GetLE16(data + 2) << 16); +} + +// Store 16, 24 or 32 bits in little-endian order. +static WEBP_INLINE void PutLE16(uint8_t* const data, int val) { + assert(val < (1 << 16)); + data[0] = (val >> 0) & 0xff; + data[1] = (val >> 8) & 0xff; +} + +static WEBP_INLINE void PutLE24(uint8_t* const data, int val) { + assert(val < (1 << 24)); + PutLE16(data, val & 0xffff); + data[2] = (val >> 16) & 0xff; +} + +static WEBP_INLINE void PutLE32(uint8_t* const data, uint32_t val) { + PutLE16(data, (int)(val & 0xffff)); + PutLE16(data + 2, (int)(val >> 16)); +} + +// use GNU builtins where available. +#if defined(__GNUC__) && \ + ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4) +// Returns (int)floor(log2(n)). n must be > 0. +static WEBP_INLINE int BitsLog2Floor(uint32_t n) { + return 31 ^ __builtin_clz(n); +} +// counts the number of trailing zero +static WEBP_INLINE int BitsCtz(uint32_t n) { return __builtin_ctz(n); } +#elif defined(_MSC_VER) && _MSC_VER > 1310 && \ + (defined(_M_X64) || defined(_M_IX86)) +#include +#pragma intrinsic(_BitScanReverse) +#pragma intrinsic(_BitScanForward) + +static WEBP_INLINE int BitsLog2Floor(uint32_t n) { + unsigned long first_set_bit; // NOLINT (runtime/int) + _BitScanReverse(&first_set_bit, n); + return first_set_bit; +} +static WEBP_INLINE int BitsCtz(uint32_t n) { + unsigned long first_set_bit; // NOLINT (runtime/int) + _BitScanForward(&first_set_bit, n); + return first_set_bit; +} +#else // default: use the (slow) C-version. +#define WEBP_HAVE_SLOW_CLZ_CTZ // signal that the Clz/Ctz function are slow +// Returns 31 ^ clz(n) = log2(n). This is the default C-implementation, either +// based on table or not. Can be used as fallback if clz() is not available. +#define WEBP_NEED_LOG_TABLE_8BIT +extern const uint8_t WebPLogTable8bit[256]; +static WEBP_INLINE int WebPLog2FloorC(uint32_t n) { + int log_value = 0; + while (n >= 256) { + log_value += 8; + n >>= 8; + } + return log_value + WebPLogTable8bit[n]; +} + +static WEBP_INLINE int BitsLog2Floor(uint32_t n) { return WebPLog2FloorC(n); } + +static WEBP_INLINE int BitsCtz(uint32_t n) { + int i; + for (i = 0; i < 32; ++i, n >>= 1) { + if (n & 1) return i; + } + return 32; +} + +#endif + +//------------------------------------------------------------------------------ +// Pixel copying. + +struct WebPPicture; + +// Copy width x height pixels from 'src' to 'dst' honoring the strides. +WEBP_EXTERN void WebPCopyPlane(const uint8_t* src, int src_stride, + uint8_t* dst, int dst_stride, + int width, int height); + +// Copy ARGB pixels from 'src' to 'dst' honoring strides. 'src' and 'dst' are +// assumed to be already allocated and using ARGB data. +WEBP_EXTERN void WebPCopyPixels(const struct WebPPicture* const src, + struct WebPPicture* const dst); + +//------------------------------------------------------------------------------ +// Unique colors. + +// Returns count of unique colors in 'pic', assuming pic->use_argb is true. +// If the unique color count is more than MAX_PALETTE_SIZE, returns +// MAX_PALETTE_SIZE+1. +// If 'palette' is not NULL and number of unique colors is less than or equal to +// MAX_PALETTE_SIZE, also outputs the actual unique colors into 'palette'. +// Note: 'palette' is assumed to be an array already allocated with at least +// MAX_PALETTE_SIZE elements. +// TODO(vrabaud) remove whenever we can break the ABI. +WEBP_EXTERN int WebPGetColorPalette(const struct WebPPicture* const pic, + uint32_t* const palette); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_UTILS_UTILS_H_ diff --git a/third-party/webp/libwebp/src/webp/decode.h b/third-party/webp/libwebp/src/webp/decode.h new file mode 100644 index 0000000000..9d968061d1 --- /dev/null +++ b/third-party/webp/libwebp/src/webp/decode.h @@ -0,0 +1,505 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Main decoding functions for WebP images. +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_WEBP_DECODE_H_ +#define WEBP_WEBP_DECODE_H_ + +#include "./types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define WEBP_DECODER_ABI_VERSION 0x0209 // MAJOR(8b) + MINOR(8b) + +// Note: forward declaring enumerations is not allowed in (strict) C and C++, +// the types are left here for reference. +// typedef enum VP8StatusCode VP8StatusCode; +// typedef enum WEBP_CSP_MODE WEBP_CSP_MODE; +typedef struct WebPRGBABuffer WebPRGBABuffer; +typedef struct WebPYUVABuffer WebPYUVABuffer; +typedef struct WebPDecBuffer WebPDecBuffer; +typedef struct WebPIDecoder WebPIDecoder; +typedef struct WebPBitstreamFeatures WebPBitstreamFeatures; +typedef struct WebPDecoderOptions WebPDecoderOptions; +typedef struct WebPDecoderConfig WebPDecoderConfig; + +// Return the decoder's version number, packed in hexadecimal using 8bits for +// each of major/minor/revision. E.g: v2.5.7 is 0x020507. +WEBP_EXTERN int WebPGetDecoderVersion(void); + +// Retrieve basic header information: width, height. +// This function will also validate the header, returning true on success, +// false otherwise. '*width' and '*height' are only valid on successful return. +// Pointers 'width' and 'height' can be passed NULL if deemed irrelevant. +// Note: The following chunk sequences (before the raw VP8/VP8L data) are +// considered valid by this function: +// RIFF + VP8(L) +// RIFF + VP8X + (optional chunks) + VP8(L) +// ALPH + VP8 <-- Not a valid WebP format: only allowed for internal purpose. +// VP8(L) <-- Not a valid WebP format: only allowed for internal purpose. +WEBP_EXTERN int WebPGetInfo(const uint8_t* data, size_t data_size, + int* width, int* height); + +// Decodes WebP images pointed to by 'data' and returns RGBA samples, along +// with the dimensions in *width and *height. The ordering of samples in +// memory is R, G, B, A, R, G, B, A... in scan order (endian-independent). +// The returned pointer should be deleted calling WebPFree(). +// Returns NULL in case of error. +WEBP_EXTERN uint8_t* WebPDecodeRGBA(const uint8_t* data, size_t data_size, + int* width, int* height); + +// Same as WebPDecodeRGBA, but returning A, R, G, B, A, R, G, B... ordered data. +WEBP_EXTERN uint8_t* WebPDecodeARGB(const uint8_t* data, size_t data_size, + int* width, int* height); + +// Same as WebPDecodeRGBA, but returning B, G, R, A, B, G, R, A... ordered data. +WEBP_EXTERN uint8_t* WebPDecodeBGRA(const uint8_t* data, size_t data_size, + int* width, int* height); + +// Same as WebPDecodeRGBA, but returning R, G, B, R, G, B... ordered data. +// If the bitstream contains transparency, it is ignored. +WEBP_EXTERN uint8_t* WebPDecodeRGB(const uint8_t* data, size_t data_size, + int* width, int* height); + +// Same as WebPDecodeRGB, but returning B, G, R, B, G, R... ordered data. +WEBP_EXTERN uint8_t* WebPDecodeBGR(const uint8_t* data, size_t data_size, + int* width, int* height); + + +// Decode WebP images pointed to by 'data' to Y'UV format(*). The pointer +// returned is the Y samples buffer. Upon return, *u and *v will point to +// the U and V chroma data. These U and V buffers need NOT be passed to +// WebPFree(), unlike the returned Y luma one. The dimension of the U and V +// planes are both (*width + 1) / 2 and (*height + 1) / 2. +// Upon return, the Y buffer has a stride returned as '*stride', while U and V +// have a common stride returned as '*uv_stride'. +// 'width' and 'height' may be NULL, the other pointers must not be. +// Returns NULL in case of error. +// (*) Also named Y'CbCr. See: https://en.wikipedia.org/wiki/YCbCr +WEBP_EXTERN uint8_t* WebPDecodeYUV(const uint8_t* data, size_t data_size, + int* width, int* height, + uint8_t** u, uint8_t** v, + int* stride, int* uv_stride); + +// These five functions are variants of the above ones, that decode the image +// directly into a pre-allocated buffer 'output_buffer'. The maximum storage +// available in this buffer is indicated by 'output_buffer_size'. If this +// storage is not sufficient (or an error occurred), NULL is returned. +// Otherwise, output_buffer is returned, for convenience. +// The parameter 'output_stride' specifies the distance (in bytes) +// between scanlines. Hence, output_buffer_size is expected to be at least +// output_stride x picture-height. +WEBP_EXTERN uint8_t* WebPDecodeRGBAInto( + const uint8_t* data, size_t data_size, + uint8_t* output_buffer, size_t output_buffer_size, int output_stride); +WEBP_EXTERN uint8_t* WebPDecodeARGBInto( + const uint8_t* data, size_t data_size, + uint8_t* output_buffer, size_t output_buffer_size, int output_stride); +WEBP_EXTERN uint8_t* WebPDecodeBGRAInto( + const uint8_t* data, size_t data_size, + uint8_t* output_buffer, size_t output_buffer_size, int output_stride); + +// RGB and BGR variants. Here too the transparency information, if present, +// will be dropped and ignored. +WEBP_EXTERN uint8_t* WebPDecodeRGBInto( + const uint8_t* data, size_t data_size, + uint8_t* output_buffer, size_t output_buffer_size, int output_stride); +WEBP_EXTERN uint8_t* WebPDecodeBGRInto( + const uint8_t* data, size_t data_size, + uint8_t* output_buffer, size_t output_buffer_size, int output_stride); + +// WebPDecodeYUVInto() is a variant of WebPDecodeYUV() that operates directly +// into pre-allocated luma/chroma plane buffers. This function requires the +// strides to be passed: one for the luma plane and one for each of the +// chroma ones. The size of each plane buffer is passed as 'luma_size', +// 'u_size' and 'v_size' respectively. +// Pointer to the luma plane ('*luma') is returned or NULL if an error occurred +// during decoding (or because some buffers were found to be too small). +WEBP_EXTERN uint8_t* WebPDecodeYUVInto( + const uint8_t* data, size_t data_size, + uint8_t* luma, size_t luma_size, int luma_stride, + uint8_t* u, size_t u_size, int u_stride, + uint8_t* v, size_t v_size, int v_stride); + +//------------------------------------------------------------------------------ +// Output colorspaces and buffer + +// Colorspaces +// Note: the naming describes the byte-ordering of packed samples in memory. +// For instance, MODE_BGRA relates to samples ordered as B,G,R,A,B,G,R,A,... +// Non-capital names (e.g.:MODE_Argb) relates to pre-multiplied RGB channels. +// RGBA-4444 and RGB-565 colorspaces are represented by following byte-order: +// RGBA-4444: [r3 r2 r1 r0 g3 g2 g1 g0], [b3 b2 b1 b0 a3 a2 a1 a0], ... +// RGB-565: [r4 r3 r2 r1 r0 g5 g4 g3], [g2 g1 g0 b4 b3 b2 b1 b0], ... +// In the case WEBP_SWAP_16BITS_CSP is defined, the bytes are swapped for +// these two modes: +// RGBA-4444: [b3 b2 b1 b0 a3 a2 a1 a0], [r3 r2 r1 r0 g3 g2 g1 g0], ... +// RGB-565: [g2 g1 g0 b4 b3 b2 b1 b0], [r4 r3 r2 r1 r0 g5 g4 g3], ... + +typedef enum WEBP_CSP_MODE { + MODE_RGB = 0, MODE_RGBA = 1, + MODE_BGR = 2, MODE_BGRA = 3, + MODE_ARGB = 4, MODE_RGBA_4444 = 5, + MODE_RGB_565 = 6, + // RGB-premultiplied transparent modes (alpha value is preserved) + MODE_rgbA = 7, + MODE_bgrA = 8, + MODE_Argb = 9, + MODE_rgbA_4444 = 10, + // YUV modes must come after RGB ones. + MODE_YUV = 11, MODE_YUVA = 12, // yuv 4:2:0 + MODE_LAST = 13 +} WEBP_CSP_MODE; + +// Some useful macros: +static WEBP_INLINE int WebPIsPremultipliedMode(WEBP_CSP_MODE mode) { + return (mode == MODE_rgbA || mode == MODE_bgrA || mode == MODE_Argb || + mode == MODE_rgbA_4444); +} + +static WEBP_INLINE int WebPIsAlphaMode(WEBP_CSP_MODE mode) { + return (mode == MODE_RGBA || mode == MODE_BGRA || mode == MODE_ARGB || + mode == MODE_RGBA_4444 || mode == MODE_YUVA || + WebPIsPremultipliedMode(mode)); +} + +static WEBP_INLINE int WebPIsRGBMode(WEBP_CSP_MODE mode) { + return (mode < MODE_YUV); +} + +//------------------------------------------------------------------------------ +// WebPDecBuffer: Generic structure for describing the output sample buffer. + +struct WebPRGBABuffer { // view as RGBA + uint8_t* rgba; // pointer to RGBA samples + int stride; // stride in bytes from one scanline to the next. + size_t size; // total size of the *rgba buffer. +}; + +struct WebPYUVABuffer { // view as YUVA + uint8_t* y, *u, *v, *a; // pointer to luma, chroma U/V, alpha samples + int y_stride; // luma stride + int u_stride, v_stride; // chroma strides + int a_stride; // alpha stride + size_t y_size; // luma plane size + size_t u_size, v_size; // chroma planes size + size_t a_size; // alpha-plane size +}; + +// Output buffer +struct WebPDecBuffer { + WEBP_CSP_MODE colorspace; // Colorspace. + int width, height; // Dimensions. + int is_external_memory; // If non-zero, 'internal_memory' pointer is not + // used. If value is '2' or more, the external + // memory is considered 'slow' and multiple + // read/write will be avoided. + union { + WebPRGBABuffer RGBA; + WebPYUVABuffer YUVA; + } u; // Nameless union of buffer parameters. + uint32_t pad[4]; // padding for later use + + uint8_t* private_memory; // Internally allocated memory (only when + // is_external_memory is 0). Should not be used + // externally, but accessed via the buffer union. +}; + +// Internal, version-checked, entry point +WEBP_EXTERN int WebPInitDecBufferInternal(WebPDecBuffer*, int); + +// Initialize the structure as empty. Must be called before any other use. +// Returns false in case of version mismatch +static WEBP_INLINE int WebPInitDecBuffer(WebPDecBuffer* buffer) { + return WebPInitDecBufferInternal(buffer, WEBP_DECODER_ABI_VERSION); +} + +// Free any memory associated with the buffer. Must always be called last. +// Note: doesn't free the 'buffer' structure itself. +WEBP_EXTERN void WebPFreeDecBuffer(WebPDecBuffer* buffer); + +//------------------------------------------------------------------------------ +// Enumeration of the status codes + +typedef enum VP8StatusCode { + VP8_STATUS_OK = 0, + VP8_STATUS_OUT_OF_MEMORY, + VP8_STATUS_INVALID_PARAM, + VP8_STATUS_BITSTREAM_ERROR, + VP8_STATUS_UNSUPPORTED_FEATURE, + VP8_STATUS_SUSPENDED, + VP8_STATUS_USER_ABORT, + VP8_STATUS_NOT_ENOUGH_DATA +} VP8StatusCode; + +//------------------------------------------------------------------------------ +// Incremental decoding +// +// This API allows streamlined decoding of partial data. +// Picture can be incrementally decoded as data become available thanks to the +// WebPIDecoder object. This object can be left in a SUSPENDED state if the +// picture is only partially decoded, pending additional input. +// Code example: +/* + WebPInitDecBuffer(&output_buffer); + output_buffer.colorspace = mode; + ... + WebPIDecoder* idec = WebPINewDecoder(&output_buffer); + while (additional_data_is_available) { + // ... (get additional data in some new_data[] buffer) + status = WebPIAppend(idec, new_data, new_data_size); + if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED) { + break; // an error occurred. + } + + // The above call decodes the current available buffer. + // Part of the image can now be refreshed by calling + // WebPIDecGetRGB()/WebPIDecGetYUVA() etc. + } + WebPIDelete(idec); +*/ + +// Creates a new incremental decoder with the supplied buffer parameter. +// This output_buffer can be passed NULL, in which case a default output buffer +// is used (with MODE_RGB). Otherwise, an internal reference to 'output_buffer' +// is kept, which means that the lifespan of 'output_buffer' must be larger than +// that of the returned WebPIDecoder object. +// The supplied 'output_buffer' content MUST NOT be changed between calls to +// WebPIAppend() or WebPIUpdate() unless 'output_buffer.is_external_memory' is +// not set to 0. In such a case, it is allowed to modify the pointers, size and +// stride of output_buffer.u.RGBA or output_buffer.u.YUVA, provided they remain +// within valid bounds. +// All other fields of WebPDecBuffer MUST remain constant between calls. +// Returns NULL if the allocation failed. +WEBP_EXTERN WebPIDecoder* WebPINewDecoder(WebPDecBuffer* output_buffer); + +// This function allocates and initializes an incremental-decoder object, which +// will output the RGB/A samples specified by 'csp' into a preallocated +// buffer 'output_buffer'. The size of this buffer is at least +// 'output_buffer_size' and the stride (distance in bytes between two scanlines) +// is specified by 'output_stride'. +// Additionally, output_buffer can be passed NULL in which case the output +// buffer will be allocated automatically when the decoding starts. The +// colorspace 'csp' is taken into account for allocating this buffer. All other +// parameters are ignored. +// Returns NULL if the allocation failed, or if some parameters are invalid. +WEBP_EXTERN WebPIDecoder* WebPINewRGB( + WEBP_CSP_MODE csp, + uint8_t* output_buffer, size_t output_buffer_size, int output_stride); + +// This function allocates and initializes an incremental-decoder object, which +// will output the raw luma/chroma samples into a preallocated planes if +// supplied. The luma plane is specified by its pointer 'luma', its size +// 'luma_size' and its stride 'luma_stride'. Similarly, the chroma-u plane +// is specified by the 'u', 'u_size' and 'u_stride' parameters, and the chroma-v +// plane by 'v' and 'v_size'. And same for the alpha-plane. The 'a' pointer +// can be pass NULL in case one is not interested in the transparency plane. +// Conversely, 'luma' can be passed NULL if no preallocated planes are supplied. +// In this case, the output buffer will be automatically allocated (using +// MODE_YUVA) when decoding starts. All parameters are then ignored. +// Returns NULL if the allocation failed or if a parameter is invalid. +WEBP_EXTERN WebPIDecoder* WebPINewYUVA( + uint8_t* luma, size_t luma_size, int luma_stride, + uint8_t* u, size_t u_size, int u_stride, + uint8_t* v, size_t v_size, int v_stride, + uint8_t* a, size_t a_size, int a_stride); + +// Deprecated version of the above, without the alpha plane. +// Kept for backward compatibility. +WEBP_EXTERN WebPIDecoder* WebPINewYUV( + uint8_t* luma, size_t luma_size, int luma_stride, + uint8_t* u, size_t u_size, int u_stride, + uint8_t* v, size_t v_size, int v_stride); + +// Deletes the WebPIDecoder object and associated memory. Must always be called +// if WebPINewDecoder, WebPINewRGB or WebPINewYUV succeeded. +WEBP_EXTERN void WebPIDelete(WebPIDecoder* idec); + +// Copies and decodes the next available data. Returns VP8_STATUS_OK when +// the image is successfully decoded. Returns VP8_STATUS_SUSPENDED when more +// data is expected. Returns error in other cases. +WEBP_EXTERN VP8StatusCode WebPIAppend( + WebPIDecoder* idec, const uint8_t* data, size_t data_size); + +// A variant of the above function to be used when data buffer contains +// partial data from the beginning. In this case data buffer is not copied +// to the internal memory. +// Note that the value of the 'data' pointer can change between calls to +// WebPIUpdate, for instance when the data buffer is resized to fit larger data. +WEBP_EXTERN VP8StatusCode WebPIUpdate( + WebPIDecoder* idec, const uint8_t* data, size_t data_size); + +// Returns the RGB/A image decoded so far. Returns NULL if output params +// are not initialized yet. The RGB/A output type corresponds to the colorspace +// specified during call to WebPINewDecoder() or WebPINewRGB(). +// *last_y is the index of last decoded row in raster scan order. Some pointers +// (*last_y, *width etc.) can be NULL if corresponding information is not +// needed. The values in these pointers are only valid on successful (non-NULL) +// return. +WEBP_EXTERN uint8_t* WebPIDecGetRGB( + const WebPIDecoder* idec, int* last_y, + int* width, int* height, int* stride); + +// Same as above function to get a YUVA image. Returns pointer to the luma +// plane or NULL in case of error. If there is no alpha information +// the alpha pointer '*a' will be returned NULL. +WEBP_EXTERN uint8_t* WebPIDecGetYUVA( + const WebPIDecoder* idec, int* last_y, + uint8_t** u, uint8_t** v, uint8_t** a, + int* width, int* height, int* stride, int* uv_stride, int* a_stride); + +// Deprecated alpha-less version of WebPIDecGetYUVA(): it will ignore the +// alpha information (if present). Kept for backward compatibility. +static WEBP_INLINE uint8_t* WebPIDecGetYUV( + const WebPIDecoder* idec, int* last_y, uint8_t** u, uint8_t** v, + int* width, int* height, int* stride, int* uv_stride) { + return WebPIDecGetYUVA(idec, last_y, u, v, NULL, width, height, + stride, uv_stride, NULL); +} + +// Generic call to retrieve information about the displayable area. +// If non NULL, the left/right/width/height pointers are filled with the visible +// rectangular area so far. +// Returns NULL in case the incremental decoder object is in an invalid state. +// Otherwise returns the pointer to the internal representation. This structure +// is read-only, tied to WebPIDecoder's lifespan and should not be modified. +WEBP_EXTERN const WebPDecBuffer* WebPIDecodedArea( + const WebPIDecoder* idec, int* left, int* top, int* width, int* height); + +//------------------------------------------------------------------------------ +// Advanced decoding parametrization +// +// Code sample for using the advanced decoding API +/* + // A) Init a configuration object + WebPDecoderConfig config; + CHECK(WebPInitDecoderConfig(&config)); + + // B) optional: retrieve the bitstream's features. + CHECK(WebPGetFeatures(data, data_size, &config.input) == VP8_STATUS_OK); + + // C) Adjust 'config', if needed + config.options.no_fancy_upsampling = 1; + config.output.colorspace = MODE_BGRA; + // etc. + + // Note that you can also make config.output point to an externally + // supplied memory buffer, provided it's big enough to store the decoded + // picture. Otherwise, config.output will just be used to allocate memory + // and store the decoded picture. + + // D) Decode! + CHECK(WebPDecode(data, data_size, &config) == VP8_STATUS_OK); + + // E) Decoded image is now in config.output (and config.output.u.RGBA) + + // F) Reclaim memory allocated in config's object. It's safe to call + // this function even if the memory is external and wasn't allocated + // by WebPDecode(). + WebPFreeDecBuffer(&config.output); +*/ + +// Features gathered from the bitstream +struct WebPBitstreamFeatures { + int width; // Width in pixels, as read from the bitstream. + int height; // Height in pixels, as read from the bitstream. + int has_alpha; // True if the bitstream contains an alpha channel. + int has_animation; // True if the bitstream is an animation. + int format; // 0 = undefined (/mixed), 1 = lossy, 2 = lossless + + uint32_t pad[5]; // padding for later use +}; + +// Internal, version-checked, entry point +WEBP_EXTERN VP8StatusCode WebPGetFeaturesInternal( + const uint8_t*, size_t, WebPBitstreamFeatures*, int); + +// Retrieve features from the bitstream. The *features structure is filled +// with information gathered from the bitstream. +// Returns VP8_STATUS_OK when the features are successfully retrieved. Returns +// VP8_STATUS_NOT_ENOUGH_DATA when more data is needed to retrieve the +// features from headers. Returns error in other cases. +// Note: The following chunk sequences (before the raw VP8/VP8L data) are +// considered valid by this function: +// RIFF + VP8(L) +// RIFF + VP8X + (optional chunks) + VP8(L) +// ALPH + VP8 <-- Not a valid WebP format: only allowed for internal purpose. +// VP8(L) <-- Not a valid WebP format: only allowed for internal purpose. +static WEBP_INLINE VP8StatusCode WebPGetFeatures( + const uint8_t* data, size_t data_size, + WebPBitstreamFeatures* features) { + return WebPGetFeaturesInternal(data, data_size, features, + WEBP_DECODER_ABI_VERSION); +} + +// Decoding options +struct WebPDecoderOptions { + int bypass_filtering; // if true, skip the in-loop filtering + int no_fancy_upsampling; // if true, use faster pointwise upsampler + int use_cropping; // if true, cropping is applied _first_ + int crop_left, crop_top; // top-left position for cropping. + // Will be snapped to even values. + int crop_width, crop_height; // dimension of the cropping area + int use_scaling; // if true, scaling is applied _afterward_ + int scaled_width, scaled_height; // final resolution + int use_threads; // if true, use multi-threaded decoding + int dithering_strength; // dithering strength (0=Off, 100=full) + int flip; // if true, flip output vertically + int alpha_dithering_strength; // alpha dithering strength in [0..100] + + uint32_t pad[5]; // padding for later use +}; + +// Main object storing the configuration for advanced decoding. +struct WebPDecoderConfig { + WebPBitstreamFeatures input; // Immutable bitstream features (optional) + WebPDecBuffer output; // Output buffer (can point to external mem) + WebPDecoderOptions options; // Decoding options +}; + +// Internal, version-checked, entry point +WEBP_EXTERN int WebPInitDecoderConfigInternal(WebPDecoderConfig*, int); + +// Initialize the configuration as empty. This function must always be +// called first, unless WebPGetFeatures() is to be called. +// Returns false in case of mismatched version. +static WEBP_INLINE int WebPInitDecoderConfig(WebPDecoderConfig* config) { + return WebPInitDecoderConfigInternal(config, WEBP_DECODER_ABI_VERSION); +} + +// Instantiate a new incremental decoder object with the requested +// configuration. The bitstream can be passed using 'data' and 'data_size' +// parameter, in which case the features will be parsed and stored into +// config->input. Otherwise, 'data' can be NULL and no parsing will occur. +// Note that 'config' can be NULL too, in which case a default configuration +// is used. If 'config' is not NULL, it must outlive the WebPIDecoder object +// as some references to its fields will be used. No internal copy of 'config' +// is made. +// The return WebPIDecoder object must always be deleted calling WebPIDelete(). +// Returns NULL in case of error (and config->status will then reflect +// the error condition, if available). +WEBP_EXTERN WebPIDecoder* WebPIDecode(const uint8_t* data, size_t data_size, + WebPDecoderConfig* config); + +// Non-incremental version. This version decodes the full data at once, taking +// 'config' into account. Returns decoding status (which should be VP8_STATUS_OK +// if the decoding was successful). Note that 'config' cannot be NULL. +WEBP_EXTERN VP8StatusCode WebPDecode(const uint8_t* data, size_t data_size, + WebPDecoderConfig* config); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_WEBP_DECODE_H_ diff --git a/third-party/webp/libwebp/src/webp/demux.h b/third-party/webp/libwebp/src/webp/demux.h new file mode 100644 index 0000000000..846eeb15a9 --- /dev/null +++ b/third-party/webp/libwebp/src/webp/demux.h @@ -0,0 +1,363 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Demux API. +// Enables extraction of image and extended format data from WebP files. + +// Code Example: Demuxing WebP data to extract all the frames, ICC profile +// and EXIF/XMP metadata. +/* + WebPDemuxer* demux = WebPDemux(&webp_data); + + uint32_t width = WebPDemuxGetI(demux, WEBP_FF_CANVAS_WIDTH); + uint32_t height = WebPDemuxGetI(demux, WEBP_FF_CANVAS_HEIGHT); + // ... (Get information about the features present in the WebP file). + uint32_t flags = WebPDemuxGetI(demux, WEBP_FF_FORMAT_FLAGS); + + // ... (Iterate over all frames). + WebPIterator iter; + if (WebPDemuxGetFrame(demux, 1, &iter)) { + do { + // ... (Consume 'iter'; e.g. Decode 'iter.fragment' with WebPDecode(), + // ... and get other frame properties like width, height, offsets etc. + // ... see 'struct WebPIterator' below for more info). + } while (WebPDemuxNextFrame(&iter)); + WebPDemuxReleaseIterator(&iter); + } + + // ... (Extract metadata). + WebPChunkIterator chunk_iter; + if (flags & ICCP_FLAG) WebPDemuxGetChunk(demux, "ICCP", 1, &chunk_iter); + // ... (Consume the ICC profile in 'chunk_iter.chunk'). + WebPDemuxReleaseChunkIterator(&chunk_iter); + if (flags & EXIF_FLAG) WebPDemuxGetChunk(demux, "EXIF", 1, &chunk_iter); + // ... (Consume the EXIF metadata in 'chunk_iter.chunk'). + WebPDemuxReleaseChunkIterator(&chunk_iter); + if (flags & XMP_FLAG) WebPDemuxGetChunk(demux, "XMP ", 1, &chunk_iter); + // ... (Consume the XMP metadata in 'chunk_iter.chunk'). + WebPDemuxReleaseChunkIterator(&chunk_iter); + WebPDemuxDelete(demux); +*/ + +#ifndef WEBP_WEBP_DEMUX_H_ +#define WEBP_WEBP_DEMUX_H_ + +#include "./decode.h" // for WEBP_CSP_MODE +#include "./mux_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define WEBP_DEMUX_ABI_VERSION 0x0107 // MAJOR(8b) + MINOR(8b) + +// Note: forward declaring enumerations is not allowed in (strict) C and C++, +// the types are left here for reference. +// typedef enum WebPDemuxState WebPDemuxState; +// typedef enum WebPFormatFeature WebPFormatFeature; +typedef struct WebPDemuxer WebPDemuxer; +typedef struct WebPIterator WebPIterator; +typedef struct WebPChunkIterator WebPChunkIterator; +typedef struct WebPAnimInfo WebPAnimInfo; +typedef struct WebPAnimDecoderOptions WebPAnimDecoderOptions; + +//------------------------------------------------------------------------------ + +// Returns the version number of the demux library, packed in hexadecimal using +// 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507. +WEBP_EXTERN int WebPGetDemuxVersion(void); + +//------------------------------------------------------------------------------ +// Life of a Demux object + +typedef enum WebPDemuxState { + WEBP_DEMUX_PARSE_ERROR = -1, // An error occurred while parsing. + WEBP_DEMUX_PARSING_HEADER = 0, // Not enough data to parse full header. + WEBP_DEMUX_PARSED_HEADER = 1, // Header parsing complete, + // data may be available. + WEBP_DEMUX_DONE = 2 // Entire file has been parsed. +} WebPDemuxState; + +// Internal, version-checked, entry point +WEBP_EXTERN WebPDemuxer* WebPDemuxInternal( + const WebPData*, int, WebPDemuxState*, int); + +// Parses the full WebP file given by 'data'. For single images the WebP file +// header alone or the file header and the chunk header may be absent. +// Returns a WebPDemuxer object on successful parse, NULL otherwise. +static WEBP_INLINE WebPDemuxer* WebPDemux(const WebPData* data) { + return WebPDemuxInternal(data, 0, NULL, WEBP_DEMUX_ABI_VERSION); +} + +// Parses the possibly incomplete WebP file given by 'data'. +// If 'state' is non-NULL it will be set to indicate the status of the demuxer. +// Returns NULL in case of error or if there isn't enough data to start parsing; +// and a WebPDemuxer object on successful parse. +// Note that WebPDemuxer keeps internal pointers to 'data' memory segment. +// If this data is volatile, the demuxer object should be deleted (by calling +// WebPDemuxDelete()) and WebPDemuxPartial() called again on the new data. +// This is usually an inexpensive operation. +static WEBP_INLINE WebPDemuxer* WebPDemuxPartial( + const WebPData* data, WebPDemuxState* state) { + return WebPDemuxInternal(data, 1, state, WEBP_DEMUX_ABI_VERSION); +} + +// Frees memory associated with 'dmux'. +WEBP_EXTERN void WebPDemuxDelete(WebPDemuxer* dmux); + +//------------------------------------------------------------------------------ +// Data/information extraction. + +typedef enum WebPFormatFeature { + WEBP_FF_FORMAT_FLAGS, // bit-wise combination of WebPFeatureFlags + // corresponding to the 'VP8X' chunk (if present). + WEBP_FF_CANVAS_WIDTH, + WEBP_FF_CANVAS_HEIGHT, + WEBP_FF_LOOP_COUNT, // only relevant for animated file + WEBP_FF_BACKGROUND_COLOR, // idem. + WEBP_FF_FRAME_COUNT // Number of frames present in the demux object. + // In case of a partial demux, this is the number + // of frames seen so far, with the last frame + // possibly being partial. +} WebPFormatFeature; + +// Get the 'feature' value from the 'dmux'. +// NOTE: values are only valid if WebPDemux() was used or WebPDemuxPartial() +// returned a state > WEBP_DEMUX_PARSING_HEADER. +// If 'feature' is WEBP_FF_FORMAT_FLAGS, the returned value is a bit-wise +// combination of WebPFeatureFlags values. +// If 'feature' is WEBP_FF_LOOP_COUNT, WEBP_FF_BACKGROUND_COLOR, the returned +// value is only meaningful if the bitstream is animated. +WEBP_EXTERN uint32_t WebPDemuxGetI( + const WebPDemuxer* dmux, WebPFormatFeature feature); + +//------------------------------------------------------------------------------ +// Frame iteration. + +struct WebPIterator { + int frame_num; + int num_frames; // equivalent to WEBP_FF_FRAME_COUNT. + int x_offset, y_offset; // offset relative to the canvas. + int width, height; // dimensions of this frame. + int duration; // display duration in milliseconds. + WebPMuxAnimDispose dispose_method; // dispose method for the frame. + int complete; // true if 'fragment' contains a full frame. partial images + // may still be decoded with the WebP incremental decoder. + WebPData fragment; // The frame given by 'frame_num'. Note for historical + // reasons this is called a fragment. + int has_alpha; // True if the frame contains transparency. + WebPMuxAnimBlend blend_method; // Blend operation for the frame. + + uint32_t pad[2]; // padding for later use. + void* private_; // for internal use only. +}; + +// Retrieves frame 'frame_number' from 'dmux'. +// 'iter->fragment' points to the frame on return from this function. +// Setting 'frame_number' equal to 0 will return the last frame of the image. +// Returns false if 'dmux' is NULL or frame 'frame_number' is not present. +// Call WebPDemuxReleaseIterator() when use of the iterator is complete. +// NOTE: 'dmux' must persist for the lifetime of 'iter'. +WEBP_EXTERN int WebPDemuxGetFrame( + const WebPDemuxer* dmux, int frame_number, WebPIterator* iter); + +// Sets 'iter->fragment' to point to the next ('iter->frame_num' + 1) or +// previous ('iter->frame_num' - 1) frame. These functions do not loop. +// Returns true on success, false otherwise. +WEBP_EXTERN int WebPDemuxNextFrame(WebPIterator* iter); +WEBP_EXTERN int WebPDemuxPrevFrame(WebPIterator* iter); + +// Releases any memory associated with 'iter'. +// Must be called before any subsequent calls to WebPDemuxGetChunk() on the same +// iter. Also, must be called before destroying the associated WebPDemuxer with +// WebPDemuxDelete(). +WEBP_EXTERN void WebPDemuxReleaseIterator(WebPIterator* iter); + +//------------------------------------------------------------------------------ +// Chunk iteration. + +struct WebPChunkIterator { + // The current and total number of chunks with the fourcc given to + // WebPDemuxGetChunk(). + int chunk_num; + int num_chunks; + WebPData chunk; // The payload of the chunk. + + uint32_t pad[6]; // padding for later use + void* private_; +}; + +// Retrieves the 'chunk_number' instance of the chunk with id 'fourcc' from +// 'dmux'. +// 'fourcc' is a character array containing the fourcc of the chunk to return, +// e.g., "ICCP", "XMP ", "EXIF", etc. +// Setting 'chunk_number' equal to 0 will return the last chunk in a set. +// Returns true if the chunk is found, false otherwise. Image related chunk +// payloads are accessed through WebPDemuxGetFrame() and related functions. +// Call WebPDemuxReleaseChunkIterator() when use of the iterator is complete. +// NOTE: 'dmux' must persist for the lifetime of the iterator. +WEBP_EXTERN int WebPDemuxGetChunk(const WebPDemuxer* dmux, + const char fourcc[4], int chunk_number, + WebPChunkIterator* iter); + +// Sets 'iter->chunk' to point to the next ('iter->chunk_num' + 1) or previous +// ('iter->chunk_num' - 1) chunk. These functions do not loop. +// Returns true on success, false otherwise. +WEBP_EXTERN int WebPDemuxNextChunk(WebPChunkIterator* iter); +WEBP_EXTERN int WebPDemuxPrevChunk(WebPChunkIterator* iter); + +// Releases any memory associated with 'iter'. +// Must be called before destroying the associated WebPDemuxer with +// WebPDemuxDelete(). +WEBP_EXTERN void WebPDemuxReleaseChunkIterator(WebPChunkIterator* iter); + +//------------------------------------------------------------------------------ +// WebPAnimDecoder API +// +// This API allows decoding (possibly) animated WebP images. +// +// Code Example: +/* + WebPAnimDecoderOptions dec_options; + WebPAnimDecoderOptionsInit(&dec_options); + // Tune 'dec_options' as needed. + WebPAnimDecoder* dec = WebPAnimDecoderNew(webp_data, &dec_options); + WebPAnimInfo anim_info; + WebPAnimDecoderGetInfo(dec, &anim_info); + for (uint32_t i = 0; i < anim_info.loop_count; ++i) { + while (WebPAnimDecoderHasMoreFrames(dec)) { + uint8_t* buf; + int timestamp; + WebPAnimDecoderGetNext(dec, &buf, ×tamp); + // ... (Render 'buf' based on 'timestamp'). + // ... (Do NOT free 'buf', as it is owned by 'dec'). + } + WebPAnimDecoderReset(dec); + } + const WebPDemuxer* demuxer = WebPAnimDecoderGetDemuxer(dec); + // ... (Do something using 'demuxer'; e.g. get EXIF/XMP/ICC data). + WebPAnimDecoderDelete(dec); +*/ + +typedef struct WebPAnimDecoder WebPAnimDecoder; // Main opaque object. + +// Global options. +struct WebPAnimDecoderOptions { + // Output colorspace. Only the following modes are supported: + // MODE_RGBA, MODE_BGRA, MODE_rgbA and MODE_bgrA. + WEBP_CSP_MODE color_mode; + int use_threads; // If true, use multi-threaded decoding. + uint32_t padding[7]; // Padding for later use. +}; + +// Internal, version-checked, entry point. +WEBP_EXTERN int WebPAnimDecoderOptionsInitInternal( + WebPAnimDecoderOptions*, int); + +// Should always be called, to initialize a fresh WebPAnimDecoderOptions +// structure before modification. Returns false in case of version mismatch. +// WebPAnimDecoderOptionsInit() must have succeeded before using the +// 'dec_options' object. +static WEBP_INLINE int WebPAnimDecoderOptionsInit( + WebPAnimDecoderOptions* dec_options) { + return WebPAnimDecoderOptionsInitInternal(dec_options, + WEBP_DEMUX_ABI_VERSION); +} + +// Internal, version-checked, entry point. +WEBP_EXTERN WebPAnimDecoder* WebPAnimDecoderNewInternal( + const WebPData*, const WebPAnimDecoderOptions*, int); + +// Creates and initializes a WebPAnimDecoder object. +// Parameters: +// webp_data - (in) WebP bitstream. This should remain unchanged during the +// lifetime of the output WebPAnimDecoder object. +// dec_options - (in) decoding options. Can be passed NULL to choose +// reasonable defaults (in particular, color mode MODE_RGBA +// will be picked). +// Returns: +// A pointer to the newly created WebPAnimDecoder object, or NULL in case of +// parsing error, invalid option or memory error. +static WEBP_INLINE WebPAnimDecoder* WebPAnimDecoderNew( + const WebPData* webp_data, const WebPAnimDecoderOptions* dec_options) { + return WebPAnimDecoderNewInternal(webp_data, dec_options, + WEBP_DEMUX_ABI_VERSION); +} + +// Global information about the animation.. +struct WebPAnimInfo { + uint32_t canvas_width; + uint32_t canvas_height; + uint32_t loop_count; + uint32_t bgcolor; + uint32_t frame_count; + uint32_t pad[4]; // padding for later use +}; + +// Get global information about the animation. +// Parameters: +// dec - (in) decoder instance to get information from. +// info - (out) global information fetched from the animation. +// Returns: +// True on success. +WEBP_EXTERN int WebPAnimDecoderGetInfo(const WebPAnimDecoder* dec, + WebPAnimInfo* info); + +// Fetch the next frame from 'dec' based on options supplied to +// WebPAnimDecoderNew(). This will be a fully reconstructed canvas of size +// 'canvas_width * 4 * canvas_height', and not just the frame sub-rectangle. The +// returned buffer 'buf' is valid only until the next call to +// WebPAnimDecoderGetNext(), WebPAnimDecoderReset() or WebPAnimDecoderDelete(). +// Parameters: +// dec - (in/out) decoder instance from which the next frame is to be fetched. +// buf - (out) decoded frame. +// timestamp - (out) timestamp of the frame in milliseconds. +// Returns: +// False if any of the arguments are NULL, or if there is a parsing or +// decoding error, or if there are no more frames. Otherwise, returns true. +WEBP_EXTERN int WebPAnimDecoderGetNext(WebPAnimDecoder* dec, + uint8_t** buf, int* timestamp); + +// Check if there are more frames left to decode. +// Parameters: +// dec - (in) decoder instance to be checked. +// Returns: +// True if 'dec' is not NULL and some frames are yet to be decoded. +// Otherwise, returns false. +WEBP_EXTERN int WebPAnimDecoderHasMoreFrames(const WebPAnimDecoder* dec); + +// Resets the WebPAnimDecoder object, so that next call to +// WebPAnimDecoderGetNext() will restart decoding from 1st frame. This would be +// helpful when all frames need to be decoded multiple times (e.g. +// info.loop_count times) without destroying and recreating the 'dec' object. +// Parameters: +// dec - (in/out) decoder instance to be reset +WEBP_EXTERN void WebPAnimDecoderReset(WebPAnimDecoder* dec); + +// Grab the internal demuxer object. +// Getting the demuxer object can be useful if one wants to use operations only +// available through demuxer; e.g. to get XMP/EXIF/ICC metadata. The returned +// demuxer object is owned by 'dec' and is valid only until the next call to +// WebPAnimDecoderDelete(). +// +// Parameters: +// dec - (in) decoder instance from which the demuxer object is to be fetched. +WEBP_EXTERN const WebPDemuxer* WebPAnimDecoderGetDemuxer( + const WebPAnimDecoder* dec); + +// Deletes the WebPAnimDecoder object. +// Parameters: +// dec - (in/out) decoder instance to be deleted +WEBP_EXTERN void WebPAnimDecoderDelete(WebPAnimDecoder* dec); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_WEBP_DEMUX_H_ diff --git a/third-party/webp/libwebp/src/webp/encode.h b/third-party/webp/libwebp/src/webp/encode.h new file mode 100644 index 0000000000..56b68e2f10 --- /dev/null +++ b/third-party/webp/libwebp/src/webp/encode.h @@ -0,0 +1,552 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// WebP encoder: main interface +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_WEBP_ENCODE_H_ +#define WEBP_WEBP_ENCODE_H_ + +#include "./types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define WEBP_ENCODER_ABI_VERSION 0x020f // MAJOR(8b) + MINOR(8b) + +// Note: forward declaring enumerations is not allowed in (strict) C and C++, +// the types are left here for reference. +// typedef enum WebPImageHint WebPImageHint; +// typedef enum WebPEncCSP WebPEncCSP; +// typedef enum WebPPreset WebPPreset; +// typedef enum WebPEncodingError WebPEncodingError; +typedef struct WebPConfig WebPConfig; +typedef struct WebPPicture WebPPicture; // main structure for I/O +typedef struct WebPAuxStats WebPAuxStats; +typedef struct WebPMemoryWriter WebPMemoryWriter; + +// Return the encoder's version number, packed in hexadecimal using 8bits for +// each of major/minor/revision. E.g: v2.5.7 is 0x020507. +WEBP_EXTERN int WebPGetEncoderVersion(void); + +//------------------------------------------------------------------------------ +// One-stop-shop call! No questions asked: + +// Returns the size of the compressed data (pointed to by *output), or 0 if +// an error occurred. The compressed data must be released by the caller +// using the call 'WebPFree(*output)'. +// These functions compress using the lossy format, and the quality_factor +// can go from 0 (smaller output, lower quality) to 100 (best quality, +// larger output). +WEBP_EXTERN size_t WebPEncodeRGB(const uint8_t* rgb, + int width, int height, int stride, + float quality_factor, uint8_t** output); +WEBP_EXTERN size_t WebPEncodeBGR(const uint8_t* bgr, + int width, int height, int stride, + float quality_factor, uint8_t** output); +WEBP_EXTERN size_t WebPEncodeRGBA(const uint8_t* rgba, + int width, int height, int stride, + float quality_factor, uint8_t** output); +WEBP_EXTERN size_t WebPEncodeBGRA(const uint8_t* bgra, + int width, int height, int stride, + float quality_factor, uint8_t** output); + +// These functions are the equivalent of the above, but compressing in a +// lossless manner. Files are usually larger than lossy format, but will +// not suffer any compression loss. +// Note these functions, like the lossy versions, use the library's default +// settings. For lossless this means 'exact' is disabled. RGB values in +// transparent areas will be modified to improve compression. To avoid this, +// use WebPEncode() and set WebPConfig::exact to 1. +WEBP_EXTERN size_t WebPEncodeLosslessRGB(const uint8_t* rgb, + int width, int height, int stride, + uint8_t** output); +WEBP_EXTERN size_t WebPEncodeLosslessBGR(const uint8_t* bgr, + int width, int height, int stride, + uint8_t** output); +WEBP_EXTERN size_t WebPEncodeLosslessRGBA(const uint8_t* rgba, + int width, int height, int stride, + uint8_t** output); +WEBP_EXTERN size_t WebPEncodeLosslessBGRA(const uint8_t* bgra, + int width, int height, int stride, + uint8_t** output); + +//------------------------------------------------------------------------------ +// Coding parameters + +// Image characteristics hint for the underlying encoder. +typedef enum WebPImageHint { + WEBP_HINT_DEFAULT = 0, // default preset. + WEBP_HINT_PICTURE, // digital picture, like portrait, inner shot + WEBP_HINT_PHOTO, // outdoor photograph, with natural lighting + WEBP_HINT_GRAPH, // Discrete tone image (graph, map-tile etc). + WEBP_HINT_LAST +} WebPImageHint; + +// Compression parameters. +struct WebPConfig { + int lossless; // Lossless encoding (0=lossy(default), 1=lossless). + float quality; // between 0 and 100. For lossy, 0 gives the smallest + // size and 100 the largest. For lossless, this + // parameter is the amount of effort put into the + // compression: 0 is the fastest but gives larger + // files compared to the slowest, but best, 100. + int method; // quality/speed trade-off (0=fast, 6=slower-better) + + WebPImageHint image_hint; // Hint for image type (lossless only for now). + + int target_size; // if non-zero, set the desired target size in bytes. + // Takes precedence over the 'compression' parameter. + float target_PSNR; // if non-zero, specifies the minimal distortion to + // try to achieve. Takes precedence over target_size. + int segments; // maximum number of segments to use, in [1..4] + int sns_strength; // Spatial Noise Shaping. 0=off, 100=maximum. + int filter_strength; // range: [0 = off .. 100 = strongest] + int filter_sharpness; // range: [0 = off .. 7 = least sharp] + int filter_type; // filtering type: 0 = simple, 1 = strong (only used + // if filter_strength > 0 or autofilter > 0) + int autofilter; // Auto adjust filter's strength [0 = off, 1 = on] + int alpha_compression; // Algorithm for encoding the alpha plane (0 = none, + // 1 = compressed with WebP lossless). Default is 1. + int alpha_filtering; // Predictive filtering method for alpha plane. + // 0: none, 1: fast, 2: best. Default if 1. + int alpha_quality; // Between 0 (smallest size) and 100 (lossless). + // Default is 100. + int pass; // number of entropy-analysis passes (in [1..10]). + + int show_compressed; // if true, export the compressed picture back. + // In-loop filtering is not applied. + int preprocessing; // preprocessing filter: + // 0=none, 1=segment-smooth, 2=pseudo-random dithering + int partitions; // log2(number of token partitions) in [0..3]. Default + // is set to 0 for easier progressive decoding. + int partition_limit; // quality degradation allowed to fit the 512k limit + // on prediction modes coding (0: no degradation, + // 100: maximum possible degradation). + int emulate_jpeg_size; // If true, compression parameters will be remapped + // to better match the expected output size from + // JPEG compression. Generally, the output size will + // be similar but the degradation will be lower. + int thread_level; // If non-zero, try and use multi-threaded encoding. + int low_memory; // If set, reduce memory usage (but increase CPU use). + + int near_lossless; // Near lossless encoding [0 = max loss .. 100 = off + // (default)]. + int exact; // if non-zero, preserve the exact RGB values under + // transparent area. Otherwise, discard this invisible + // RGB information for better compression. The default + // value is 0. + + int use_delta_palette; // reserved for future lossless feature + int use_sharp_yuv; // if needed, use sharp (and slow) RGB->YUV conversion + + int qmin; // minimum permissible quality factor + int qmax; // maximum permissible quality factor +}; + +// Enumerate some predefined settings for WebPConfig, depending on the type +// of source picture. These presets are used when calling WebPConfigPreset(). +typedef enum WebPPreset { + WEBP_PRESET_DEFAULT = 0, // default preset. + WEBP_PRESET_PICTURE, // digital picture, like portrait, inner shot + WEBP_PRESET_PHOTO, // outdoor photograph, with natural lighting + WEBP_PRESET_DRAWING, // hand or line drawing, with high-contrast details + WEBP_PRESET_ICON, // small-sized colorful images + WEBP_PRESET_TEXT // text-like +} WebPPreset; + +// Internal, version-checked, entry point +WEBP_EXTERN int WebPConfigInitInternal(WebPConfig*, WebPPreset, float, int); + +// Should always be called, to initialize a fresh WebPConfig structure before +// modification. Returns false in case of version mismatch. WebPConfigInit() +// must have succeeded before using the 'config' object. +// Note that the default values are lossless=0 and quality=75. +static WEBP_INLINE int WebPConfigInit(WebPConfig* config) { + return WebPConfigInitInternal(config, WEBP_PRESET_DEFAULT, 75.f, + WEBP_ENCODER_ABI_VERSION); +} + +// This function will initialize the configuration according to a predefined +// set of parameters (referred to by 'preset') and a given quality factor. +// This function can be called as a replacement to WebPConfigInit(). Will +// return false in case of error. +static WEBP_INLINE int WebPConfigPreset(WebPConfig* config, + WebPPreset preset, float quality) { + return WebPConfigInitInternal(config, preset, quality, + WEBP_ENCODER_ABI_VERSION); +} + +// Activate the lossless compression mode with the desired efficiency level +// between 0 (fastest, lowest compression) and 9 (slower, best compression). +// A good default level is '6', providing a fair tradeoff between compression +// speed and final compressed size. +// This function will overwrite several fields from config: 'method', 'quality' +// and 'lossless'. Returns false in case of parameter error. +WEBP_EXTERN int WebPConfigLosslessPreset(WebPConfig* config, int level); + +// Returns true if 'config' is non-NULL and all configuration parameters are +// within their valid ranges. +WEBP_EXTERN int WebPValidateConfig(const WebPConfig* config); + +//------------------------------------------------------------------------------ +// Input / Output +// Structure for storing auxiliary statistics. + +struct WebPAuxStats { + int coded_size; // final size + + float PSNR[5]; // peak-signal-to-noise ratio for Y/U/V/All/Alpha + int block_count[3]; // number of intra4/intra16/skipped macroblocks + int header_bytes[2]; // approximate number of bytes spent for header + // and mode-partition #0 + int residual_bytes[3][4]; // approximate number of bytes spent for + // DC/AC/uv coefficients for each (0..3) segments. + int segment_size[4]; // number of macroblocks in each segments + int segment_quant[4]; // quantizer values for each segments + int segment_level[4]; // filtering strength for each segments [0..63] + + int alpha_data_size; // size of the transparency data + int layer_data_size; // size of the enhancement layer data + + // lossless encoder statistics + uint32_t lossless_features; // bit0:predictor bit1:cross-color transform + // bit2:subtract-green bit3:color indexing + int histogram_bits; // number of precision bits of histogram + int transform_bits; // precision bits for transform + int cache_bits; // number of bits for color cache lookup + int palette_size; // number of color in palette, if used + int lossless_size; // final lossless size + int lossless_hdr_size; // lossless header (transform, huffman etc) size + int lossless_data_size; // lossless image data size + + uint32_t pad[2]; // padding for later use +}; + +// Signature for output function. Should return true if writing was successful. +// data/data_size is the segment of data to write, and 'picture' is for +// reference (and so one can make use of picture->custom_ptr). +typedef int (*WebPWriterFunction)(const uint8_t* data, size_t data_size, + const WebPPicture* picture); + +// WebPMemoryWrite: a special WebPWriterFunction that writes to memory using +// the following WebPMemoryWriter object (to be set as a custom_ptr). +struct WebPMemoryWriter { + uint8_t* mem; // final buffer (of size 'max_size', larger than 'size'). + size_t size; // final size + size_t max_size; // total capacity + uint32_t pad[1]; // padding for later use +}; + +// The following must be called first before any use. +WEBP_EXTERN void WebPMemoryWriterInit(WebPMemoryWriter* writer); + +// The following must be called to deallocate writer->mem memory. The 'writer' +// object itself is not deallocated. +WEBP_EXTERN void WebPMemoryWriterClear(WebPMemoryWriter* writer); +// The custom writer to be used with WebPMemoryWriter as custom_ptr. Upon +// completion, writer.mem and writer.size will hold the coded data. +// writer.mem must be freed by calling WebPMemoryWriterClear. +WEBP_EXTERN int WebPMemoryWrite(const uint8_t* data, size_t data_size, + const WebPPicture* picture); + +// Progress hook, called from time to time to report progress. It can return +// false to request an abort of the encoding process, or true otherwise if +// everything is OK. +typedef int (*WebPProgressHook)(int percent, const WebPPicture* picture); + +// Color spaces. +typedef enum WebPEncCSP { + // chroma sampling + WEBP_YUV420 = 0, // 4:2:0 + WEBP_YUV420A = 4, // alpha channel variant + WEBP_CSP_UV_MASK = 3, // bit-mask to get the UV sampling factors + WEBP_CSP_ALPHA_BIT = 4 // bit that is set if alpha is present +} WebPEncCSP; + +// Encoding error conditions. +typedef enum WebPEncodingError { + VP8_ENC_OK = 0, + VP8_ENC_ERROR_OUT_OF_MEMORY, // memory error allocating objects + VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY, // memory error while flushing bits + VP8_ENC_ERROR_NULL_PARAMETER, // a pointer parameter is NULL + VP8_ENC_ERROR_INVALID_CONFIGURATION, // configuration is invalid + VP8_ENC_ERROR_BAD_DIMENSION, // picture has invalid width/height + VP8_ENC_ERROR_PARTITION0_OVERFLOW, // partition is bigger than 512k + VP8_ENC_ERROR_PARTITION_OVERFLOW, // partition is bigger than 16M + VP8_ENC_ERROR_BAD_WRITE, // error while flushing bytes + VP8_ENC_ERROR_FILE_TOO_BIG, // file is bigger than 4G + VP8_ENC_ERROR_USER_ABORT, // abort request by user + VP8_ENC_ERROR_LAST // list terminator. always last. +} WebPEncodingError; + +// maximum width/height allowed (inclusive), in pixels +#define WEBP_MAX_DIMENSION 16383 + +// Main exchange structure (input samples, output bytes, statistics) +// +// Once WebPPictureInit() has been called, it's ok to make all the INPUT fields +// (use_argb, y/u/v, argb, ...) point to user-owned data, even if +// WebPPictureAlloc() has been called. Depending on the value use_argb, +// it's guaranteed that either *argb or *y/*u/*v content will be kept untouched. +struct WebPPicture { + // INPUT + ////////////// + // Main flag for encoder selecting between ARGB or YUV input. + // It is recommended to use ARGB input (*argb, argb_stride) for lossless + // compression, and YUV input (*y, *u, *v, etc.) for lossy compression + // since these are the respective native colorspace for these formats. + int use_argb; + + // YUV input (mostly used for input to lossy compression) + WebPEncCSP colorspace; // colorspace: should be YUV420 for now (=Y'CbCr). + int width, height; // dimensions (less or equal to WEBP_MAX_DIMENSION) + uint8_t* y, *u, *v; // pointers to luma/chroma planes. + int y_stride, uv_stride; // luma/chroma strides. + uint8_t* a; // pointer to the alpha plane + int a_stride; // stride of the alpha plane + uint32_t pad1[2]; // padding for later use + + // ARGB input (mostly used for input to lossless compression) + uint32_t* argb; // Pointer to argb (32 bit) plane. + int argb_stride; // This is stride in pixels units, not bytes. + uint32_t pad2[3]; // padding for later use + + // OUTPUT + /////////////// + // Byte-emission hook, to store compressed bytes as they are ready. + WebPWriterFunction writer; // can be NULL + void* custom_ptr; // can be used by the writer. + + // map for extra information (only for lossy compression mode) + int extra_info_type; // 1: intra type, 2: segment, 3: quant + // 4: intra-16 prediction mode, + // 5: chroma prediction mode, + // 6: bit cost, 7: distortion + uint8_t* extra_info; // if not NULL, points to an array of size + // ((width + 15) / 16) * ((height + 15) / 16) that + // will be filled with a macroblock map, depending + // on extra_info_type. + + // STATS AND REPORTS + /////////////////////////// + // Pointer to side statistics (updated only if not NULL) + WebPAuxStats* stats; + + // Error code for the latest error encountered during encoding + WebPEncodingError error_code; + + // If not NULL, report progress during encoding. + WebPProgressHook progress_hook; + + void* user_data; // this field is free to be set to any value and + // used during callbacks (like progress-report e.g.). + + uint32_t pad3[3]; // padding for later use + + // Unused for now + uint8_t* pad4, *pad5; + uint32_t pad6[8]; // padding for later use + + // PRIVATE FIELDS + //////////////////// + void* memory_; // row chunk of memory for yuva planes + void* memory_argb_; // and for argb too. + void* pad7[2]; // padding for later use +}; + +// Internal, version-checked, entry point +WEBP_EXTERN int WebPPictureInitInternal(WebPPicture*, int); + +// Should always be called, to initialize the structure. Returns false in case +// of version mismatch. WebPPictureInit() must have succeeded before using the +// 'picture' object. +// Note that, by default, use_argb is false and colorspace is WEBP_YUV420. +static WEBP_INLINE int WebPPictureInit(WebPPicture* picture) { + return WebPPictureInitInternal(picture, WEBP_ENCODER_ABI_VERSION); +} + +//------------------------------------------------------------------------------ +// WebPPicture utils + +// Convenience allocation / deallocation based on picture->width/height: +// Allocate y/u/v buffers as per colorspace/width/height specification. +// Note! This function will free the previous buffer if needed. +// Returns false in case of memory error. +WEBP_EXTERN int WebPPictureAlloc(WebPPicture* picture); + +// Release the memory allocated by WebPPictureAlloc() or WebPPictureImport*(). +// Note that this function does _not_ free the memory used by the 'picture' +// object itself. +// Besides memory (which is reclaimed) all other fields of 'picture' are +// preserved. +WEBP_EXTERN void WebPPictureFree(WebPPicture* picture); + +// Copy the pixels of *src into *dst, using WebPPictureAlloc. Upon return, *dst +// will fully own the copied pixels (this is not a view). The 'dst' picture need +// not be initialized as its content is overwritten. +// Returns false in case of memory allocation error. +WEBP_EXTERN int WebPPictureCopy(const WebPPicture* src, WebPPicture* dst); + +// Compute the single distortion for packed planes of samples. +// 'src' will be compared to 'ref', and the raw distortion stored into +// '*distortion'. The refined metric (log(MSE), log(1 - ssim),...' will be +// stored in '*result'. +// 'x_step' is the horizontal stride (in bytes) between samples. +// 'src/ref_stride' is the byte distance between rows. +// Returns false in case of error (bad parameter, memory allocation error, ...). +WEBP_EXTERN int WebPPlaneDistortion(const uint8_t* src, size_t src_stride, + const uint8_t* ref, size_t ref_stride, + int width, int height, + size_t x_step, + int type, // 0 = PSNR, 1 = SSIM, 2 = LSIM + float* distortion, float* result); + +// Compute PSNR, SSIM or LSIM distortion metric between two pictures. Results +// are in dB, stored in result[] in the B/G/R/A/All order. The distortion is +// always performed using ARGB samples. Hence if the input is YUV(A), the +// picture will be internally converted to ARGB (just for the measurement). +// Warning: this function is rather CPU-intensive. +WEBP_EXTERN int WebPPictureDistortion( + const WebPPicture* src, const WebPPicture* ref, + int metric_type, // 0 = PSNR, 1 = SSIM, 2 = LSIM + float result[5]); + +// self-crops a picture to the rectangle defined by top/left/width/height. +// Returns false in case of memory allocation error, or if the rectangle is +// outside of the source picture. +// The rectangle for the view is defined by the top-left corner pixel +// coordinates (left, top) as well as its width and height. This rectangle +// must be fully be comprised inside the 'src' source picture. If the source +// picture uses the YUV420 colorspace, the top and left coordinates will be +// snapped to even values. +WEBP_EXTERN int WebPPictureCrop(WebPPicture* picture, + int left, int top, int width, int height); + +// Extracts a view from 'src' picture into 'dst'. The rectangle for the view +// is defined by the top-left corner pixel coordinates (left, top) as well +// as its width and height. This rectangle must be fully be comprised inside +// the 'src' source picture. If the source picture uses the YUV420 colorspace, +// the top and left coordinates will be snapped to even values. +// Picture 'src' must out-live 'dst' picture. Self-extraction of view is allowed +// ('src' equal to 'dst') as a mean of fast-cropping (but note that doing so, +// the original dimension will be lost). Picture 'dst' need not be initialized +// with WebPPictureInit() if it is different from 'src', since its content will +// be overwritten. +// Returns false in case of invalid parameters. +WEBP_EXTERN int WebPPictureView(const WebPPicture* src, + int left, int top, int width, int height, + WebPPicture* dst); + +// Returns true if the 'picture' is actually a view and therefore does +// not own the memory for pixels. +WEBP_EXTERN int WebPPictureIsView(const WebPPicture* picture); + +// Rescale a picture to new dimension width x height. +// If either 'width' or 'height' (but not both) is 0 the corresponding +// dimension will be calculated preserving the aspect ratio. +// No gamma correction is applied. +// Returns false in case of error (invalid parameter or insufficient memory). +WEBP_EXTERN int WebPPictureRescale(WebPPicture* picture, int width, int height); + +// Colorspace conversion function to import RGB samples. +// Previous buffer will be free'd, if any. +// *rgb buffer should have a size of at least height * rgb_stride. +// Returns false in case of memory error. +WEBP_EXTERN int WebPPictureImportRGB( + WebPPicture* picture, const uint8_t* rgb, int rgb_stride); +// Same, but for RGBA buffer. +WEBP_EXTERN int WebPPictureImportRGBA( + WebPPicture* picture, const uint8_t* rgba, int rgba_stride); +// Same, but for RGBA buffer. Imports the RGB direct from the 32-bit format +// input buffer ignoring the alpha channel. Avoids needing to copy the data +// to a temporary 24-bit RGB buffer to import the RGB only. +WEBP_EXTERN int WebPPictureImportRGBX( + WebPPicture* picture, const uint8_t* rgbx, int rgbx_stride); + +// Variants of the above, but taking BGR(A|X) input. +WEBP_EXTERN int WebPPictureImportBGR( + WebPPicture* picture, const uint8_t* bgr, int bgr_stride); +WEBP_EXTERN int WebPPictureImportBGRA( + WebPPicture* picture, const uint8_t* bgra, int bgra_stride); +WEBP_EXTERN int WebPPictureImportBGRX( + WebPPicture* picture, const uint8_t* bgrx, int bgrx_stride); + +// Converts picture->argb data to the YUV420A format. The 'colorspace' +// parameter is deprecated and should be equal to WEBP_YUV420. +// Upon return, picture->use_argb is set to false. The presence of real +// non-opaque transparent values is detected, and 'colorspace' will be +// adjusted accordingly. Note that this method is lossy. +// Returns false in case of error. +WEBP_EXTERN int WebPPictureARGBToYUVA(WebPPicture* picture, + WebPEncCSP /*colorspace = WEBP_YUV420*/); + +// Same as WebPPictureARGBToYUVA(), but the conversion is done using +// pseudo-random dithering with a strength 'dithering' between +// 0.0 (no dithering) and 1.0 (maximum dithering). This is useful +// for photographic picture. +WEBP_EXTERN int WebPPictureARGBToYUVADithered( + WebPPicture* picture, WebPEncCSP colorspace, float dithering); + +// Performs 'sharp' RGBA->YUVA420 downsampling and colorspace conversion. +// Downsampling is handled with extra care in case of color clipping. This +// method is roughly 2x slower than WebPPictureARGBToYUVA() but produces better +// and sharper YUV representation. +// Returns false in case of error. +WEBP_EXTERN int WebPPictureSharpARGBToYUVA(WebPPicture* picture); +// kept for backward compatibility: +WEBP_EXTERN int WebPPictureSmartARGBToYUVA(WebPPicture* picture); + +// Converts picture->yuv to picture->argb and sets picture->use_argb to true. +// The input format must be YUV_420 or YUV_420A. The conversion from YUV420 to +// ARGB incurs a small loss too. +// Note that the use of this colorspace is discouraged if one has access to the +// raw ARGB samples, since using YUV420 is comparatively lossy. +// Returns false in case of error. +WEBP_EXTERN int WebPPictureYUVAToARGB(WebPPicture* picture); + +// Helper function: given a width x height plane of RGBA or YUV(A) samples +// clean-up or smoothen the YUV or RGB samples under fully transparent area, +// to help compressibility (no guarantee, though). +WEBP_EXTERN void WebPCleanupTransparentArea(WebPPicture* picture); + +// Scan the picture 'picture' for the presence of non fully opaque alpha values. +// Returns true in such case. Otherwise returns false (indicating that the +// alpha plane can be ignored altogether e.g.). +WEBP_EXTERN int WebPPictureHasTransparency(const WebPPicture* picture); + +// Remove the transparency information (if present) by blending the color with +// the background color 'background_rgb' (specified as 24bit RGB triplet). +// After this call, all alpha values are reset to 0xff. +WEBP_EXTERN void WebPBlendAlpha(WebPPicture* picture, uint32_t background_rgb); + +//------------------------------------------------------------------------------ +// Main call + +// Main encoding call, after config and picture have been initialized. +// 'picture' must be less than 16384x16384 in dimension (cf WEBP_MAX_DIMENSION), +// and the 'config' object must be a valid one. +// Returns false in case of error, true otherwise. +// In case of error, picture->error_code is updated accordingly. +// 'picture' can hold the source samples in both YUV(A) or ARGB input, depending +// on the value of 'picture->use_argb'. It is highly recommended to use +// the former for lossy encoding, and the latter for lossless encoding +// (when config.lossless is true). Automatic conversion from one format to +// another is provided but they both incur some loss. +WEBP_EXTERN int WebPEncode(const WebPConfig* config, WebPPicture* picture); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_WEBP_ENCODE_H_ diff --git a/third-party/webp/libwebp/src/webp/format_constants.h b/third-party/webp/libwebp/src/webp/format_constants.h new file mode 100644 index 0000000000..999035c5d2 --- /dev/null +++ b/third-party/webp/libwebp/src/webp/format_constants.h @@ -0,0 +1,87 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Internal header for constants related to WebP file format. +// +// Author: Urvang (urvang@google.com) + +#ifndef WEBP_WEBP_FORMAT_CONSTANTS_H_ +#define WEBP_WEBP_FORMAT_CONSTANTS_H_ + +// Create fourcc of the chunk from the chunk tag characters. +#define MKFOURCC(a, b, c, d) ((a) | (b) << 8 | (c) << 16 | (uint32_t)(d) << 24) + +// VP8 related constants. +#define VP8_SIGNATURE 0x9d012a // Signature in VP8 data. +#define VP8_MAX_PARTITION0_SIZE (1 << 19) // max size of mode partition +#define VP8_MAX_PARTITION_SIZE (1 << 24) // max size for token partition +#define VP8_FRAME_HEADER_SIZE 10 // Size of the frame header within VP8 data. + +// VP8L related constants. +#define VP8L_SIGNATURE_SIZE 1 // VP8L signature size. +#define VP8L_MAGIC_BYTE 0x2f // VP8L signature byte. +#define VP8L_IMAGE_SIZE_BITS 14 // Number of bits used to store + // width and height. +#define VP8L_VERSION_BITS 3 // 3 bits reserved for version. +#define VP8L_VERSION 0 // version 0 +#define VP8L_FRAME_HEADER_SIZE 5 // Size of the VP8L frame header. + +#define MAX_PALETTE_SIZE 256 +#define MAX_CACHE_BITS 11 +#define HUFFMAN_CODES_PER_META_CODE 5 +#define ARGB_BLACK 0xff000000 + +#define DEFAULT_CODE_LENGTH 8 +#define MAX_ALLOWED_CODE_LENGTH 15 + +#define NUM_LITERAL_CODES 256 +#define NUM_LENGTH_CODES 24 +#define NUM_DISTANCE_CODES 40 +#define CODE_LENGTH_CODES 19 + +#define MIN_HUFFMAN_BITS 2 // min number of Huffman bits +#define MAX_HUFFMAN_BITS 9 // max number of Huffman bits + +#define TRANSFORM_PRESENT 1 // The bit to be written when next data + // to be read is a transform. +#define NUM_TRANSFORMS 4 // Maximum number of allowed transform + // in a bitstream. +typedef enum { + PREDICTOR_TRANSFORM = 0, + CROSS_COLOR_TRANSFORM = 1, + SUBTRACT_GREEN_TRANSFORM = 2, + COLOR_INDEXING_TRANSFORM = 3 +} VP8LImageTransformType; + +// Alpha related constants. +#define ALPHA_HEADER_LEN 1 +#define ALPHA_NO_COMPRESSION 0 +#define ALPHA_LOSSLESS_COMPRESSION 1 +#define ALPHA_PREPROCESSED_LEVELS 1 + +// Mux related constants. +#define TAG_SIZE 4 // Size of a chunk tag (e.g. "VP8L"). +#define CHUNK_SIZE_BYTES 4 // Size needed to store chunk's size. +#define CHUNK_HEADER_SIZE 8 // Size of a chunk header. +#define RIFF_HEADER_SIZE 12 // Size of the RIFF header ("RIFFnnnnWEBP"). +#define ANMF_CHUNK_SIZE 16 // Size of an ANMF chunk. +#define ANIM_CHUNK_SIZE 6 // Size of an ANIM chunk. +#define VP8X_CHUNK_SIZE 10 // Size of a VP8X chunk. + +#define MAX_CANVAS_SIZE (1 << 24) // 24-bit max for VP8X width/height. +#define MAX_IMAGE_AREA (1ULL << 32) // 32-bit max for width x height. +#define MAX_LOOP_COUNT (1 << 16) // maximum value for loop-count +#define MAX_DURATION (1 << 24) // maximum duration +#define MAX_POSITION_OFFSET (1 << 24) // maximum frame x/y offset + +// Maximum chunk payload is such that adding the header and padding won't +// overflow a uint32_t. +#define MAX_CHUNK_PAYLOAD (~0U - CHUNK_HEADER_SIZE - 1) + +#endif // WEBP_WEBP_FORMAT_CONSTANTS_H_ diff --git a/third-party/webp/libwebp/src/webp/mux.h b/third-party/webp/libwebp/src/webp/mux.h new file mode 100644 index 0000000000..7d27489a40 --- /dev/null +++ b/third-party/webp/libwebp/src/webp/mux.h @@ -0,0 +1,530 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// RIFF container manipulation and encoding for WebP images. +// +// Authors: Urvang (urvang@google.com) +// Vikas (vikasa@google.com) + +#ifndef WEBP_WEBP_MUX_H_ +#define WEBP_WEBP_MUX_H_ + +#include "./mux_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define WEBP_MUX_ABI_VERSION 0x0108 // MAJOR(8b) + MINOR(8b) + +//------------------------------------------------------------------------------ +// Mux API +// +// This API allows manipulation of WebP container images containing features +// like color profile, metadata, animation. +// +// Code Example#1: Create a WebPMux object with image data, color profile and +// XMP metadata. +/* + int copy_data = 0; + WebPMux* mux = WebPMuxNew(); + // ... (Prepare image data). + WebPMuxSetImage(mux, &image, copy_data); + // ... (Prepare ICCP color profile data). + WebPMuxSetChunk(mux, "ICCP", &icc_profile, copy_data); + // ... (Prepare XMP metadata). + WebPMuxSetChunk(mux, "XMP ", &xmp, copy_data); + // Get data from mux in WebP RIFF format. + WebPMuxAssemble(mux, &output_data); + WebPMuxDelete(mux); + // ... (Consume output_data; e.g. write output_data.bytes to file). + WebPDataClear(&output_data); +*/ + +// Code Example#2: Get image and color profile data from a WebP file. +/* + int copy_data = 0; + // ... (Read data from file). + WebPMux* mux = WebPMuxCreate(&data, copy_data); + WebPMuxGetFrame(mux, 1, &image); + // ... (Consume image; e.g. call WebPDecode() to decode the data). + WebPMuxGetChunk(mux, "ICCP", &icc_profile); + // ... (Consume icc_data). + WebPMuxDelete(mux); + WebPFree(data); +*/ + +// Note: forward declaring enumerations is not allowed in (strict) C and C++, +// the types are left here for reference. +// typedef enum WebPMuxError WebPMuxError; +// typedef enum WebPChunkId WebPChunkId; +typedef struct WebPMux WebPMux; // main opaque object. +typedef struct WebPMuxFrameInfo WebPMuxFrameInfo; +typedef struct WebPMuxAnimParams WebPMuxAnimParams; +typedef struct WebPAnimEncoderOptions WebPAnimEncoderOptions; + +// Error codes +typedef enum WebPMuxError { + WEBP_MUX_OK = 1, + WEBP_MUX_NOT_FOUND = 0, + WEBP_MUX_INVALID_ARGUMENT = -1, + WEBP_MUX_BAD_DATA = -2, + WEBP_MUX_MEMORY_ERROR = -3, + WEBP_MUX_NOT_ENOUGH_DATA = -4 +} WebPMuxError; + +// IDs for different types of chunks. +typedef enum WebPChunkId { + WEBP_CHUNK_VP8X, // VP8X + WEBP_CHUNK_ICCP, // ICCP + WEBP_CHUNK_ANIM, // ANIM + WEBP_CHUNK_ANMF, // ANMF + WEBP_CHUNK_DEPRECATED, // (deprecated from FRGM) + WEBP_CHUNK_ALPHA, // ALPH + WEBP_CHUNK_IMAGE, // VP8/VP8L + WEBP_CHUNK_EXIF, // EXIF + WEBP_CHUNK_XMP, // XMP + WEBP_CHUNK_UNKNOWN, // Other chunks. + WEBP_CHUNK_NIL +} WebPChunkId; + +//------------------------------------------------------------------------------ + +// Returns the version number of the mux library, packed in hexadecimal using +// 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507. +WEBP_EXTERN int WebPGetMuxVersion(void); + +//------------------------------------------------------------------------------ +// Life of a Mux object + +// Internal, version-checked, entry point +WEBP_EXTERN WebPMux* WebPNewInternal(int); + +// Creates an empty mux object. +// Returns: +// A pointer to the newly created empty mux object. +// Or NULL in case of memory error. +static WEBP_INLINE WebPMux* WebPMuxNew(void) { + return WebPNewInternal(WEBP_MUX_ABI_VERSION); +} + +// Deletes the mux object. +// Parameters: +// mux - (in/out) object to be deleted +WEBP_EXTERN void WebPMuxDelete(WebPMux* mux); + +//------------------------------------------------------------------------------ +// Mux creation. + +// Internal, version-checked, entry point +WEBP_EXTERN WebPMux* WebPMuxCreateInternal(const WebPData*, int, int); + +// Creates a mux object from raw data given in WebP RIFF format. +// Parameters: +// bitstream - (in) the bitstream data in WebP RIFF format +// copy_data - (in) value 1 indicates given data WILL be copied to the mux +// object and value 0 indicates data will NOT be copied. +// Returns: +// A pointer to the mux object created from given data - on success. +// NULL - In case of invalid data or memory error. +static WEBP_INLINE WebPMux* WebPMuxCreate(const WebPData* bitstream, + int copy_data) { + return WebPMuxCreateInternal(bitstream, copy_data, WEBP_MUX_ABI_VERSION); +} + +//------------------------------------------------------------------------------ +// Non-image chunks. + +// Note: Only non-image related chunks should be managed through chunk APIs. +// (Image related chunks are: "ANMF", "VP8 ", "VP8L" and "ALPH"). +// To add, get and delete images, use WebPMuxSetImage(), WebPMuxPushFrame(), +// WebPMuxGetFrame() and WebPMuxDeleteFrame(). + +// Adds a chunk with id 'fourcc' and data 'chunk_data' in the mux object. +// Any existing chunk(s) with the same id will be removed. +// Parameters: +// mux - (in/out) object to which the chunk is to be added +// fourcc - (in) a character array containing the fourcc of the given chunk; +// e.g., "ICCP", "XMP ", "EXIF" etc. +// chunk_data - (in) the chunk data to be added +// copy_data - (in) value 1 indicates given data WILL be copied to the mux +// object and value 0 indicates data will NOT be copied. +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if mux, fourcc or chunk_data is NULL +// or if fourcc corresponds to an image chunk. +// WEBP_MUX_MEMORY_ERROR - on memory allocation error. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPMuxSetChunk( + WebPMux* mux, const char fourcc[4], const WebPData* chunk_data, + int copy_data); + +// Gets a reference to the data of the chunk with id 'fourcc' in the mux object. +// The caller should NOT free the returned data. +// Parameters: +// mux - (in) object from which the chunk data is to be fetched +// fourcc - (in) a character array containing the fourcc of the chunk; +// e.g., "ICCP", "XMP ", "EXIF" etc. +// chunk_data - (out) returned chunk data +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if mux, fourcc or chunk_data is NULL +// or if fourcc corresponds to an image chunk. +// WEBP_MUX_NOT_FOUND - If mux does not contain a chunk with the given id. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPMuxGetChunk( + const WebPMux* mux, const char fourcc[4], WebPData* chunk_data); + +// Deletes the chunk with the given 'fourcc' from the mux object. +// Parameters: +// mux - (in/out) object from which the chunk is to be deleted +// fourcc - (in) a character array containing the fourcc of the chunk; +// e.g., "ICCP", "XMP ", "EXIF" etc. +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if mux or fourcc is NULL +// or if fourcc corresponds to an image chunk. +// WEBP_MUX_NOT_FOUND - If mux does not contain a chunk with the given fourcc. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPMuxDeleteChunk( + WebPMux* mux, const char fourcc[4]); + +//------------------------------------------------------------------------------ +// Images. + +// Encapsulates data about a single frame. +struct WebPMuxFrameInfo { + WebPData bitstream; // image data: can be a raw VP8/VP8L bitstream + // or a single-image WebP file. + int x_offset; // x-offset of the frame. + int y_offset; // y-offset of the frame. + int duration; // duration of the frame (in milliseconds). + + WebPChunkId id; // frame type: should be one of WEBP_CHUNK_ANMF + // or WEBP_CHUNK_IMAGE + WebPMuxAnimDispose dispose_method; // Disposal method for the frame. + WebPMuxAnimBlend blend_method; // Blend operation for the frame. + uint32_t pad[1]; // padding for later use +}; + +// Sets the (non-animated) image in the mux object. +// Note: Any existing images (including frames) will be removed. +// Parameters: +// mux - (in/out) object in which the image is to be set +// bitstream - (in) can be a raw VP8/VP8L bitstream or a single-image +// WebP file (non-animated) +// copy_data - (in) value 1 indicates given data WILL be copied to the mux +// object and value 0 indicates data will NOT be copied. +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL or bitstream is NULL. +// WEBP_MUX_MEMORY_ERROR - on memory allocation error. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPMuxSetImage( + WebPMux* mux, const WebPData* bitstream, int copy_data); + +// Adds a frame at the end of the mux object. +// Notes: (1) frame.id should be WEBP_CHUNK_ANMF +// (2) For setting a non-animated image, use WebPMuxSetImage() instead. +// (3) Type of frame being pushed must be same as the frames in mux. +// (4) As WebP only supports even offsets, any odd offset will be snapped +// to an even location using: offset &= ~1 +// Parameters: +// mux - (in/out) object to which the frame is to be added +// frame - (in) frame data. +// copy_data - (in) value 1 indicates given data WILL be copied to the mux +// object and value 0 indicates data will NOT be copied. +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if mux or frame is NULL +// or if content of 'frame' is invalid. +// WEBP_MUX_MEMORY_ERROR - on memory allocation error. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPMuxPushFrame( + WebPMux* mux, const WebPMuxFrameInfo* frame, int copy_data); + +// Gets the nth frame from the mux object. +// The content of 'frame->bitstream' is allocated using WebPMalloc(), and NOT +// owned by the 'mux' object. It MUST be deallocated by the caller by calling +// WebPDataClear(). +// nth=0 has a special meaning - last position. +// Parameters: +// mux - (in) object from which the info is to be fetched +// nth - (in) index of the frame in the mux object +// frame - (out) data of the returned frame +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if mux or frame is NULL. +// WEBP_MUX_NOT_FOUND - if there are less than nth frames in the mux object. +// WEBP_MUX_BAD_DATA - if nth frame chunk in mux is invalid. +// WEBP_MUX_MEMORY_ERROR - on memory allocation error. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPMuxGetFrame( + const WebPMux* mux, uint32_t nth, WebPMuxFrameInfo* frame); + +// Deletes a frame from the mux object. +// nth=0 has a special meaning - last position. +// Parameters: +// mux - (in/out) object from which a frame is to be deleted +// nth - (in) The position from which the frame is to be deleted +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL. +// WEBP_MUX_NOT_FOUND - If there are less than nth frames in the mux object +// before deletion. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPMuxDeleteFrame(WebPMux* mux, uint32_t nth); + +//------------------------------------------------------------------------------ +// Animation. + +// Animation parameters. +struct WebPMuxAnimParams { + uint32_t bgcolor; // Background color of the canvas stored (in MSB order) as: + // Bits 00 to 07: Alpha. + // Bits 08 to 15: Red. + // Bits 16 to 23: Green. + // Bits 24 to 31: Blue. + int loop_count; // Number of times to repeat the animation [0 = infinite]. +}; + +// Sets the animation parameters in the mux object. Any existing ANIM chunks +// will be removed. +// Parameters: +// mux - (in/out) object in which ANIM chunk is to be set/added +// params - (in) animation parameters. +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if mux or params is NULL. +// WEBP_MUX_MEMORY_ERROR - on memory allocation error. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPMuxSetAnimationParams( + WebPMux* mux, const WebPMuxAnimParams* params); + +// Gets the animation parameters from the mux object. +// Parameters: +// mux - (in) object from which the animation parameters to be fetched +// params - (out) animation parameters extracted from the ANIM chunk +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if mux or params is NULL. +// WEBP_MUX_NOT_FOUND - if ANIM chunk is not present in mux object. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPMuxGetAnimationParams( + const WebPMux* mux, WebPMuxAnimParams* params); + +//------------------------------------------------------------------------------ +// Misc Utilities. + +// Sets the canvas size for the mux object. The width and height can be +// specified explicitly or left as zero (0, 0). +// * When width and height are specified explicitly, then this frame bound is +// enforced during subsequent calls to WebPMuxAssemble() and an error is +// reported if any animated frame does not completely fit within the canvas. +// * When unspecified (0, 0), the constructed canvas will get the frame bounds +// from the bounding-box over all frames after calling WebPMuxAssemble(). +// Parameters: +// mux - (in) object to which the canvas size is to be set +// width - (in) canvas width +// height - (in) canvas height +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL; or +// width or height are invalid or out of bounds +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPMuxSetCanvasSize(WebPMux* mux, + int width, int height); + +// Gets the canvas size from the mux object. +// Note: This method assumes that the VP8X chunk, if present, is up-to-date. +// That is, the mux object hasn't been modified since the last call to +// WebPMuxAssemble() or WebPMuxCreate(). +// Parameters: +// mux - (in) object from which the canvas size is to be fetched +// width - (out) canvas width +// height - (out) canvas height +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if mux, width or height is NULL. +// WEBP_MUX_BAD_DATA - if VP8X/VP8/VP8L chunk or canvas size is invalid. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPMuxGetCanvasSize(const WebPMux* mux, + int* width, int* height); + +// Gets the feature flags from the mux object. +// Note: This method assumes that the VP8X chunk, if present, is up-to-date. +// That is, the mux object hasn't been modified since the last call to +// WebPMuxAssemble() or WebPMuxCreate(). +// Parameters: +// mux - (in) object from which the features are to be fetched +// flags - (out) the flags specifying which features are present in the +// mux object. This will be an OR of various flag values. +// Enum 'WebPFeatureFlags' can be used to test individual flag values. +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if mux or flags is NULL. +// WEBP_MUX_BAD_DATA - if VP8X/VP8/VP8L chunk or canvas size is invalid. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPMuxGetFeatures(const WebPMux* mux, + uint32_t* flags); + +// Gets number of chunks with the given 'id' in the mux object. +// Parameters: +// mux - (in) object from which the info is to be fetched +// id - (in) chunk id specifying the type of chunk +// num_elements - (out) number of chunks with the given chunk id +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if mux, or num_elements is NULL. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPMuxNumChunks(const WebPMux* mux, + WebPChunkId id, int* num_elements); + +// Assembles all chunks in WebP RIFF format and returns in 'assembled_data'. +// This function also validates the mux object. +// Note: The content of 'assembled_data' will be ignored and overwritten. +// Also, the content of 'assembled_data' is allocated using WebPMalloc(), and +// NOT owned by the 'mux' object. It MUST be deallocated by the caller by +// calling WebPDataClear(). It's always safe to call WebPDataClear() upon +// return, even in case of error. +// Parameters: +// mux - (in/out) object whose chunks are to be assembled +// assembled_data - (out) assembled WebP data +// Returns: +// WEBP_MUX_BAD_DATA - if mux object is invalid. +// WEBP_MUX_INVALID_ARGUMENT - if mux or assembled_data is NULL. +// WEBP_MUX_MEMORY_ERROR - on memory allocation error. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPMuxAssemble(WebPMux* mux, + WebPData* assembled_data); + +//------------------------------------------------------------------------------ +// WebPAnimEncoder API +// +// This API allows encoding (possibly) animated WebP images. +// +// Code Example: +/* + WebPAnimEncoderOptions enc_options; + WebPAnimEncoderOptionsInit(&enc_options); + // Tune 'enc_options' as needed. + WebPAnimEncoder* enc = WebPAnimEncoderNew(width, height, &enc_options); + while() { + WebPConfig config; + WebPConfigInit(&config); + // Tune 'config' as needed. + WebPAnimEncoderAdd(enc, frame, timestamp_ms, &config); + } + WebPAnimEncoderAdd(enc, NULL, timestamp_ms, NULL); + WebPAnimEncoderAssemble(enc, webp_data); + WebPAnimEncoderDelete(enc); + // Write the 'webp_data' to a file, or re-mux it further. +*/ + +typedef struct WebPAnimEncoder WebPAnimEncoder; // Main opaque object. + +// Forward declarations. Defined in encode.h. +struct WebPPicture; +struct WebPConfig; + +// Global options. +struct WebPAnimEncoderOptions { + WebPMuxAnimParams anim_params; // Animation parameters. + int minimize_size; // If true, minimize the output size (slow). Implicitly + // disables key-frame insertion. + int kmin; + int kmax; // Minimum and maximum distance between consecutive key + // frames in the output. The library may insert some key + // frames as needed to satisfy this criteria. + // Note that these conditions should hold: kmax > kmin + // and kmin >= kmax / 2 + 1. Also, if kmax <= 0, then + // key-frame insertion is disabled; and if kmax == 1, + // then all frames will be key-frames (kmin value does + // not matter for these special cases). + int allow_mixed; // If true, use mixed compression mode; may choose + // either lossy and lossless for each frame. + int verbose; // If true, print info and warning messages to stderr. + + uint32_t padding[4]; // Padding for later use. +}; + +// Internal, version-checked, entry point. +WEBP_EXTERN int WebPAnimEncoderOptionsInitInternal( + WebPAnimEncoderOptions*, int); + +// Should always be called, to initialize a fresh WebPAnimEncoderOptions +// structure before modification. Returns false in case of version mismatch. +// WebPAnimEncoderOptionsInit() must have succeeded before using the +// 'enc_options' object. +static WEBP_INLINE int WebPAnimEncoderOptionsInit( + WebPAnimEncoderOptions* enc_options) { + return WebPAnimEncoderOptionsInitInternal(enc_options, WEBP_MUX_ABI_VERSION); +} + +// Internal, version-checked, entry point. +WEBP_EXTERN WebPAnimEncoder* WebPAnimEncoderNewInternal( + int, int, const WebPAnimEncoderOptions*, int); + +// Creates and initializes a WebPAnimEncoder object. +// Parameters: +// width/height - (in) canvas width and height of the animation. +// enc_options - (in) encoding options; can be passed NULL to pick +// reasonable defaults. +// Returns: +// A pointer to the newly created WebPAnimEncoder object. +// Or NULL in case of memory error. +static WEBP_INLINE WebPAnimEncoder* WebPAnimEncoderNew( + int width, int height, const WebPAnimEncoderOptions* enc_options) { + return WebPAnimEncoderNewInternal(width, height, enc_options, + WEBP_MUX_ABI_VERSION); +} + +// Optimize the given frame for WebP, encode it and add it to the +// WebPAnimEncoder object. +// The last call to 'WebPAnimEncoderAdd' should be with frame = NULL, which +// indicates that no more frames are to be added. This call is also used to +// determine the duration of the last frame. +// Parameters: +// enc - (in/out) object to which the frame is to be added. +// frame - (in/out) frame data in ARGB or YUV(A) format. If it is in YUV(A) +// format, it will be converted to ARGB, which incurs a small loss. +// timestamp_ms - (in) timestamp of this frame in milliseconds. +// Duration of a frame would be calculated as +// "timestamp of next frame - timestamp of this frame". +// Hence, timestamps should be in non-decreasing order. +// config - (in) encoding options; can be passed NULL to pick +// reasonable defaults. +// Returns: +// On error, returns false and frame->error_code is set appropriately. +// Otherwise, returns true. +WEBP_EXTERN int WebPAnimEncoderAdd( + WebPAnimEncoder* enc, struct WebPPicture* frame, int timestamp_ms, + const struct WebPConfig* config); + +// Assemble all frames added so far into a WebP bitstream. +// This call should be preceded by a call to 'WebPAnimEncoderAdd' with +// frame = NULL; if not, the duration of the last frame will be internally +// estimated. +// Parameters: +// enc - (in/out) object from which the frames are to be assembled. +// webp_data - (out) generated WebP bitstream. +// Returns: +// True on success. +WEBP_EXTERN int WebPAnimEncoderAssemble(WebPAnimEncoder* enc, + WebPData* webp_data); + +// Get error string corresponding to the most recent call using 'enc'. The +// returned string is owned by 'enc' and is valid only until the next call to +// WebPAnimEncoderAdd() or WebPAnimEncoderAssemble() or WebPAnimEncoderDelete(). +// Parameters: +// enc - (in/out) object from which the error string is to be fetched. +// Returns: +// NULL if 'enc' is NULL. Otherwise, returns the error string if the last call +// to 'enc' had an error, or an empty string if the last call was a success. +WEBP_EXTERN const char* WebPAnimEncoderGetError(WebPAnimEncoder* enc); + +// Deletes the WebPAnimEncoder object. +// Parameters: +// enc - (in/out) object to be deleted +WEBP_EXTERN void WebPAnimEncoderDelete(WebPAnimEncoder* enc); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_WEBP_MUX_H_ diff --git a/third-party/webp/libwebp/src/webp/mux_types.h b/third-party/webp/libwebp/src/webp/mux_types.h new file mode 100644 index 0000000000..2fe8195839 --- /dev/null +++ b/third-party/webp/libwebp/src/webp/mux_types.h @@ -0,0 +1,98 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Data-types common to the mux and demux libraries. +// +// Author: Urvang (urvang@google.com) + +#ifndef WEBP_WEBP_MUX_TYPES_H_ +#define WEBP_WEBP_MUX_TYPES_H_ + +#include // memset() +#include "./types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Note: forward declaring enumerations is not allowed in (strict) C and C++, +// the types are left here for reference. +// typedef enum WebPFeatureFlags WebPFeatureFlags; +// typedef enum WebPMuxAnimDispose WebPMuxAnimDispose; +// typedef enum WebPMuxAnimBlend WebPMuxAnimBlend; +typedef struct WebPData WebPData; + +// VP8X Feature Flags. +typedef enum WebPFeatureFlags { + ANIMATION_FLAG = 0x00000002, + XMP_FLAG = 0x00000004, + EXIF_FLAG = 0x00000008, + ALPHA_FLAG = 0x00000010, + ICCP_FLAG = 0x00000020, + + ALL_VALID_FLAGS = 0x0000003e +} WebPFeatureFlags; + +// Dispose method (animation only). Indicates how the area used by the current +// frame is to be treated before rendering the next frame on the canvas. +typedef enum WebPMuxAnimDispose { + WEBP_MUX_DISPOSE_NONE, // Do not dispose. + WEBP_MUX_DISPOSE_BACKGROUND // Dispose to background color. +} WebPMuxAnimDispose; + +// Blend operation (animation only). Indicates how transparent pixels of the +// current frame are blended with those of the previous canvas. +typedef enum WebPMuxAnimBlend { + WEBP_MUX_BLEND, // Blend. + WEBP_MUX_NO_BLEND // Do not blend. +} WebPMuxAnimBlend; + +// Data type used to describe 'raw' data, e.g., chunk data +// (ICC profile, metadata) and WebP compressed image data. +// 'bytes' memory must be allocated using WebPMalloc() and such. +struct WebPData { + const uint8_t* bytes; + size_t size; +}; + +// Initializes the contents of the 'webp_data' object with default values. +static WEBP_INLINE void WebPDataInit(WebPData* webp_data) { + if (webp_data != NULL) { + memset(webp_data, 0, sizeof(*webp_data)); + } +} + +// Clears the contents of the 'webp_data' object by calling WebPFree(). +// Does not deallocate the object itself. +static WEBP_INLINE void WebPDataClear(WebPData* webp_data) { + if (webp_data != NULL) { + WebPFree((void*)webp_data->bytes); + WebPDataInit(webp_data); + } +} + +// Allocates necessary storage for 'dst' and copies the contents of 'src'. +// Returns true on success. +static WEBP_INLINE int WebPDataCopy(const WebPData* src, WebPData* dst) { + if (src == NULL || dst == NULL) return 0; + WebPDataInit(dst); + if (src->bytes != NULL && src->size != 0) { + dst->bytes = (uint8_t*)WebPMalloc(src->size); + if (dst->bytes == NULL) return 0; + memcpy((void*)dst->bytes, src->bytes, src->size); + dst->size = src->size; + } + return 1; +} + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_WEBP_MUX_TYPES_H_ diff --git a/third-party/webp/libwebp/src/webp/types.h b/third-party/webp/libwebp/src/webp/types.h new file mode 100644 index 0000000000..f255432e41 --- /dev/null +++ b/third-party/webp/libwebp/src/webp/types.h @@ -0,0 +1,72 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Common types + memory wrappers +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_WEBP_TYPES_H_ +#define WEBP_WEBP_TYPES_H_ + +#include // for size_t + +#ifndef _MSC_VER +#include +#if defined(__cplusplus) || !defined(__STRICT_ANSI__) || \ + (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) +#define WEBP_INLINE inline +#else +#define WEBP_INLINE +#endif +#else +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed short int16_t; +typedef unsigned short uint16_t; +typedef signed int int32_t; +typedef unsigned int uint32_t; +typedef unsigned long long int uint64_t; +typedef long long int int64_t; +#define WEBP_INLINE __forceinline +#endif /* _MSC_VER */ + +#ifndef WEBP_EXTERN +// This explicitly marks library functions and allows for changing the +// signature for e.g., Windows DLL builds. +# if defined(__GNUC__) && __GNUC__ >= 4 +# define WEBP_EXTERN extern __attribute__ ((visibility ("default"))) +# else +# if defined(_MSC_VER) && defined(WEBP_DLL) +# define WEBP_EXTERN __declspec(dllexport) +# else +# define WEBP_EXTERN extern +# endif +# endif /* __GNUC__ >= 4 */ +#endif /* WEBP_EXTERN */ + +// Macro to check ABI compatibility (same major revision number) +#define WEBP_ABI_IS_INCOMPATIBLE(a, b) (((a) >> 8) != ((b) >> 8)) + +#ifdef __cplusplus +extern "C" { +#endif + +// Allocates 'size' bytes of memory. Returns NULL upon error. Memory +// must be deallocated by calling WebPFree(). This function is made available +// by the core 'libwebp' library. +WEBP_EXTERN void* WebPMalloc(size_t size); + +// Releases memory returned by the WebPDecode*() functions (from decode.h). +WEBP_EXTERN void WebPFree(void* ptr); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_WEBP_TYPES_H_ diff --git a/third-party/webp/libwebp/swig/README.md b/third-party/webp/libwebp/swig/README.md new file mode 100644 index 0000000000..7fa1c388e2 --- /dev/null +++ b/third-party/webp/libwebp/swig/README.md @@ -0,0 +1,67 @@ +# SWIG bindings + +## Building + +### JNI SWIG bindings + +```shell + $ gcc -shared -fPIC -fno-strict-aliasing -O2 \ + -I/path/to/your/jdk/includes \ + libwebp_java_wrap.c \ + -lwebp \ + -o libwebp_jni.so +``` + +Example usage: + +```java +import com.google.webp.libwebp; + +import java.lang.reflect.Method; + +public class libwebp_jni_example { + static { + System.loadLibrary("webp_jni"); + } + + /** + * usage: java -cp libwebp.jar:. libwebp_jni_example + */ + public static void main(String argv[]) { + final int version = libwebp.WebPGetDecoderVersion(); + System.out.println("libwebp version: " + Integer.toHexString(version)); + + System.out.println("libwebp methods:"); + final Method[] libwebpMethods = libwebp.class.getDeclaredMethods(); + for (int i = 0; i < libwebpMethods.length; i++) { + System.out.println(libwebpMethods[i]); + } + } +} +``` + +```shell + $ javac -cp libwebp.jar libwebp_jni_example.java + $ java -Djava.library.path=. -cp libwebp.jar:. libwebp_jni_example +``` + +### Python SWIG bindings: + +```shell + $ python setup.py build_ext + $ python setup.py install --prefix=pylocal +``` + +Example usage: + +```python +import glob +import sys +sys.path.append(glob.glob('pylocal/lib/python*/site-packages')[0]) + +from com.google.webp import libwebp +print "libwebp decoder version: %x" % libwebp.WebPGetDecoderVersion() + +print "libwebp attributes:" +for attr in dir(libwebp): print attr +``` diff --git a/third-party/webp/libwebp/swig/libwebp.go b/third-party/webp/libwebp/swig/libwebp.go new file mode 100644 index 0000000000..df205aa383 --- /dev/null +++ b/third-party/webp/libwebp/swig/libwebp.go @@ -0,0 +1,45 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.10 + * + * This file is not intended to be easily readable and contains a number of + * coding conventions designed to improve portability and efficiency. Do not make + * changes to this file unless you know what you are doing--modify the SWIG + * interface file instead. + * ----------------------------------------------------------------------------- */ + +package libwebp + +import _ "runtime/cgo" +import "unsafe" + +type _ unsafe.Pointer + +type _swig_fnptr *byte +type _swig_memberptr *byte + +//extern libwebpSwigCgocall +func SwigCgocall() + +//extern libwebpSwigCgocallDone +func SwigCgocallDone() + +//extern libwebpSwigCgocallBack +func SwigCgocallBack() + +//extern libwebpSwigCgocallBackDone +func SwigCgocallBackDone() + +func WebPGetDecoderVersion() int +func Wrapped_WebPGetInfo(string, []int, []int) int + +// WebPGetInfo has 2 output parameters, provide a version in the more natural +// go idiom: +func WebPGetInfo(webp []byte) (ok bool, width int, height int) { + w := []int{0} + h := []int{0} + ok = Wrapped_WebPGetInfo(string(webp), w, h) != 0 + width = w[0] + height = h[0] + return +} diff --git a/third-party/webp/libwebp/swig/libwebp.jar b/third-party/webp/libwebp/swig/libwebp.jar new file mode 100644 index 0000000000000000000000000000000000000000..2fc502b972101270fc1ecfb8c8c3948e0a2e45a6 GIT binary patch literal 2150 zcmWIWW@Zs#-~ht6J>Jd?NPv@pg~8V~#8KDN&rSc|DFy~+h5&DN4v-2asImZ@nni#r z;F^6M{XE@VgG2Ou-9G!CIql=Et9OytTUYDcne&^246YbIcv__A<*VcAd$DvC3+IfN zl1FCG(8^$${!H^nnwt1i@o=%}OP+~oS3FaFo%yNgV-X|RA=Rs{zjp^(1HvGOaDg3# z?h6*6XmWn8K5iAw=3j)2gl?f9X11+|u_l z`wM4N+w+?iSC%x+{dsWS=l^q`&)MAm_w)DX`3#S5OuyJWqes*xeT`9^!J{72V^)t< zlba_dR9a^ zdv^8CCaLu@saGDQSxsIpc7EHe$o^GNT}{0^lY(@o6-7B-&zPdN*gULadEnHAAt|b& z-bZ(wJ{lXEtt_?hMP+)|yF1gX4o{alRQ1o^Ug+))kp;g$96d9QYkK;%vM3+<_r>X3 z-Q~~vUQG^}V|V%&%aJK@i~p{Y+IK5T_q}LT_|_oJ_0znro{XPzdG*ZJudD1nPdxN& z@72g1Ev2Wb5|exL3RU$I_vRG_%1!=ivHI|<#bq5N!d=Z``kAntGT<;$4Yf?yV5lreaI%Z+i$IhiD zF}X+cn6pig!Pyy!XN;-}-JR0Ithr<}ZaK#B7M`6D812Lz&j0jsYx9MuX8~uYy)>NF z68^|g>a4py%L2x@ABEgPRbO`Bp0HEs@3$c7wXHY&%jQ7RM9foX$O+0yDOgA7lHd)k7SkqY*HaVkrqG{y$AeZb(YgSfG^WL)T zZfJRV>)f=9oRf`%Z)Xb5RV_-(wqCnPc(J;byYU*U<}K_s46~TSUYl?Ex$E!TF9o+< zH61V2$i8gTcsudSlD;Q`OHDleUwg%Z7=uMha5y&-+x&BRNjTv<*4Yc4V~G^K_MQT zj?HZ1u`{;yEm^W<32UWZxSC!KgZ!zAbSpvbM6u6j?-akAGkeQ@`}y$<1&r!KE)O+0 zk9%eac*I2YneJ8+$eqW>d1T#PaW94In`Lgz_vd+K`>L&X>L+2-ch)6k&b}oT&aZw> zd;P&|s)N^xRi9r8O_&w6diBa#r7VdmET(~g#i9xmMalVP>qyuhgZ&}*w5Yf6{iDz3f1Y@a;O{+`E~ zv(MOU-S$&8b+eR@qV102^GkBOYgf<7mE_Ly*38&%$M#`#R-$~kBz zrmf)EWy~viZcT!pfqsO5PS-x6HwDvJ%UQp(d|!AdQgjWcoWUcJ(mTopKe$14O2XQg zfdz~V3?G3NOMo{clL!N9{K4uQP?dxV;B^eBfMTnxBt z5`+oIfJ{ief?EfuW|W5meJ4fFLkrkTgQ;9n?@lPXC~q2LbG{=tilB n&_fM5G87Qz09luTp^xqms8R6j6X4Ct2GYb1g!_S3PXzM-9zhES literal 0 HcmV?d00001 diff --git a/third-party/webp/libwebp/swig/libwebp.py b/third-party/webp/libwebp/swig/libwebp.py new file mode 100644 index 0000000000..2d126b5dcc --- /dev/null +++ b/third-party/webp/libwebp/swig/libwebp.py @@ -0,0 +1,235 @@ +# This file was automatically generated by SWIG (http://www.swig.org). +# Version 3.0.12 +# +# Do not make changes to this file unless you know what you are doing--modify +# the SWIG interface file instead. + +from sys import version_info as _swig_python_version_info +if _swig_python_version_info >= (2, 7, 0): + def swig_import_helper(): + import importlib + pkg = __name__.rpartition('.')[0] + mname = '.'.join((pkg, '_libwebp')).lstrip('.') + try: + return importlib.import_module(mname) + except ImportError: + return importlib.import_module('_libwebp') + _libwebp = swig_import_helper() + del swig_import_helper +elif _swig_python_version_info >= (2, 6, 0): + def swig_import_helper(): + from os.path import dirname + import imp + fp = None + try: + fp, pathname, description = imp.find_module('_libwebp', [dirname(__file__)]) + except ImportError: + import _libwebp + return _libwebp + try: + _mod = imp.load_module('_libwebp', fp, pathname, description) + finally: + if fp is not None: + fp.close() + return _mod + _libwebp = swig_import_helper() + del swig_import_helper +else: + import _libwebp +del _swig_python_version_info + +try: + _swig_property = property +except NameError: + pass # Python < 2.2 doesn't have 'property'. + +try: + import builtins as __builtin__ +except ImportError: + import __builtin__ + +def _swig_setattr_nondynamic(self, class_type, name, value, static=1): + if (name == "thisown"): + return self.this.own(value) + if (name == "this"): + if type(value).__name__ == 'SwigPyObject': + self.__dict__[name] = value + return + method = class_type.__swig_setmethods__.get(name, None) + if method: + return method(self, value) + if (not static): + if _newclass: + object.__setattr__(self, name, value) + else: + self.__dict__[name] = value + else: + raise AttributeError("You cannot add attributes to %s" % self) + + +def _swig_setattr(self, class_type, name, value): + return _swig_setattr_nondynamic(self, class_type, name, value, 0) + + +def _swig_getattr(self, class_type, name): + if (name == "thisown"): + return self.this.own() + method = class_type.__swig_getmethods__.get(name, None) + if method: + return method(self) + raise AttributeError("'%s' object has no attribute '%s'" % (class_type.__name__, name)) + + +def _swig_repr(self): + try: + strthis = "proxy of " + self.this.__repr__() + except __builtin__.Exception: + strthis = "" + return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,) + +try: + _object = object + _newclass = 1 +except __builtin__.Exception: + class _object: + pass + _newclass = 0 + + +def WebPGetDecoderVersion(): + """WebPGetDecoderVersion() -> int""" + return _libwebp.WebPGetDecoderVersion() + +def WebPGetInfo(data): + """WebPGetInfo(uint8_t data) -> (width, height)""" + return _libwebp.WebPGetInfo(data) + +def WebPDecodeRGB(data): + """WebPDecodeRGB(uint8_t data) -> (rgb, width, height)""" + return _libwebp.WebPDecodeRGB(data) + +def WebPDecodeRGBA(data): + """WebPDecodeRGBA(uint8_t data) -> (rgb, width, height)""" + return _libwebp.WebPDecodeRGBA(data) + +def WebPDecodeARGB(data): + """WebPDecodeARGB(uint8_t data) -> (rgb, width, height)""" + return _libwebp.WebPDecodeARGB(data) + +def WebPDecodeBGR(data): + """WebPDecodeBGR(uint8_t data) -> (rgb, width, height)""" + return _libwebp.WebPDecodeBGR(data) + +def WebPDecodeBGRA(data): + """WebPDecodeBGRA(uint8_t data) -> (rgb, width, height)""" + return _libwebp.WebPDecodeBGRA(data) + +def WebPGetEncoderVersion(): + """WebPGetEncoderVersion() -> int""" + return _libwebp.WebPGetEncoderVersion() + +def wrap_WebPEncodeRGB(rgb, unused1, unused2, width, height, stride, quality_factor): + """private, do not call directly.""" + return _libwebp.wrap_WebPEncodeRGB(rgb, unused1, unused2, width, height, stride, quality_factor) + +def wrap_WebPEncodeBGR(rgb, unused1, unused2, width, height, stride, quality_factor): + """private, do not call directly.""" + return _libwebp.wrap_WebPEncodeBGR(rgb, unused1, unused2, width, height, stride, quality_factor) + +def wrap_WebPEncodeRGBA(rgb, unused1, unused2, width, height, stride, quality_factor): + """private, do not call directly.""" + return _libwebp.wrap_WebPEncodeRGBA(rgb, unused1, unused2, width, height, stride, quality_factor) + +def wrap_WebPEncodeBGRA(rgb, unused1, unused2, width, height, stride, quality_factor): + """private, do not call directly.""" + return _libwebp.wrap_WebPEncodeBGRA(rgb, unused1, unused2, width, height, stride, quality_factor) + +def wrap_WebPEncodeLosslessRGB(rgb, unused1, unused2, width, height, stride): + """private, do not call directly.""" + return _libwebp.wrap_WebPEncodeLosslessRGB(rgb, unused1, unused2, width, height, stride) + +def wrap_WebPEncodeLosslessBGR(rgb, unused1, unused2, width, height, stride): + """private, do not call directly.""" + return _libwebp.wrap_WebPEncodeLosslessBGR(rgb, unused1, unused2, width, height, stride) + +def wrap_WebPEncodeLosslessRGBA(rgb, unused1, unused2, width, height, stride): + """private, do not call directly.""" + return _libwebp.wrap_WebPEncodeLosslessRGBA(rgb, unused1, unused2, width, height, stride) + +def wrap_WebPEncodeLosslessBGRA(rgb, unused1, unused2, width, height, stride): + """private, do not call directly.""" + return _libwebp.wrap_WebPEncodeLosslessBGRA(rgb, unused1, unused2, width, height, stride) + +_UNUSED = 1 + + +def WebPEncodeRGB(rgb, width, height, stride, quality_factor): + """WebPEncodeRGB(uint8_t rgb, int width, int height, int stride, float quality_factor) -> lossy_webp""" + webp = wrap_WebPEncodeRGB( + rgb, _UNUSED, _UNUSED, width, height, stride, quality_factor) + if len(webp[0]) == 0: + return None + return webp[0] + + +def WebPEncodeRGBA(rgb, width, height, stride, quality_factor): + """WebPEncodeRGBA(uint8_t rgb, int width, int height, int stride, float quality_factor) -> lossy_webp""" + webp = wrap_WebPEncodeRGBA( + rgb, _UNUSED, _UNUSED, width, height, stride, quality_factor) + if len(webp[0]) == 0: + return None + return webp[0] + + +def WebPEncodeBGR(rgb, width, height, stride, quality_factor): + """WebPEncodeBGR(uint8_t rgb, int width, int height, int stride, float quality_factor) -> lossy_webp""" + webp = wrap_WebPEncodeBGR( + rgb, _UNUSED, _UNUSED, width, height, stride, quality_factor) + if len(webp[0]) == 0: + return None + return webp[0] + + +def WebPEncodeBGRA(rgb, width, height, stride, quality_factor): + """WebPEncodeBGRA(uint8_t rgb, int width, int height, int stride, float quality_factor) -> lossy_webp""" + webp = wrap_WebPEncodeBGRA( + rgb, _UNUSED, _UNUSED, width, height, stride, quality_factor) + if len(webp[0]) == 0: + return None + return webp[0] + + +def WebPEncodeLosslessRGB(rgb, width, height, stride): + """WebPEncodeLosslessRGB(uint8_t rgb, int width, int height, int stride) -> lossless_webp""" + webp = wrap_WebPEncodeLosslessRGB(rgb, _UNUSED, _UNUSED, width, height, stride) + if len(webp[0]) == 0: + return None + return webp[0] + + +def WebPEncodeLosslessRGBA(rgb, width, height, stride): + """WebPEncodeLosslessRGBA(uint8_t rgb, int width, int height, int stride) -> lossless_webp""" + webp = wrap_WebPEncodeLosslessRGBA(rgb, _UNUSED, _UNUSED, width, height, stride) + if len(webp[0]) == 0: + return None + return webp[0] + + +def WebPEncodeLosslessBGR(rgb, width, height, stride): + """WebPEncodeLosslessBGR(uint8_t rgb, int width, int height, int stride) -> lossless_webp""" + webp = wrap_WebPEncodeLosslessBGR(rgb, _UNUSED, _UNUSED, width, height, stride) + if len(webp[0]) == 0: + return None + return webp[0] + + +def WebPEncodeLosslessBGRA(rgb, width, height, stride): + """WebPEncodeLosslessBGRA(uint8_t rgb, int width, int height, int stride) -> lossless_webp""" + webp = wrap_WebPEncodeLosslessBGRA(rgb, _UNUSED, _UNUSED, width, height, stride) + if len(webp[0]) == 0: + return None + return webp[0] + +# This file is compatible with both classic and new-style classes. + + diff --git a/third-party/webp/libwebp/swig/libwebp.swig b/third-party/webp/libwebp/swig/libwebp.swig new file mode 100644 index 0000000000..ca38298197 --- /dev/null +++ b/third-party/webp/libwebp/swig/libwebp.swig @@ -0,0 +1,438 @@ +// Copyright 2011 Google Inc. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// libwebp swig interface definition +// +// Author: James Zern (jzern@google.com) + +/* + Go bindings: + $ swig -go \ + -outdir . \ + -o libwebp_go_wrap.c libwebp.swig + + Java bindings: + $ mkdir -p java/com/google/webp + $ swig -java \ + -package com.google.webp \ + -outdir java/com/google/webp \ + -o libwebp_java_wrap.c libwebp.swig + + Python bindings: + $ swig -python \ + -outdir . \ + -o libwebp_python_wrap.c libwebp.swig +*/ + +#ifdef SWIGPYTHON +%module(package="com.google.webp") libwebp +%begin %{ +#define SWIG_PYTHON_STRICT_BYTE_CHAR +%} +#else +%module libwebp +#endif /* SWIGPYTHON */ + +%include "constraints.i" +%include "typemaps.i" + +#ifdef SWIGGO +%apply (char* STRING, size_t LENGTH) { (const uint8_t* data, size_t data_size) } + +%rename(wrapped_WebPGetInfo) WebPGetInfo(const uint8_t* data, size_t data_size, + int* width, int* height); +#endif /* SWIGGO */ + +#ifdef SWIGJAVA +%include "arrays_java.i"; +%include "enums.swg" /*NB: requires JDK-1.5+ + See: http://www.swig.org/Doc1.3/Java.html#enumerations */ + +// map uint8_t* such that a byte[] is used +%{ +#include "webp/types.h" +%} +// from arrays_java.i (signed char) +JAVA_ARRAYS_DECL(uint8_t, jbyte, Byte, Uint8) +JAVA_ARRAYS_IMPL(uint8_t, jbyte, Byte, Uint8) +JAVA_ARRAYS_TYPEMAPS(uint8_t, byte, jbyte, Uint8, "[B") +%apply uint8_t[] { uint8_t* } +#endif /* SWIGJAVA */ + +#ifdef SWIGPYTHON +%apply (char* STRING, size_t LENGTH) { (const uint8_t* data, size_t data_size) } +%typemap(out) uint8_t* { + $result = PyString_FromStringAndSize( + (const char*)$1, + ($1 == NULL) ? 0 : ReturnedBufferSize("$symname", arg3, arg4)); +} + +%typemap (in) const uint8_t* rgb (Py_buffer rgb_buffer) { + // NB: with Python < 2.6 the old style buffer protocol may be used: + // Py_ssize_t unused; + // PyObject_AsReadBuffer($input, (const void**)(&$1), &unused); + if (!PyObject_CheckBuffer($input)) { + SWIG_exception_fail(SWIG_TypeError, + "in method '$symname', argument $argnum" + " does not support the buffer interface"); + } + if (PyObject_GetBuffer($input, &rgb_buffer, PyBUF_SIMPLE)) { + SWIG_exception_fail(SWIG_RuntimeError, + "in method '$symname', unable to get buffer view"); + } + $1 = ($1_ltype)rgb_buffer.buf; +} + +%typemap(freearg) const uint8_t* rgb { + PyBuffer_Release(&rgb_buffer$argnum); +} + +%define DECODE_AUTODOC(func) +%feature("autodoc", #func "(uint8_t data) -> (rgb, width, height)") func; +%enddef + +%feature("autodoc", "1"); +DECODE_AUTODOC(WebPDecodeRGB); +DECODE_AUTODOC(WebPDecodeRGBA); +DECODE_AUTODOC(WebPDecodeARGB); +DECODE_AUTODOC(WebPDecodeBGR); +DECODE_AUTODOC(WebPDecodeBGRA); +%feature("autodoc", "WebPGetInfo(uint8_t data) -> (width, height)") WebPGetInfo; +#endif /* SWIGPYTHON */ + +//------------------------------------------------------------------------------ +// Decoder specific + +%apply int* OUTPUT { int* width, int* height } + +int WebPGetDecoderVersion(void); +int WebPGetInfo(const uint8_t* data, size_t data_size, + int* width, int* height); + +#if defined(SWIGJAVA) || defined(SWIGPYTHON) + +// free the buffer returned by these functions after copying into +// the native type +%newobject WebPDecodeRGB; +%newobject WebPDecodeRGBA; +%newobject WebPDecodeARGB; +%newobject WebPDecodeBGR; +%newobject WebPDecodeBGRA; +%typemap(newfree) uint8_t* "free($1);" + +uint8_t* WebPDecodeRGB(const uint8_t* data, size_t data_size, + int* width, int* height); +uint8_t* WebPDecodeRGBA(const uint8_t* data, size_t data_size, + int* width, int* height); +uint8_t* WebPDecodeARGB(const uint8_t* data, size_t data_size, + int* width, int* height); +uint8_t* WebPDecodeBGR(const uint8_t* data, size_t data_size, + int* width, int* height); +uint8_t* WebPDecodeBGRA(const uint8_t* data, size_t data_size, + int* width, int* height); + +#endif /* SWIGJAVA || SWIGPYTHON */ + +//------------------------------------------------------------------------------ +// Encoder specific + +#if defined(SWIGJAVA) || defined(SWIGPYTHON) + +int WebPGetEncoderVersion(void); + +#endif /* SWIGJAVA || SWIGPYTHON */ + +//------------------------------------------------------------------------------ +// Wrapper code additions + +%{ +#include "webp/decode.h" +#include "webp/encode.h" +%} + +#ifdef SWIGJAVA +%{ +#define FillMeInAsSizeCannotBeDeterminedAutomatically \ + (result ? (jint)ReturnedBufferSize(__FUNCTION__, arg3, arg4) : 0) +%} +#endif /* SWIGJAVA */ + +#if defined(SWIGJAVA) || defined(SWIGPYTHON) +%{ +static size_t ReturnedBufferSize( + const char* function, int* width, int* height) { + static const struct sizemap { + const char* function; + int size_multiplier; + } size_map[] = { +#ifdef SWIGJAVA + { "Java_com_google_webp_libwebpJNI_WebPDecodeRGB", 3 }, + { "Java_com_google_webp_libwebpJNI_WebPDecodeRGBA", 4 }, + { "Java_com_google_webp_libwebpJNI_WebPDecodeARGB", 4 }, + { "Java_com_google_webp_libwebpJNI_WebPDecodeBGR", 3 }, + { "Java_com_google_webp_libwebpJNI_WebPDecodeBGRA", 4 }, + { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeRGB", 1 }, + { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeBGR", 1 }, + { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeRGBA", 1 }, + { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeBGRA", 1 }, + { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessRGB", 1 }, + { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessBGR", 1 }, + { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessRGBA", 1 }, + { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessBGRA", 1 }, +#endif +#ifdef SWIGPYTHON + { "WebPDecodeRGB", 3 }, + { "WebPDecodeRGBA", 4 }, + { "WebPDecodeARGB", 4 }, + { "WebPDecodeBGR", 3 }, + { "WebPDecodeBGRA", 4 }, + { "wrap_WebPEncodeRGB", 1 }, + { "wrap_WebPEncodeBGR", 1 }, + { "wrap_WebPEncodeRGBA", 1 }, + { "wrap_WebPEncodeBGRA", 1 }, + { "wrap_WebPEncodeLosslessRGB", 1 }, + { "wrap_WebPEncodeLosslessBGR", 1 }, + { "wrap_WebPEncodeLosslessRGBA", 1 }, + { "wrap_WebPEncodeLosslessBGRA", 1 }, +#endif + { NULL, 0 } + }; + const struct sizemap* p; + size_t size = 0; + + for (p = size_map; p->function; ++p) { + if (!strcmp(function, p->function)) { + size = *width * *height * p->size_multiplier; + break; + } + } + + return size; +} +%} + +%{ +typedef size_t (*WebPEncodeFunction)(const uint8_t* rgb, + int width, int height, int stride, + float quality_factor, uint8_t** output); +typedef size_t (*WebPEncodeLosslessFunction)(const uint8_t* rgb, + int width, int height, int stride, + uint8_t** output); + +static uint8_t* EncodeLossy(const uint8_t* rgb, + int width, int height, int stride, + float quality_factor, + WebPEncodeFunction encfn, + int* output_size, int* unused) { + uint8_t* output = NULL; + const size_t image_size = + encfn(rgb, width, height, stride, quality_factor, &output); + // the values of following two will be interpreted by ReturnedBufferSize() + // as 'width' and 'height' in the size calculation. + *output_size = image_size; + *unused = 1; + return image_size ? output : NULL; +} + +static uint8_t* EncodeLossless(const uint8_t* rgb, + int width, int height, int stride, + WebPEncodeLosslessFunction encfn, + int* output_size, int* unused) { + uint8_t* output = NULL; + const size_t image_size = encfn(rgb, width, height, stride, &output); + // the values of the following two will be interpreted by + // ReturnedBufferSize() as 'width' and 'height' in the size calculation. + *output_size = image_size; + *unused = 1; + return image_size ? output : NULL; +} +%} + +#endif /* SWIGJAVA || SWIGPYTHON */ + +//------------------------------------------------------------------------------ +// libwebp/encode wrapper functions + +#if defined(SWIGJAVA) || defined(SWIGPYTHON) + +%apply int* INPUT { int* unused1, int* unused2 } +%apply int* OUTPUT { int* output_size } + +// free the buffer returned by these functions after copying into +// the native type +%newobject wrap_WebPEncodeRGB; +%newobject wrap_WebPEncodeBGR; +%newobject wrap_WebPEncodeRGBA; +%newobject wrap_WebPEncodeBGRA; +%newobject wrap_WebPEncodeLosslessRGB; +%newobject wrap_WebPEncodeLosslessBGR; +%newobject wrap_WebPEncodeLosslessRGBA; +%newobject wrap_WebPEncodeLosslessBGRA; + +#ifdef SWIGJAVA +// There's no reason to call these directly +%javamethodmodifiers wrap_WebPEncodeRGB "private"; +%javamethodmodifiers wrap_WebPEncodeBGR "private"; +%javamethodmodifiers wrap_WebPEncodeRGBA "private"; +%javamethodmodifiers wrap_WebPEncodeBGRA "private"; +%javamethodmodifiers wrap_WebPEncodeLosslessRGB "private"; +%javamethodmodifiers wrap_WebPEncodeLosslessBGR "private"; +%javamethodmodifiers wrap_WebPEncodeLosslessRGBA "private"; +%javamethodmodifiers wrap_WebPEncodeLosslessBGRA "private"; +#endif /* SWIGJAVA */ + +#ifdef SWIGPYTHON +// This autodoc will serve as a catch-all for wrap_*. +%feature("autodoc", "private, do not call directly."); +#endif + +%inline %{ +// Changes the return type of WebPEncode* to more closely match Decode*. +// This also makes it easier to wrap the output buffer in a native type rather +// than dealing with the return pointer. +// The additional parameters are to allow reuse of ReturnedBufferSize(), +// unused2 and output_size will be used in this case. +#define LOSSY_WRAPPER(FUNC) \ + static uint8_t* wrap_##FUNC( \ + const uint8_t* rgb, int* unused1, int* unused2, int* output_size, \ + int width, int height, int stride, float quality_factor) { \ + return EncodeLossy(rgb, width, height, stride, quality_factor, \ + FUNC, output_size, unused2); \ + } \ + +LOSSY_WRAPPER(WebPEncodeRGB) +LOSSY_WRAPPER(WebPEncodeBGR) +LOSSY_WRAPPER(WebPEncodeRGBA) +LOSSY_WRAPPER(WebPEncodeBGRA) + +#undef LOSSY_WRAPPER + +#define LOSSLESS_WRAPPER(FUNC) \ + static uint8_t* wrap_##FUNC( \ + const uint8_t* rgb, int* unused1, int* unused2, int* output_size, \ + int width, int height, int stride) { \ + return EncodeLossless(rgb, width, height, stride, \ + FUNC, output_size, unused2); \ + } \ + +LOSSLESS_WRAPPER(WebPEncodeLosslessRGB) +LOSSLESS_WRAPPER(WebPEncodeLosslessBGR) +LOSSLESS_WRAPPER(WebPEncodeLosslessRGBA) +LOSSLESS_WRAPPER(WebPEncodeLosslessBGRA) + +#undef LOSSLESS_WRAPPER + +%} + +#endif /* SWIGJAVA || SWIGPYTHON */ + +//------------------------------------------------------------------------------ +// Language specific + +#ifdef SWIGGO +%insert(go_wrapper) %{ + +// WebPGetInfo has 2 output parameters, provide a version in the more natural +// go idiom: +func WebPGetInfo(webp []byte) (ok bool, width int, height int) { + w := []int{0} + h := []int{0} + ok = Wrapped_WebPGetInfo(string(webp), w, h) != 0 + width = w[0] + height = h[0] + return +} + +%} +#endif /* SWIGGO */ + +#ifdef SWIGJAVA +%{ +/* Work around broken gcj jni.h */ +#ifdef __GCJ_JNI_H__ +# undef JNIEXPORT +# define JNIEXPORT +# undef JNICALL +# define JNICALL +#endif +%} + +%pragma(java) modulecode=%{ + private static final int UNUSED = 1; + private static int outputSize[] = { 0 }; +%} + + +%define CALL_ENCODE_LOSSY_WRAPPER(func) +%pragma(java) modulecode=%{ + public static byte[] func( + byte[] rgb, int width, int height, int stride, float quality_factor) { + return wrap_##func( + rgb, UNUSED, UNUSED, outputSize, width, height, stride, quality_factor); + } +%} +%enddef + +%define CALL_ENCODE_LOSSLESS_WRAPPER(func) +%pragma(java) modulecode=%{ + public static byte[] func( + byte[] rgb, int width, int height, int stride) { + return wrap_##func( + rgb, UNUSED, UNUSED, outputSize, width, height, stride); + } +%} +%enddef + +CALL_ENCODE_LOSSY_WRAPPER(WebPEncodeRGB) +CALL_ENCODE_LOSSY_WRAPPER(WebPEncodeRGBA) +CALL_ENCODE_LOSSY_WRAPPER(WebPEncodeBGR) +CALL_ENCODE_LOSSY_WRAPPER(WebPEncodeBGRA) +CALL_ENCODE_LOSSLESS_WRAPPER(WebPEncodeLosslessRGB) +CALL_ENCODE_LOSSLESS_WRAPPER(WebPEncodeLosslessRGBA) +CALL_ENCODE_LOSSLESS_WRAPPER(WebPEncodeLosslessBGR) +CALL_ENCODE_LOSSLESS_WRAPPER(WebPEncodeLosslessBGRA) +#endif /* SWIGJAVA */ + +#ifdef SWIGPYTHON +%pythoncode %{ +_UNUSED = 1 +%} + +%define CALL_ENCODE_LOSSY_WRAPPER(func) +%pythoncode %{ +def func(rgb, width, height, stride, quality_factor): + """func(uint8_t rgb, int width, int height, int stride, float quality_factor) -> lossy_webp""" + webp = wrap_##func( + rgb, _UNUSED, _UNUSED, width, height, stride, quality_factor) + if len(webp[0]) == 0: + return None + return webp[0] +%} +%enddef + +%define CALL_ENCODE_LOSSLESS_WRAPPER(func) +%pythoncode %{ +def func(rgb, width, height, stride): + """func(uint8_t rgb, int width, int height, int stride) -> lossless_webp""" + webp = wrap_##func(rgb, _UNUSED, _UNUSED, width, height, stride) + if len(webp[0]) == 0: + return None + return webp[0] +%} +%enddef + +CALL_ENCODE_LOSSY_WRAPPER(WebPEncodeRGB) +CALL_ENCODE_LOSSY_WRAPPER(WebPEncodeRGBA) +CALL_ENCODE_LOSSY_WRAPPER(WebPEncodeBGR) +CALL_ENCODE_LOSSY_WRAPPER(WebPEncodeBGRA) +CALL_ENCODE_LOSSLESS_WRAPPER(WebPEncodeLosslessRGB) +CALL_ENCODE_LOSSLESS_WRAPPER(WebPEncodeLosslessRGBA) +CALL_ENCODE_LOSSLESS_WRAPPER(WebPEncodeLosslessBGR) +CALL_ENCODE_LOSSLESS_WRAPPER(WebPEncodeLosslessBGRA) +#endif /* SWIGPYTHON */ diff --git a/third-party/webp/libwebp/swig/libwebp_gc.c b/third-party/webp/libwebp/swig/libwebp_gc.c new file mode 100644 index 0000000000..308b7f835f --- /dev/null +++ b/third-party/webp/libwebp/swig/libwebp_gc.c @@ -0,0 +1,52 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.10 + * + * This file is not intended to be easily readable and contains a number of + * coding conventions designed to improve portability and efficiency. Do not make + * changes to this file unless you know what you are doing--modify the SWIG + * interface file instead. + * ----------------------------------------------------------------------------- */ + +/* This file should be compiled with 6c/8c. */ +#pragma dynimport _ _ "libwebp_go.so" + +#include "runtime.h" +#include "cgocall.h" + +#ifdef _64BIT +#define SWIG_PARM_SIZE 8 +#else +#define SWIG_PARM_SIZE 4 +#endif + +#pragma dynimport _wrap_WebPGetDecoderVersion _wrap_WebPGetDecoderVersion "" +extern void (*_wrap_WebPGetDecoderVersion)(void*); +static void (*x_wrap_WebPGetDecoderVersion)(void*) = _wrap_WebPGetDecoderVersion; + +void +·WebPGetDecoderVersion(struct { + uint8 x[SWIG_PARM_SIZE]; +} p) + +{ + runtime·cgocall(x_wrap_WebPGetDecoderVersion, &p); +} + + + +#pragma dynimport _wrap_wrapped_WebPGetInfo _wrap_wrapped_WebPGetInfo "" +extern void (*_wrap_wrapped_WebPGetInfo)(void*); +static void (*x_wrap_wrapped_WebPGetInfo)(void*) = _wrap_wrapped_WebPGetInfo; + +void +·Wrapped_WebPGetInfo(struct { + uint8 x[(2 * SWIG_PARM_SIZE) + (3 * SWIG_PARM_SIZE) + (3 * SWIG_PARM_SIZE) + SWIG_PARM_SIZE]; +} p) + +{ + runtime·cgocall(x_wrap_wrapped_WebPGetInfo, &p); +} + + + diff --git a/third-party/webp/libwebp/swig/libwebp_go_wrap.c b/third-party/webp/libwebp/swig/libwebp_go_wrap.c new file mode 100644 index 0000000000..351d523f26 --- /dev/null +++ b/third-party/webp/libwebp/swig/libwebp_go_wrap.c @@ -0,0 +1,274 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.10 + * + * This file is not intended to be easily readable and contains a number of + * coding conventions designed to improve portability and efficiency. Do not make + * changes to this file unless you know what you are doing--modify the SWIG + * interface file instead. + * ----------------------------------------------------------------------------- */ +#define SWIGMODULE libwebp +/* ----------------------------------------------------------------------------- + * This section contains generic SWIG labels for method/variable + * declarations/attributes, and other compiler dependent labels. + * ----------------------------------------------------------------------------- */ + +/* template workaround for compilers that cannot correctly implement the C++ standard */ +#ifndef SWIGTEMPLATEDISAMBIGUATOR +# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560) +# define SWIGTEMPLATEDISAMBIGUATOR template +# elif defined(__HP_aCC) +/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */ +/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */ +# define SWIGTEMPLATEDISAMBIGUATOR template +# else +# define SWIGTEMPLATEDISAMBIGUATOR +# endif +#endif + +/* inline attribute */ +#ifndef SWIGINLINE +# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__)) +# define SWIGINLINE inline +# else +# define SWIGINLINE +# endif +#endif + +/* attribute recognised by some compilers to avoid 'unused' warnings */ +#ifndef SWIGUNUSED +# if defined(__GNUC__) +# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +# elif defined(__ICC) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +#endif + +#ifndef SWIG_MSC_UNSUPPRESS_4505 +# if defined(_MSC_VER) +# pragma warning(disable : 4505) /* unreferenced local function has been removed */ +# endif +#endif + +#ifndef SWIGUNUSEDPARM +# ifdef __cplusplus +# define SWIGUNUSEDPARM(p) +# else +# define SWIGUNUSEDPARM(p) p SWIGUNUSED +# endif +#endif + +/* internal SWIG method */ +#ifndef SWIGINTERN +# define SWIGINTERN static SWIGUNUSED +#endif + +/* internal inline SWIG method */ +#ifndef SWIGINTERNINLINE +# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE +#endif + +/* exporting methods */ +#if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +# ifndef GCC_HASCLASSVISIBILITY +# define GCC_HASCLASSVISIBILITY +# endif +#endif + +#ifndef SWIGEXPORT +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# if defined(STATIC_LINKED) +# define SWIGEXPORT +# else +# define SWIGEXPORT __declspec(dllexport) +# endif +# else +# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY) +# define SWIGEXPORT __attribute__ ((visibility("default"))) +# else +# define SWIGEXPORT +# endif +# endif +#endif + +/* calling conventions for Windows */ +#ifndef SWIGSTDCALL +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# define SWIGSTDCALL __stdcall +# else +# define SWIGSTDCALL +# endif +#endif + +/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ +#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +# define _CRT_SECURE_NO_DEPRECATE +#endif + +/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */ +#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE) +# define _SCL_SECURE_NO_DEPRECATE +#endif + + + +#include +#include +#include +#include +#include + + + +typedef long long intgo; +typedef unsigned long long uintgo; + + + +typedef struct { char *p; intgo n; } _gostring_; +typedef struct { void* array; intgo len; intgo cap; } _goslice_; + + + + +#define swiggo_size_assert_eq(x, y, name) typedef char name[(x-y)*(x-y)*-2+1]; +#define swiggo_size_assert(t, n) swiggo_size_assert_eq(sizeof(t), n, swiggo_sizeof_##t##_is_not_##n) + +swiggo_size_assert(char, 1) +swiggo_size_assert(short, 2) +swiggo_size_assert(int, 4) +typedef long long swiggo_long_long; +swiggo_size_assert(swiggo_long_long, 8) +swiggo_size_assert(float, 4) +swiggo_size_assert(double, 8) + +#ifdef __cplusplus +extern "C" { +#endif +extern void crosscall2(void (*fn)(void *, int), void *, int); +extern void _cgo_allocate(void *, int); +extern void _cgo_panic(void *, int); +#ifdef __cplusplus +} +#endif + +static void *_swig_goallocate(size_t len) { + struct { + size_t len; + void *ret; + } a; + a.len = len; + crosscall2(_cgo_allocate, &a, (int) sizeof a); + return a.ret; +} + +static void _swig_gopanic(const char *p) { + struct { + const char *p; + } a; + a.p = p; + crosscall2(_cgo_panic, &a, (int) sizeof a); +} + + + + +static _gostring_ _swig_makegostring(const char *p, size_t l) { + _gostring_ ret; + ret.p = (char*)_swig_goallocate(l + 1); + memcpy(ret.p, p, l); + ret.n = l; + return ret; +} + +#define SWIG_contract_assert(expr, msg) \ + if (!(expr)) { _swig_gopanic(msg); } else + + +#define SWIG_exception(code, msg) _swig_gopanic(msg) + + +#include "webp/decode.h" +#include "webp/encode.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void +_wrap_WebPGetDecoderVersion(void *swig_v) +{ + int result; + + struct swigargs { + long : 0; + intgo result; + } *swig_a = (struct swigargs *) swig_v; + + + result = (int)WebPGetDecoderVersion(); + swig_a->result = result; +} + + +void +_wrap_wrapped_WebPGetInfo(void *swig_v) +{ + uint8_t *arg1 = (uint8_t *) 0 ; + size_t arg2 ; + int *arg3 = (int *) 0 ; + int *arg4 = (int *) 0 ; + int temp3 ; + int temp4 ; + int result; + + struct swigargs { + _gostring_ arg1; + _goslice_ arg3; + _goslice_ arg4; + long : 0; + intgo result; + } *swig_a = (struct swigargs *) swig_v; + + + arg1 = (uint8_t *)swig_a->arg1.p; + arg2 = (size_t)swig_a->arg1.n; + + { + if (swig_a->arg3.len == 0) { + _swig_gopanic("array must contain at least 1 element"); + } + arg3 = &temp3; + } + { + if (swig_a->arg4.len == 0) { + _swig_gopanic("array must contain at least 1 element"); + } + arg4 = &temp4; + } + + result = (int)WebPGetInfo((uint8_t const *)arg1,arg2,arg3,arg4); + swig_a->result = result; + { + int* a = (int *) swig_a->arg3.array; + a[0] = temp3; + } + { + int* a = (int *) swig_a->arg4.array; + a[0] = temp4; + } + + +} + + +#ifdef __cplusplus +} +#endif + diff --git a/third-party/webp/libwebp/swig/libwebp_java_wrap.c b/third-party/webp/libwebp/swig/libwebp_java_wrap.c new file mode 100644 index 0000000000..c8d4b13312 --- /dev/null +++ b/third-party/webp/libwebp/swig/libwebp_java_wrap.c @@ -0,0 +1,1765 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.4 + * + * This file is not intended to be easily readable and contains a number of + * coding conventions designed to improve portability and efficiency. Do not make + * changes to this file unless you know what you are doing--modify the SWIG + * interface file instead. + * ----------------------------------------------------------------------------- */ + +#define SWIGJAVA + +/* ----------------------------------------------------------------------------- + * This section contains generic SWIG labels for method/variable + * declarations/attributes, and other compiler dependent labels. + * ----------------------------------------------------------------------------- */ + +/* template workaround for compilers that cannot correctly implement the C++ standard */ +#ifndef SWIGTEMPLATEDISAMBIGUATOR +# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560) +# define SWIGTEMPLATEDISAMBIGUATOR template +# elif defined(__HP_aCC) +/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */ +/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */ +# define SWIGTEMPLATEDISAMBIGUATOR template +# else +# define SWIGTEMPLATEDISAMBIGUATOR +# endif +#endif + +/* inline attribute */ +#ifndef SWIGINLINE +# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__)) +# define SWIGINLINE inline +# else +# define SWIGINLINE +# endif +#endif + +/* attribute recognised by some compilers to avoid 'unused' warnings */ +#ifndef SWIGUNUSED +# if defined(__GNUC__) +# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +# elif defined(__ICC) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +#endif + +#ifndef SWIG_MSC_UNSUPPRESS_4505 +# if defined(_MSC_VER) +# pragma warning(disable : 4505) /* unreferenced local function has been removed */ +# endif +#endif + +#ifndef SWIGUNUSEDPARM +# ifdef __cplusplus +# define SWIGUNUSEDPARM(p) +# else +# define SWIGUNUSEDPARM(p) p SWIGUNUSED +# endif +#endif + +/* internal SWIG method */ +#ifndef SWIGINTERN +# define SWIGINTERN static SWIGUNUSED +#endif + +/* internal inline SWIG method */ +#ifndef SWIGINTERNINLINE +# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE +#endif + +/* exporting methods */ +#if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +# ifndef GCC_HASCLASSVISIBILITY +# define GCC_HASCLASSVISIBILITY +# endif +#endif + +#ifndef SWIGEXPORT +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# if defined(STATIC_LINKED) +# define SWIGEXPORT +# else +# define SWIGEXPORT __declspec(dllexport) +# endif +# else +# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY) +# define SWIGEXPORT __attribute__ ((visibility("default"))) +# else +# define SWIGEXPORT +# endif +# endif +#endif + +/* calling conventions for Windows */ +#ifndef SWIGSTDCALL +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# define SWIGSTDCALL __stdcall +# else +# define SWIGSTDCALL +# endif +#endif + +/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ +#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +# define _CRT_SECURE_NO_DEPRECATE +#endif + +/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */ +#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE) +# define _SCL_SECURE_NO_DEPRECATE +#endif + + + +/* Fix for jlong on some versions of gcc on Windows */ +#if defined(__GNUC__) && !defined(__INTEL_COMPILER) + typedef long long __int64; +#endif + +/* Fix for jlong on 64-bit x86 Solaris */ +#if defined(__x86_64) +# ifdef _LP64 +# undef _LP64 +# endif +#endif + +#include +#include +#include + + +/* Support for throwing Java exceptions */ +typedef enum { + SWIG_JavaOutOfMemoryError = 1, + SWIG_JavaIOException, + SWIG_JavaRuntimeException, + SWIG_JavaIndexOutOfBoundsException, + SWIG_JavaArithmeticException, + SWIG_JavaIllegalArgumentException, + SWIG_JavaNullPointerException, + SWIG_JavaDirectorPureVirtual, + SWIG_JavaUnknownError +} SWIG_JavaExceptionCodes; + +typedef struct { + SWIG_JavaExceptionCodes code; + const char *java_exception; +} SWIG_JavaExceptions_t; + + +static void SWIGUNUSED SWIG_JavaThrowException(JNIEnv *jenv, SWIG_JavaExceptionCodes code, const char *msg) { + jclass excep; + static const SWIG_JavaExceptions_t java_exceptions[] = { + { SWIG_JavaOutOfMemoryError, "java/lang/OutOfMemoryError" }, + { SWIG_JavaIOException, "java/io/IOException" }, + { SWIG_JavaRuntimeException, "java/lang/RuntimeException" }, + { SWIG_JavaIndexOutOfBoundsException, "java/lang/IndexOutOfBoundsException" }, + { SWIG_JavaArithmeticException, "java/lang/ArithmeticException" }, + { SWIG_JavaIllegalArgumentException, "java/lang/IllegalArgumentException" }, + { SWIG_JavaNullPointerException, "java/lang/NullPointerException" }, + { SWIG_JavaDirectorPureVirtual, "java/lang/RuntimeException" }, + { SWIG_JavaUnknownError, "java/lang/UnknownError" }, + { (SWIG_JavaExceptionCodes)0, "java/lang/UnknownError" } + }; + const SWIG_JavaExceptions_t *except_ptr = java_exceptions; + + while (except_ptr->code != code && except_ptr->code) + except_ptr++; + + (*jenv)->ExceptionClear(jenv); + excep = (*jenv)->FindClass(jenv, except_ptr->java_exception); + if (excep) + (*jenv)->ThrowNew(jenv, excep, msg); +} + + +/* Contract support */ + +#define SWIG_contract_assert(nullreturn, expr, msg) if (!(expr)) {SWIG_JavaThrowException(jenv, SWIG_JavaIllegalArgumentException, msg); return nullreturn; } else + +/* Errors in SWIG */ +#define SWIG_UnknownError -1 +#define SWIG_IOError -2 +#define SWIG_RuntimeError -3 +#define SWIG_IndexError -4 +#define SWIG_TypeError -5 +#define SWIG_DivisionByZero -6 +#define SWIG_OverflowError -7 +#define SWIG_SyntaxError -8 +#define SWIG_ValueError -9 +#define SWIG_SystemError -10 +#define SWIG_AttributeError -11 +#define SWIG_MemoryError -12 +#define SWIG_NullReferenceError -13 + + + + +SWIGINTERN void SWIG_JavaException(JNIEnv *jenv, int code, const char *msg) { + SWIG_JavaExceptionCodes exception_code = SWIG_JavaUnknownError; + switch(code) { + case SWIG_MemoryError: + exception_code = SWIG_JavaOutOfMemoryError; + break; + case SWIG_IOError: + exception_code = SWIG_JavaIOException; + break; + case SWIG_SystemError: + case SWIG_RuntimeError: + exception_code = SWIG_JavaRuntimeException; + break; + case SWIG_OverflowError: + case SWIG_IndexError: + exception_code = SWIG_JavaIndexOutOfBoundsException; + break; + case SWIG_DivisionByZero: + exception_code = SWIG_JavaArithmeticException; + break; + case SWIG_SyntaxError: + case SWIG_ValueError: + case SWIG_TypeError: + exception_code = SWIG_JavaIllegalArgumentException; + break; + case SWIG_UnknownError: + default: + exception_code = SWIG_JavaUnknownError; + break; + } + SWIG_JavaThrowException(jenv, exception_code, msg); +} + + +#if defined(SWIG_NOINCLUDE) || defined(SWIG_NOARRAYS) + + +int SWIG_JavaArrayInSchar (JNIEnv *jenv, jbyte **jarr, signed char **carr, jbyteArray input); +void SWIG_JavaArrayArgoutSchar (JNIEnv *jenv, jbyte *jarr, signed char *carr, jbyteArray input); +jbyteArray SWIG_JavaArrayOutSchar (JNIEnv *jenv, signed char *result, jsize sz); + + +int SWIG_JavaArrayInUchar (JNIEnv *jenv, jshort **jarr, unsigned char **carr, jshortArray input); +void SWIG_JavaArrayArgoutUchar (JNIEnv *jenv, jshort *jarr, unsigned char *carr, jshortArray input); +jshortArray SWIG_JavaArrayOutUchar (JNIEnv *jenv, unsigned char *result, jsize sz); + + +int SWIG_JavaArrayInShort (JNIEnv *jenv, jshort **jarr, short **carr, jshortArray input); +void SWIG_JavaArrayArgoutShort (JNIEnv *jenv, jshort *jarr, short *carr, jshortArray input); +jshortArray SWIG_JavaArrayOutShort (JNIEnv *jenv, short *result, jsize sz); + + +int SWIG_JavaArrayInUshort (JNIEnv *jenv, jint **jarr, unsigned short **carr, jintArray input); +void SWIG_JavaArrayArgoutUshort (JNIEnv *jenv, jint *jarr, unsigned short *carr, jintArray input); +jintArray SWIG_JavaArrayOutUshort (JNIEnv *jenv, unsigned short *result, jsize sz); + + +int SWIG_JavaArrayInInt (JNIEnv *jenv, jint **jarr, int **carr, jintArray input); +void SWIG_JavaArrayArgoutInt (JNIEnv *jenv, jint *jarr, int *carr, jintArray input); +jintArray SWIG_JavaArrayOutInt (JNIEnv *jenv, int *result, jsize sz); + + +int SWIG_JavaArrayInUint (JNIEnv *jenv, jlong **jarr, unsigned int **carr, jlongArray input); +void SWIG_JavaArrayArgoutUint (JNIEnv *jenv, jlong *jarr, unsigned int *carr, jlongArray input); +jlongArray SWIG_JavaArrayOutUint (JNIEnv *jenv, unsigned int *result, jsize sz); + + +int SWIG_JavaArrayInLong (JNIEnv *jenv, jint **jarr, long **carr, jintArray input); +void SWIG_JavaArrayArgoutLong (JNIEnv *jenv, jint *jarr, long *carr, jintArray input); +jintArray SWIG_JavaArrayOutLong (JNIEnv *jenv, long *result, jsize sz); + + +int SWIG_JavaArrayInUlong (JNIEnv *jenv, jlong **jarr, unsigned long **carr, jlongArray input); +void SWIG_JavaArrayArgoutUlong (JNIEnv *jenv, jlong *jarr, unsigned long *carr, jlongArray input); +jlongArray SWIG_JavaArrayOutUlong (JNIEnv *jenv, unsigned long *result, jsize sz); + + +int SWIG_JavaArrayInLonglong (JNIEnv *jenv, jlong **jarr, jlong **carr, jlongArray input); +void SWIG_JavaArrayArgoutLonglong (JNIEnv *jenv, jlong *jarr, jlong *carr, jlongArray input); +jlongArray SWIG_JavaArrayOutLonglong (JNIEnv *jenv, jlong *result, jsize sz); + + +int SWIG_JavaArrayInFloat (JNIEnv *jenv, jfloat **jarr, float **carr, jfloatArray input); +void SWIG_JavaArrayArgoutFloat (JNIEnv *jenv, jfloat *jarr, float *carr, jfloatArray input); +jfloatArray SWIG_JavaArrayOutFloat (JNIEnv *jenv, float *result, jsize sz); + + +int SWIG_JavaArrayInDouble (JNIEnv *jenv, jdouble **jarr, double **carr, jdoubleArray input); +void SWIG_JavaArrayArgoutDouble (JNIEnv *jenv, jdouble *jarr, double *carr, jdoubleArray input); +jdoubleArray SWIG_JavaArrayOutDouble (JNIEnv *jenv, double *result, jsize sz); + + +#else + + +/* signed char[] support */ +int SWIG_JavaArrayInSchar (JNIEnv *jenv, jbyte **jarr, signed char **carr, jbyteArray input) { + int i; + jsize sz; + if (!input) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null array"); + return 0; + } + sz = (*jenv)->GetArrayLength(jenv, input); + *jarr = (*jenv)->GetByteArrayElements(jenv, input, 0); + if (!*jarr) + return 0; + *carr = (signed char*) calloc(sz, sizeof(signed char)); + if (!*carr) { + SWIG_JavaThrowException(jenv, SWIG_JavaOutOfMemoryError, "array memory allocation failed"); + return 0; + } + for (i=0; iGetArrayLength(jenv, input); + for (i=0; iReleaseByteArrayElements(jenv, input, jarr, 0); +} + +jbyteArray SWIG_JavaArrayOutSchar (JNIEnv *jenv, signed char *result, jsize sz) { + jbyte *arr; + int i; + jbyteArray jresult = (*jenv)->NewByteArray(jenv, sz); + if (!jresult) + return NULL; + arr = (*jenv)->GetByteArrayElements(jenv, jresult, 0); + if (!arr) + return NULL; + for (i=0; iReleaseByteArrayElements(jenv, jresult, arr, 0); + return jresult; +} + + +/* unsigned char[] support */ +int SWIG_JavaArrayInUchar (JNIEnv *jenv, jshort **jarr, unsigned char **carr, jshortArray input) { + int i; + jsize sz; + if (!input) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null array"); + return 0; + } + sz = (*jenv)->GetArrayLength(jenv, input); + *jarr = (*jenv)->GetShortArrayElements(jenv, input, 0); + if (!*jarr) + return 0; + *carr = (unsigned char*) calloc(sz, sizeof(unsigned char)); + if (!*carr) { + SWIG_JavaThrowException(jenv, SWIG_JavaOutOfMemoryError, "array memory allocation failed"); + return 0; + } + for (i=0; iGetArrayLength(jenv, input); + for (i=0; iReleaseShortArrayElements(jenv, input, jarr, 0); +} + +jshortArray SWIG_JavaArrayOutUchar (JNIEnv *jenv, unsigned char *result, jsize sz) { + jshort *arr; + int i; + jshortArray jresult = (*jenv)->NewShortArray(jenv, sz); + if (!jresult) + return NULL; + arr = (*jenv)->GetShortArrayElements(jenv, jresult, 0); + if (!arr) + return NULL; + for (i=0; iReleaseShortArrayElements(jenv, jresult, arr, 0); + return jresult; +} + + +/* short[] support */ +int SWIG_JavaArrayInShort (JNIEnv *jenv, jshort **jarr, short **carr, jshortArray input) { + int i; + jsize sz; + if (!input) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null array"); + return 0; + } + sz = (*jenv)->GetArrayLength(jenv, input); + *jarr = (*jenv)->GetShortArrayElements(jenv, input, 0); + if (!*jarr) + return 0; + *carr = (short*) calloc(sz, sizeof(short)); + if (!*carr) { + SWIG_JavaThrowException(jenv, SWIG_JavaOutOfMemoryError, "array memory allocation failed"); + return 0; + } + for (i=0; iGetArrayLength(jenv, input); + for (i=0; iReleaseShortArrayElements(jenv, input, jarr, 0); +} + +jshortArray SWIG_JavaArrayOutShort (JNIEnv *jenv, short *result, jsize sz) { + jshort *arr; + int i; + jshortArray jresult = (*jenv)->NewShortArray(jenv, sz); + if (!jresult) + return NULL; + arr = (*jenv)->GetShortArrayElements(jenv, jresult, 0); + if (!arr) + return NULL; + for (i=0; iReleaseShortArrayElements(jenv, jresult, arr, 0); + return jresult; +} + + +/* unsigned short[] support */ +int SWIG_JavaArrayInUshort (JNIEnv *jenv, jint **jarr, unsigned short **carr, jintArray input) { + int i; + jsize sz; + if (!input) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null array"); + return 0; + } + sz = (*jenv)->GetArrayLength(jenv, input); + *jarr = (*jenv)->GetIntArrayElements(jenv, input, 0); + if (!*jarr) + return 0; + *carr = (unsigned short*) calloc(sz, sizeof(unsigned short)); + if (!*carr) { + SWIG_JavaThrowException(jenv, SWIG_JavaOutOfMemoryError, "array memory allocation failed"); + return 0; + } + for (i=0; iGetArrayLength(jenv, input); + for (i=0; iReleaseIntArrayElements(jenv, input, jarr, 0); +} + +jintArray SWIG_JavaArrayOutUshort (JNIEnv *jenv, unsigned short *result, jsize sz) { + jint *arr; + int i; + jintArray jresult = (*jenv)->NewIntArray(jenv, sz); + if (!jresult) + return NULL; + arr = (*jenv)->GetIntArrayElements(jenv, jresult, 0); + if (!arr) + return NULL; + for (i=0; iReleaseIntArrayElements(jenv, jresult, arr, 0); + return jresult; +} + + +/* int[] support */ +int SWIG_JavaArrayInInt (JNIEnv *jenv, jint **jarr, int **carr, jintArray input) { + int i; + jsize sz; + if (!input) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null array"); + return 0; + } + sz = (*jenv)->GetArrayLength(jenv, input); + *jarr = (*jenv)->GetIntArrayElements(jenv, input, 0); + if (!*jarr) + return 0; + *carr = (int*) calloc(sz, sizeof(int)); + if (!*carr) { + SWIG_JavaThrowException(jenv, SWIG_JavaOutOfMemoryError, "array memory allocation failed"); + return 0; + } + for (i=0; iGetArrayLength(jenv, input); + for (i=0; iReleaseIntArrayElements(jenv, input, jarr, 0); +} + +jintArray SWIG_JavaArrayOutInt (JNIEnv *jenv, int *result, jsize sz) { + jint *arr; + int i; + jintArray jresult = (*jenv)->NewIntArray(jenv, sz); + if (!jresult) + return NULL; + arr = (*jenv)->GetIntArrayElements(jenv, jresult, 0); + if (!arr) + return NULL; + for (i=0; iReleaseIntArrayElements(jenv, jresult, arr, 0); + return jresult; +} + + +/* unsigned int[] support */ +int SWIG_JavaArrayInUint (JNIEnv *jenv, jlong **jarr, unsigned int **carr, jlongArray input) { + int i; + jsize sz; + if (!input) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null array"); + return 0; + } + sz = (*jenv)->GetArrayLength(jenv, input); + *jarr = (*jenv)->GetLongArrayElements(jenv, input, 0); + if (!*jarr) + return 0; + *carr = (unsigned int*) calloc(sz, sizeof(unsigned int)); + if (!*carr) { + SWIG_JavaThrowException(jenv, SWIG_JavaOutOfMemoryError, "array memory allocation failed"); + return 0; + } + for (i=0; iGetArrayLength(jenv, input); + for (i=0; iReleaseLongArrayElements(jenv, input, jarr, 0); +} + +jlongArray SWIG_JavaArrayOutUint (JNIEnv *jenv, unsigned int *result, jsize sz) { + jlong *arr; + int i; + jlongArray jresult = (*jenv)->NewLongArray(jenv, sz); + if (!jresult) + return NULL; + arr = (*jenv)->GetLongArrayElements(jenv, jresult, 0); + if (!arr) + return NULL; + for (i=0; iReleaseLongArrayElements(jenv, jresult, arr, 0); + return jresult; +} + + +/* long[] support */ +int SWIG_JavaArrayInLong (JNIEnv *jenv, jint **jarr, long **carr, jintArray input) { + int i; + jsize sz; + if (!input) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null array"); + return 0; + } + sz = (*jenv)->GetArrayLength(jenv, input); + *jarr = (*jenv)->GetIntArrayElements(jenv, input, 0); + if (!*jarr) + return 0; + *carr = (long*) calloc(sz, sizeof(long)); + if (!*carr) { + SWIG_JavaThrowException(jenv, SWIG_JavaOutOfMemoryError, "array memory allocation failed"); + return 0; + } + for (i=0; iGetArrayLength(jenv, input); + for (i=0; iReleaseIntArrayElements(jenv, input, jarr, 0); +} + +jintArray SWIG_JavaArrayOutLong (JNIEnv *jenv, long *result, jsize sz) { + jint *arr; + int i; + jintArray jresult = (*jenv)->NewIntArray(jenv, sz); + if (!jresult) + return NULL; + arr = (*jenv)->GetIntArrayElements(jenv, jresult, 0); + if (!arr) + return NULL; + for (i=0; iReleaseIntArrayElements(jenv, jresult, arr, 0); + return jresult; +} + + +/* unsigned long[] support */ +int SWIG_JavaArrayInUlong (JNIEnv *jenv, jlong **jarr, unsigned long **carr, jlongArray input) { + int i; + jsize sz; + if (!input) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null array"); + return 0; + } + sz = (*jenv)->GetArrayLength(jenv, input); + *jarr = (*jenv)->GetLongArrayElements(jenv, input, 0); + if (!*jarr) + return 0; + *carr = (unsigned long*) calloc(sz, sizeof(unsigned long)); + if (!*carr) { + SWIG_JavaThrowException(jenv, SWIG_JavaOutOfMemoryError, "array memory allocation failed"); + return 0; + } + for (i=0; iGetArrayLength(jenv, input); + for (i=0; iReleaseLongArrayElements(jenv, input, jarr, 0); +} + +jlongArray SWIG_JavaArrayOutUlong (JNIEnv *jenv, unsigned long *result, jsize sz) { + jlong *arr; + int i; + jlongArray jresult = (*jenv)->NewLongArray(jenv, sz); + if (!jresult) + return NULL; + arr = (*jenv)->GetLongArrayElements(jenv, jresult, 0); + if (!arr) + return NULL; + for (i=0; iReleaseLongArrayElements(jenv, jresult, arr, 0); + return jresult; +} + + +/* jlong[] support */ +int SWIG_JavaArrayInLonglong (JNIEnv *jenv, jlong **jarr, jlong **carr, jlongArray input) { + int i; + jsize sz; + if (!input) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null array"); + return 0; + } + sz = (*jenv)->GetArrayLength(jenv, input); + *jarr = (*jenv)->GetLongArrayElements(jenv, input, 0); + if (!*jarr) + return 0; + *carr = (jlong*) calloc(sz, sizeof(jlong)); + if (!*carr) { + SWIG_JavaThrowException(jenv, SWIG_JavaOutOfMemoryError, "array memory allocation failed"); + return 0; + } + for (i=0; iGetArrayLength(jenv, input); + for (i=0; iReleaseLongArrayElements(jenv, input, jarr, 0); +} + +jlongArray SWIG_JavaArrayOutLonglong (JNIEnv *jenv, jlong *result, jsize sz) { + jlong *arr; + int i; + jlongArray jresult = (*jenv)->NewLongArray(jenv, sz); + if (!jresult) + return NULL; + arr = (*jenv)->GetLongArrayElements(jenv, jresult, 0); + if (!arr) + return NULL; + for (i=0; iReleaseLongArrayElements(jenv, jresult, arr, 0); + return jresult; +} + + +/* float[] support */ +int SWIG_JavaArrayInFloat (JNIEnv *jenv, jfloat **jarr, float **carr, jfloatArray input) { + int i; + jsize sz; + if (!input) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null array"); + return 0; + } + sz = (*jenv)->GetArrayLength(jenv, input); + *jarr = (*jenv)->GetFloatArrayElements(jenv, input, 0); + if (!*jarr) + return 0; + *carr = (float*) calloc(sz, sizeof(float)); + if (!*carr) { + SWIG_JavaThrowException(jenv, SWIG_JavaOutOfMemoryError, "array memory allocation failed"); + return 0; + } + for (i=0; iGetArrayLength(jenv, input); + for (i=0; iReleaseFloatArrayElements(jenv, input, jarr, 0); +} + +jfloatArray SWIG_JavaArrayOutFloat (JNIEnv *jenv, float *result, jsize sz) { + jfloat *arr; + int i; + jfloatArray jresult = (*jenv)->NewFloatArray(jenv, sz); + if (!jresult) + return NULL; + arr = (*jenv)->GetFloatArrayElements(jenv, jresult, 0); + if (!arr) + return NULL; + for (i=0; iReleaseFloatArrayElements(jenv, jresult, arr, 0); + return jresult; +} + + +/* double[] support */ +int SWIG_JavaArrayInDouble (JNIEnv *jenv, jdouble **jarr, double **carr, jdoubleArray input) { + int i; + jsize sz; + if (!input) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null array"); + return 0; + } + sz = (*jenv)->GetArrayLength(jenv, input); + *jarr = (*jenv)->GetDoubleArrayElements(jenv, input, 0); + if (!*jarr) + return 0; + *carr = (double*) calloc(sz, sizeof(double)); + if (!*carr) { + SWIG_JavaThrowException(jenv, SWIG_JavaOutOfMemoryError, "array memory allocation failed"); + return 0; + } + for (i=0; iGetArrayLength(jenv, input); + for (i=0; iReleaseDoubleArrayElements(jenv, input, jarr, 0); +} + +jdoubleArray SWIG_JavaArrayOutDouble (JNIEnv *jenv, double *result, jsize sz) { + jdouble *arr; + int i; + jdoubleArray jresult = (*jenv)->NewDoubleArray(jenv, sz); + if (!jresult) + return NULL; + arr = (*jenv)->GetDoubleArrayElements(jenv, jresult, 0); + if (!arr) + return NULL; + for (i=0; iReleaseDoubleArrayElements(jenv, jresult, arr, 0); + return jresult; +} + + +#endif + + +#include "webp/types.h" + + +int SWIG_JavaArrayInUint8 (JNIEnv *jenv, jbyte **jarr, uint8_t **carr, jbyteArray input); +void SWIG_JavaArrayArgoutUint8 (JNIEnv *jenv, jbyte *jarr, uint8_t *carr, jbyteArray input); +jbyteArray SWIG_JavaArrayOutUint8 (JNIEnv *jenv, uint8_t *result, jsize sz); + + +/* uint8_t[] support */ +int SWIG_JavaArrayInUint8 (JNIEnv *jenv, jbyte **jarr, uint8_t **carr, jbyteArray input) { + int i; + jsize sz; + if (!input) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null array"); + return 0; + } + sz = (*jenv)->GetArrayLength(jenv, input); + *jarr = (*jenv)->GetByteArrayElements(jenv, input, 0); + if (!*jarr) + return 0; + *carr = (uint8_t*) calloc(sz, sizeof(uint8_t)); + if (!*carr) { + SWIG_JavaThrowException(jenv, SWIG_JavaOutOfMemoryError, "array memory allocation failed"); + return 0; + } + for (i=0; iGetArrayLength(jenv, input); + for (i=0; iReleaseByteArrayElements(jenv, input, jarr, 0); +} + +jbyteArray SWIG_JavaArrayOutUint8 (JNIEnv *jenv, uint8_t *result, jsize sz) { + jbyte *arr; + int i; + jbyteArray jresult = (*jenv)->NewByteArray(jenv, sz); + if (!jresult) + return NULL; + arr = (*jenv)->GetByteArrayElements(jenv, jresult, 0); + if (!arr) + return NULL; + for (i=0; iReleaseByteArrayElements(jenv, jresult, arr, 0); + return jresult; +} + + +#include "webp/decode.h" +#include "webp/encode.h" + + +#define FillMeInAsSizeCannotBeDeterminedAutomatically \ + (result ? (jint)ReturnedBufferSize(__FUNCTION__, arg3, arg4) : 0) + + +static size_t ReturnedBufferSize( + const char* function, int* width, int* height) { + static const struct sizemap { + const char* function; + int size_multiplier; + } size_map[] = { +#ifdef SWIGJAVA + { "Java_com_google_webp_libwebpJNI_WebPDecodeRGB", 3 }, + { "Java_com_google_webp_libwebpJNI_WebPDecodeRGBA", 4 }, + { "Java_com_google_webp_libwebpJNI_WebPDecodeARGB", 4 }, + { "Java_com_google_webp_libwebpJNI_WebPDecodeBGR", 3 }, + { "Java_com_google_webp_libwebpJNI_WebPDecodeBGRA", 4 }, + { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeRGB", 1 }, + { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeBGR", 1 }, + { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeRGBA", 1 }, + { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeBGRA", 1 }, + { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessRGB", 1 }, + { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessBGR", 1 }, + { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessRGBA", 1 }, + { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessBGRA", 1 }, +#endif +#ifdef SWIGPYTHON + { "WebPDecodeRGB", 3 }, + { "WebPDecodeRGBA", 4 }, + { "WebPDecodeARGB", 4 }, + { "WebPDecodeBGR", 3 }, + { "WebPDecodeBGRA", 4 }, + { "wrap_WebPEncodeRGB", 1 }, + { "wrap_WebPEncodeBGR", 1 }, + { "wrap_WebPEncodeRGBA", 1 }, + { "wrap_WebPEncodeBGRA", 1 }, + { "wrap_WebPEncodeLosslessRGB", 1 }, + { "wrap_WebPEncodeLosslessBGR", 1 }, + { "wrap_WebPEncodeLosslessRGBA", 1 }, + { "wrap_WebPEncodeLosslessBGRA", 1 }, +#endif + { NULL, 0 } + }; + const struct sizemap* p; + size_t size = 0; + + for (p = size_map; p->function; ++p) { + if (!strcmp(function, p->function)) { + size = *width * *height * p->size_multiplier; + break; + } + } + + return size; +} + + +typedef size_t (*WebPEncodeFunction)(const uint8_t* rgb, + int width, int height, int stride, + float quality_factor, uint8_t** output); +typedef size_t (*WebPEncodeLosslessFunction)(const uint8_t* rgb, + int width, int height, int stride, + uint8_t** output); + +static uint8_t* EncodeLossy(const uint8_t* rgb, + int width, int height, int stride, + float quality_factor, + WebPEncodeFunction encfn, + int* output_size, int* unused) { + uint8_t* output = NULL; + const size_t image_size = + encfn(rgb, width, height, stride, quality_factor, &output); + // the values of following two will be interpreted by ReturnedBufferSize() + // as 'width' and 'height' in the size calculation. + *output_size = image_size; + *unused = 1; + return image_size ? output : NULL; +} + +static uint8_t* EncodeLossless(const uint8_t* rgb, + int width, int height, int stride, + WebPEncodeLosslessFunction encfn, + int* output_size, int* unused) { + uint8_t* output = NULL; + const size_t image_size = encfn(rgb, width, height, stride, &output); + // the values of the following two will be interpreted by + // ReturnedBufferSize() as 'width' and 'height' in the size calculation. + *output_size = image_size; + *unused = 1; + return image_size ? output : NULL; +} + + +// Changes the return type of WebPEncode* to more closely match Decode*. +// This also makes it easier to wrap the output buffer in a native type rather +// than dealing with the return pointer. +// The additional parameters are to allow reuse of ReturnedBufferSize(), +// unused2 and output_size will be used in this case. +#define LOSSY_WRAPPER(FUNC) \ + static uint8_t* wrap_##FUNC( \ + const uint8_t* rgb, int* unused1, int* unused2, int* output_size, \ + int width, int height, int stride, float quality_factor) { \ + return EncodeLossy(rgb, width, height, stride, quality_factor, \ + FUNC, output_size, unused2); \ + } \ + +LOSSY_WRAPPER(WebPEncodeRGB) +LOSSY_WRAPPER(WebPEncodeBGR) +LOSSY_WRAPPER(WebPEncodeRGBA) +LOSSY_WRAPPER(WebPEncodeBGRA) + +#undef LOSSY_WRAPPER + +#define LOSSLESS_WRAPPER(FUNC) \ + static uint8_t* wrap_##FUNC( \ + const uint8_t* rgb, int* unused1, int* unused2, int* output_size, \ + int width, int height, int stride) { \ + return EncodeLossless(rgb, width, height, stride, \ + FUNC, output_size, unused2); \ + } \ + +LOSSLESS_WRAPPER(WebPEncodeLosslessRGB) +LOSSLESS_WRAPPER(WebPEncodeLosslessBGR) +LOSSLESS_WRAPPER(WebPEncodeLosslessRGBA) +LOSSLESS_WRAPPER(WebPEncodeLosslessBGRA) + +#undef LOSSLESS_WRAPPER + + + +/* Work around broken gcj jni.h */ +#ifdef __GCJ_JNI_H__ +# undef JNIEXPORT +# define JNIEXPORT +# undef JNICALL +# define JNICALL +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +SWIGEXPORT jint JNICALL Java_com_google_webp_libwebpJNI_WebPGetDecoderVersion(JNIEnv *jenv, jclass jcls) { + jint jresult = 0 ; + int result; + + (void)jenv; + (void)jcls; + result = (int)WebPGetDecoderVersion(); + jresult = (jint)result; + return jresult; +} + + +SWIGEXPORT jint JNICALL Java_com_google_webp_libwebpJNI_WebPGetInfo(JNIEnv *jenv, jclass jcls, jbyteArray jarg1, jlong jarg2, jintArray jarg3, jintArray jarg4) { + jint jresult = 0 ; + uint8_t *arg1 = (uint8_t *) 0 ; + size_t arg2 ; + int *arg3 = (int *) 0 ; + int *arg4 = (int *) 0 ; + jbyte *jarr1 ; + int temp3 ; + int temp4 ; + int result; + + (void)jenv; + (void)jcls; + if (!SWIG_JavaArrayInUint8(jenv, &jarr1, &arg1, jarg1)) return 0; + arg2 = (size_t)jarg2; + { + if (!jarg3) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); + return 0; + } + if ((*jenv)->GetArrayLength(jenv, jarg3) == 0) { + SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); + return 0; + } + arg3 = &temp3; + } + { + if (!jarg4) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); + return 0; + } + if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) { + SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); + return 0; + } + arg4 = &temp4; + } + result = (int)WebPGetInfo((uint8_t const *)arg1,arg2,arg3,arg4); + jresult = (jint)result; + SWIG_JavaArrayArgoutUint8(jenv, jarr1, arg1, jarg1); + { + jint jvalue = (jint)temp3; + (*jenv)->SetIntArrayRegion(jenv, jarg3, 0, 1, &jvalue); + } + { + jint jvalue = (jint)temp4; + (*jenv)->SetIntArrayRegion(jenv, jarg4, 0, 1, &jvalue); + } + free(arg1); + + + return jresult; +} + + +SWIGEXPORT jbyteArray JNICALL Java_com_google_webp_libwebpJNI_WebPDecodeRGB(JNIEnv *jenv, jclass jcls, jbyteArray jarg1, jlong jarg2, jintArray jarg3, jintArray jarg4) { + jbyteArray jresult = 0 ; + uint8_t *arg1 = (uint8_t *) 0 ; + size_t arg2 ; + int *arg3 = (int *) 0 ; + int *arg4 = (int *) 0 ; + jbyte *jarr1 ; + int temp3 ; + int temp4 ; + uint8_t *result = 0 ; + + (void)jenv; + (void)jcls; + if (!SWIG_JavaArrayInUint8(jenv, &jarr1, &arg1, jarg1)) return 0; + arg2 = (size_t)jarg2; + { + if (!jarg3) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); + return 0; + } + if ((*jenv)->GetArrayLength(jenv, jarg3) == 0) { + SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); + return 0; + } + arg3 = &temp3; + } + { + if (!jarg4) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); + return 0; + } + if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) { + SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); + return 0; + } + arg4 = &temp4; + } + result = (uint8_t *)WebPDecodeRGB((uint8_t const *)arg1,arg2,arg3,arg4); + jresult = SWIG_JavaArrayOutUint8(jenv, result, FillMeInAsSizeCannotBeDeterminedAutomatically); + SWIG_JavaArrayArgoutUint8(jenv, jarr1, arg1, jarg1); + { + jint jvalue = (jint)temp3; + (*jenv)->SetIntArrayRegion(jenv, jarg3, 0, 1, &jvalue); + } + { + jint jvalue = (jint)temp4; + (*jenv)->SetIntArrayRegion(jenv, jarg4, 0, 1, &jvalue); + } + free(arg1); + + + free(result); + return jresult; +} + + +SWIGEXPORT jbyteArray JNICALL Java_com_google_webp_libwebpJNI_WebPDecodeRGBA(JNIEnv *jenv, jclass jcls, jbyteArray jarg1, jlong jarg2, jintArray jarg3, jintArray jarg4) { + jbyteArray jresult = 0 ; + uint8_t *arg1 = (uint8_t *) 0 ; + size_t arg2 ; + int *arg3 = (int *) 0 ; + int *arg4 = (int *) 0 ; + jbyte *jarr1 ; + int temp3 ; + int temp4 ; + uint8_t *result = 0 ; + + (void)jenv; + (void)jcls; + if (!SWIG_JavaArrayInUint8(jenv, &jarr1, &arg1, jarg1)) return 0; + arg2 = (size_t)jarg2; + { + if (!jarg3) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); + return 0; + } + if ((*jenv)->GetArrayLength(jenv, jarg3) == 0) { + SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); + return 0; + } + arg3 = &temp3; + } + { + if (!jarg4) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); + return 0; + } + if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) { + SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); + return 0; + } + arg4 = &temp4; + } + result = (uint8_t *)WebPDecodeRGBA((uint8_t const *)arg1,arg2,arg3,arg4); + jresult = SWIG_JavaArrayOutUint8(jenv, result, FillMeInAsSizeCannotBeDeterminedAutomatically); + SWIG_JavaArrayArgoutUint8(jenv, jarr1, arg1, jarg1); + { + jint jvalue = (jint)temp3; + (*jenv)->SetIntArrayRegion(jenv, jarg3, 0, 1, &jvalue); + } + { + jint jvalue = (jint)temp4; + (*jenv)->SetIntArrayRegion(jenv, jarg4, 0, 1, &jvalue); + } + free(arg1); + + + free(result); + return jresult; +} + + +SWIGEXPORT jbyteArray JNICALL Java_com_google_webp_libwebpJNI_WebPDecodeARGB(JNIEnv *jenv, jclass jcls, jbyteArray jarg1, jlong jarg2, jintArray jarg3, jintArray jarg4) { + jbyteArray jresult = 0 ; + uint8_t *arg1 = (uint8_t *) 0 ; + size_t arg2 ; + int *arg3 = (int *) 0 ; + int *arg4 = (int *) 0 ; + jbyte *jarr1 ; + int temp3 ; + int temp4 ; + uint8_t *result = 0 ; + + (void)jenv; + (void)jcls; + if (!SWIG_JavaArrayInUint8(jenv, &jarr1, &arg1, jarg1)) return 0; + arg2 = (size_t)jarg2; + { + if (!jarg3) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); + return 0; + } + if ((*jenv)->GetArrayLength(jenv, jarg3) == 0) { + SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); + return 0; + } + arg3 = &temp3; + } + { + if (!jarg4) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); + return 0; + } + if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) { + SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); + return 0; + } + arg4 = &temp4; + } + result = (uint8_t *)WebPDecodeARGB((uint8_t const *)arg1,arg2,arg3,arg4); + jresult = SWIG_JavaArrayOutUint8(jenv, result, FillMeInAsSizeCannotBeDeterminedAutomatically); + SWIG_JavaArrayArgoutUint8(jenv, jarr1, arg1, jarg1); + { + jint jvalue = (jint)temp3; + (*jenv)->SetIntArrayRegion(jenv, jarg3, 0, 1, &jvalue); + } + { + jint jvalue = (jint)temp4; + (*jenv)->SetIntArrayRegion(jenv, jarg4, 0, 1, &jvalue); + } + free(arg1); + + + free(result); + return jresult; +} + + +SWIGEXPORT jbyteArray JNICALL Java_com_google_webp_libwebpJNI_WebPDecodeBGR(JNIEnv *jenv, jclass jcls, jbyteArray jarg1, jlong jarg2, jintArray jarg3, jintArray jarg4) { + jbyteArray jresult = 0 ; + uint8_t *arg1 = (uint8_t *) 0 ; + size_t arg2 ; + int *arg3 = (int *) 0 ; + int *arg4 = (int *) 0 ; + jbyte *jarr1 ; + int temp3 ; + int temp4 ; + uint8_t *result = 0 ; + + (void)jenv; + (void)jcls; + if (!SWIG_JavaArrayInUint8(jenv, &jarr1, &arg1, jarg1)) return 0; + arg2 = (size_t)jarg2; + { + if (!jarg3) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); + return 0; + } + if ((*jenv)->GetArrayLength(jenv, jarg3) == 0) { + SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); + return 0; + } + arg3 = &temp3; + } + { + if (!jarg4) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); + return 0; + } + if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) { + SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); + return 0; + } + arg4 = &temp4; + } + result = (uint8_t *)WebPDecodeBGR((uint8_t const *)arg1,arg2,arg3,arg4); + jresult = SWIG_JavaArrayOutUint8(jenv, result, FillMeInAsSizeCannotBeDeterminedAutomatically); + SWIG_JavaArrayArgoutUint8(jenv, jarr1, arg1, jarg1); + { + jint jvalue = (jint)temp3; + (*jenv)->SetIntArrayRegion(jenv, jarg3, 0, 1, &jvalue); + } + { + jint jvalue = (jint)temp4; + (*jenv)->SetIntArrayRegion(jenv, jarg4, 0, 1, &jvalue); + } + free(arg1); + + + free(result); + return jresult; +} + + +SWIGEXPORT jbyteArray JNICALL Java_com_google_webp_libwebpJNI_WebPDecodeBGRA(JNIEnv *jenv, jclass jcls, jbyteArray jarg1, jlong jarg2, jintArray jarg3, jintArray jarg4) { + jbyteArray jresult = 0 ; + uint8_t *arg1 = (uint8_t *) 0 ; + size_t arg2 ; + int *arg3 = (int *) 0 ; + int *arg4 = (int *) 0 ; + jbyte *jarr1 ; + int temp3 ; + int temp4 ; + uint8_t *result = 0 ; + + (void)jenv; + (void)jcls; + if (!SWIG_JavaArrayInUint8(jenv, &jarr1, &arg1, jarg1)) return 0; + arg2 = (size_t)jarg2; + { + if (!jarg3) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); + return 0; + } + if ((*jenv)->GetArrayLength(jenv, jarg3) == 0) { + SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); + return 0; + } + arg3 = &temp3; + } + { + if (!jarg4) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); + return 0; + } + if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) { + SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); + return 0; + } + arg4 = &temp4; + } + result = (uint8_t *)WebPDecodeBGRA((uint8_t const *)arg1,arg2,arg3,arg4); + jresult = SWIG_JavaArrayOutUint8(jenv, result, FillMeInAsSizeCannotBeDeterminedAutomatically); + SWIG_JavaArrayArgoutUint8(jenv, jarr1, arg1, jarg1); + { + jint jvalue = (jint)temp3; + (*jenv)->SetIntArrayRegion(jenv, jarg3, 0, 1, &jvalue); + } + { + jint jvalue = (jint)temp4; + (*jenv)->SetIntArrayRegion(jenv, jarg4, 0, 1, &jvalue); + } + free(arg1); + + + free(result); + return jresult; +} + + +SWIGEXPORT jint JNICALL Java_com_google_webp_libwebpJNI_WebPGetEncoderVersion(JNIEnv *jenv, jclass jcls) { + jint jresult = 0 ; + int result; + + (void)jenv; + (void)jcls; + result = (int)WebPGetEncoderVersion(); + jresult = (jint)result; + return jresult; +} + + +SWIGEXPORT jbyteArray JNICALL Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeRGB(JNIEnv *jenv, jclass jcls, jbyteArray jarg1, jint jarg2, jint jarg3, jintArray jarg4, jint jarg5, jint jarg6, jint jarg7, jfloat jarg8) { + jbyteArray jresult = 0 ; + uint8_t *arg1 = (uint8_t *) 0 ; + int *arg2 = (int *) 0 ; + int *arg3 = (int *) 0 ; + int *arg4 = (int *) 0 ; + int arg5 ; + int arg6 ; + int arg7 ; + float arg8 ; + jbyte *jarr1 ; + int temp4 ; + uint8_t *result = 0 ; + + (void)jenv; + (void)jcls; + if (!SWIG_JavaArrayInUint8(jenv, &jarr1, &arg1, jarg1)) return 0; + arg2 = (int *)&jarg2; + arg3 = (int *)&jarg3; + { + if (!jarg4) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); + return 0; + } + if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) { + SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); + return 0; + } + arg4 = &temp4; + } + arg5 = (int)jarg5; + arg6 = (int)jarg6; + arg7 = (int)jarg7; + arg8 = (float)jarg8; + result = (uint8_t *)wrap_WebPEncodeRGB((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8); + jresult = SWIG_JavaArrayOutUint8(jenv, result, FillMeInAsSizeCannotBeDeterminedAutomatically); + SWIG_JavaArrayArgoutUint8(jenv, jarr1, arg1, jarg1); + { + jint jvalue = (jint)temp4; + (*jenv)->SetIntArrayRegion(jenv, jarg4, 0, 1, &jvalue); + } + free(arg1); + + + + free(result); + return jresult; +} + + +SWIGEXPORT jbyteArray JNICALL Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeBGR(JNIEnv *jenv, jclass jcls, jbyteArray jarg1, jint jarg2, jint jarg3, jintArray jarg4, jint jarg5, jint jarg6, jint jarg7, jfloat jarg8) { + jbyteArray jresult = 0 ; + uint8_t *arg1 = (uint8_t *) 0 ; + int *arg2 = (int *) 0 ; + int *arg3 = (int *) 0 ; + int *arg4 = (int *) 0 ; + int arg5 ; + int arg6 ; + int arg7 ; + float arg8 ; + jbyte *jarr1 ; + int temp4 ; + uint8_t *result = 0 ; + + (void)jenv; + (void)jcls; + if (!SWIG_JavaArrayInUint8(jenv, &jarr1, &arg1, jarg1)) return 0; + arg2 = (int *)&jarg2; + arg3 = (int *)&jarg3; + { + if (!jarg4) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); + return 0; + } + if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) { + SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); + return 0; + } + arg4 = &temp4; + } + arg5 = (int)jarg5; + arg6 = (int)jarg6; + arg7 = (int)jarg7; + arg8 = (float)jarg8; + result = (uint8_t *)wrap_WebPEncodeBGR((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8); + jresult = SWIG_JavaArrayOutUint8(jenv, result, FillMeInAsSizeCannotBeDeterminedAutomatically); + SWIG_JavaArrayArgoutUint8(jenv, jarr1, arg1, jarg1); + { + jint jvalue = (jint)temp4; + (*jenv)->SetIntArrayRegion(jenv, jarg4, 0, 1, &jvalue); + } + free(arg1); + + + + free(result); + return jresult; +} + + +SWIGEXPORT jbyteArray JNICALL Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeRGBA(JNIEnv *jenv, jclass jcls, jbyteArray jarg1, jint jarg2, jint jarg3, jintArray jarg4, jint jarg5, jint jarg6, jint jarg7, jfloat jarg8) { + jbyteArray jresult = 0 ; + uint8_t *arg1 = (uint8_t *) 0 ; + int *arg2 = (int *) 0 ; + int *arg3 = (int *) 0 ; + int *arg4 = (int *) 0 ; + int arg5 ; + int arg6 ; + int arg7 ; + float arg8 ; + jbyte *jarr1 ; + int temp4 ; + uint8_t *result = 0 ; + + (void)jenv; + (void)jcls; + if (!SWIG_JavaArrayInUint8(jenv, &jarr1, &arg1, jarg1)) return 0; + arg2 = (int *)&jarg2; + arg3 = (int *)&jarg3; + { + if (!jarg4) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); + return 0; + } + if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) { + SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); + return 0; + } + arg4 = &temp4; + } + arg5 = (int)jarg5; + arg6 = (int)jarg6; + arg7 = (int)jarg7; + arg8 = (float)jarg8; + result = (uint8_t *)wrap_WebPEncodeRGBA((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8); + jresult = SWIG_JavaArrayOutUint8(jenv, result, FillMeInAsSizeCannotBeDeterminedAutomatically); + SWIG_JavaArrayArgoutUint8(jenv, jarr1, arg1, jarg1); + { + jint jvalue = (jint)temp4; + (*jenv)->SetIntArrayRegion(jenv, jarg4, 0, 1, &jvalue); + } + free(arg1); + + + + free(result); + return jresult; +} + + +SWIGEXPORT jbyteArray JNICALL Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeBGRA(JNIEnv *jenv, jclass jcls, jbyteArray jarg1, jint jarg2, jint jarg3, jintArray jarg4, jint jarg5, jint jarg6, jint jarg7, jfloat jarg8) { + jbyteArray jresult = 0 ; + uint8_t *arg1 = (uint8_t *) 0 ; + int *arg2 = (int *) 0 ; + int *arg3 = (int *) 0 ; + int *arg4 = (int *) 0 ; + int arg5 ; + int arg6 ; + int arg7 ; + float arg8 ; + jbyte *jarr1 ; + int temp4 ; + uint8_t *result = 0 ; + + (void)jenv; + (void)jcls; + if (!SWIG_JavaArrayInUint8(jenv, &jarr1, &arg1, jarg1)) return 0; + arg2 = (int *)&jarg2; + arg3 = (int *)&jarg3; + { + if (!jarg4) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); + return 0; + } + if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) { + SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); + return 0; + } + arg4 = &temp4; + } + arg5 = (int)jarg5; + arg6 = (int)jarg6; + arg7 = (int)jarg7; + arg8 = (float)jarg8; + result = (uint8_t *)wrap_WebPEncodeBGRA((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8); + jresult = SWIG_JavaArrayOutUint8(jenv, result, FillMeInAsSizeCannotBeDeterminedAutomatically); + SWIG_JavaArrayArgoutUint8(jenv, jarr1, arg1, jarg1); + { + jint jvalue = (jint)temp4; + (*jenv)->SetIntArrayRegion(jenv, jarg4, 0, 1, &jvalue); + } + free(arg1); + + + + free(result); + return jresult; +} + + +SWIGEXPORT jbyteArray JNICALL Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessRGB(JNIEnv *jenv, jclass jcls, jbyteArray jarg1, jint jarg2, jint jarg3, jintArray jarg4, jint jarg5, jint jarg6, jint jarg7) { + jbyteArray jresult = 0 ; + uint8_t *arg1 = (uint8_t *) 0 ; + int *arg2 = (int *) 0 ; + int *arg3 = (int *) 0 ; + int *arg4 = (int *) 0 ; + int arg5 ; + int arg6 ; + int arg7 ; + jbyte *jarr1 ; + int temp4 ; + uint8_t *result = 0 ; + + (void)jenv; + (void)jcls; + if (!SWIG_JavaArrayInUint8(jenv, &jarr1, &arg1, jarg1)) return 0; + arg2 = (int *)&jarg2; + arg3 = (int *)&jarg3; + { + if (!jarg4) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); + return 0; + } + if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) { + SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); + return 0; + } + arg4 = &temp4; + } + arg5 = (int)jarg5; + arg6 = (int)jarg6; + arg7 = (int)jarg7; + result = (uint8_t *)wrap_WebPEncodeLosslessRGB((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7); + jresult = SWIG_JavaArrayOutUint8(jenv, result, FillMeInAsSizeCannotBeDeterminedAutomatically); + SWIG_JavaArrayArgoutUint8(jenv, jarr1, arg1, jarg1); + { + jint jvalue = (jint)temp4; + (*jenv)->SetIntArrayRegion(jenv, jarg4, 0, 1, &jvalue); + } + free(arg1); + + + + free(result); + return jresult; +} + + +SWIGEXPORT jbyteArray JNICALL Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessBGR(JNIEnv *jenv, jclass jcls, jbyteArray jarg1, jint jarg2, jint jarg3, jintArray jarg4, jint jarg5, jint jarg6, jint jarg7) { + jbyteArray jresult = 0 ; + uint8_t *arg1 = (uint8_t *) 0 ; + int *arg2 = (int *) 0 ; + int *arg3 = (int *) 0 ; + int *arg4 = (int *) 0 ; + int arg5 ; + int arg6 ; + int arg7 ; + jbyte *jarr1 ; + int temp4 ; + uint8_t *result = 0 ; + + (void)jenv; + (void)jcls; + if (!SWIG_JavaArrayInUint8(jenv, &jarr1, &arg1, jarg1)) return 0; + arg2 = (int *)&jarg2; + arg3 = (int *)&jarg3; + { + if (!jarg4) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); + return 0; + } + if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) { + SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); + return 0; + } + arg4 = &temp4; + } + arg5 = (int)jarg5; + arg6 = (int)jarg6; + arg7 = (int)jarg7; + result = (uint8_t *)wrap_WebPEncodeLosslessBGR((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7); + jresult = SWIG_JavaArrayOutUint8(jenv, result, FillMeInAsSizeCannotBeDeterminedAutomatically); + SWIG_JavaArrayArgoutUint8(jenv, jarr1, arg1, jarg1); + { + jint jvalue = (jint)temp4; + (*jenv)->SetIntArrayRegion(jenv, jarg4, 0, 1, &jvalue); + } + free(arg1); + + + + free(result); + return jresult; +} + + +SWIGEXPORT jbyteArray JNICALL Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessRGBA(JNIEnv *jenv, jclass jcls, jbyteArray jarg1, jint jarg2, jint jarg3, jintArray jarg4, jint jarg5, jint jarg6, jint jarg7) { + jbyteArray jresult = 0 ; + uint8_t *arg1 = (uint8_t *) 0 ; + int *arg2 = (int *) 0 ; + int *arg3 = (int *) 0 ; + int *arg4 = (int *) 0 ; + int arg5 ; + int arg6 ; + int arg7 ; + jbyte *jarr1 ; + int temp4 ; + uint8_t *result = 0 ; + + (void)jenv; + (void)jcls; + if (!SWIG_JavaArrayInUint8(jenv, &jarr1, &arg1, jarg1)) return 0; + arg2 = (int *)&jarg2; + arg3 = (int *)&jarg3; + { + if (!jarg4) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); + return 0; + } + if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) { + SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); + return 0; + } + arg4 = &temp4; + } + arg5 = (int)jarg5; + arg6 = (int)jarg6; + arg7 = (int)jarg7; + result = (uint8_t *)wrap_WebPEncodeLosslessRGBA((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7); + jresult = SWIG_JavaArrayOutUint8(jenv, result, FillMeInAsSizeCannotBeDeterminedAutomatically); + SWIG_JavaArrayArgoutUint8(jenv, jarr1, arg1, jarg1); + { + jint jvalue = (jint)temp4; + (*jenv)->SetIntArrayRegion(jenv, jarg4, 0, 1, &jvalue); + } + free(arg1); + + + + free(result); + return jresult; +} + + +SWIGEXPORT jbyteArray JNICALL Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessBGRA(JNIEnv *jenv, jclass jcls, jbyteArray jarg1, jint jarg2, jint jarg3, jintArray jarg4, jint jarg5, jint jarg6, jint jarg7) { + jbyteArray jresult = 0 ; + uint8_t *arg1 = (uint8_t *) 0 ; + int *arg2 = (int *) 0 ; + int *arg3 = (int *) 0 ; + int *arg4 = (int *) 0 ; + int arg5 ; + int arg6 ; + int arg7 ; + jbyte *jarr1 ; + int temp4 ; + uint8_t *result = 0 ; + + (void)jenv; + (void)jcls; + if (!SWIG_JavaArrayInUint8(jenv, &jarr1, &arg1, jarg1)) return 0; + arg2 = (int *)&jarg2; + arg3 = (int *)&jarg3; + { + if (!jarg4) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); + return 0; + } + if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) { + SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); + return 0; + } + arg4 = &temp4; + } + arg5 = (int)jarg5; + arg6 = (int)jarg6; + arg7 = (int)jarg7; + result = (uint8_t *)wrap_WebPEncodeLosslessBGRA((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7); + jresult = SWIG_JavaArrayOutUint8(jenv, result, FillMeInAsSizeCannotBeDeterminedAutomatically); + SWIG_JavaArrayArgoutUint8(jenv, jarr1, arg1, jarg1); + { + jint jvalue = (jint)temp4; + (*jenv)->SetIntArrayRegion(jenv, jarg4, 0, 1, &jvalue); + } + free(arg1); + + + + free(result); + return jresult; +} + + +#ifdef __cplusplus +} +#endif + diff --git a/third-party/webp/libwebp/swig/libwebp_python_wrap.c b/third-party/webp/libwebp/swig/libwebp_python_wrap.c new file mode 100644 index 0000000000..3aa27285e8 --- /dev/null +++ b/third-party/webp/libwebp/swig/libwebp_python_wrap.c @@ -0,0 +1,5628 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 3.0.12 + * + * This file is not intended to be easily readable and contains a number of + * coding conventions designed to improve portability and efficiency. Do not make + * changes to this file unless you know what you are doing--modify the SWIG + * interface file instead. + * ----------------------------------------------------------------------------- */ + +#define SWIG_PYTHON_STRICT_BYTE_CHAR + + + +#ifndef SWIGPYTHON +#define SWIGPYTHON +#endif + +#define SWIG_PYTHON_DIRECTOR_NO_VTABLE + +/* ----------------------------------------------------------------------------- + * This section contains generic SWIG labels for method/variable + * declarations/attributes, and other compiler dependent labels. + * ----------------------------------------------------------------------------- */ + +/* template workaround for compilers that cannot correctly implement the C++ standard */ +#ifndef SWIGTEMPLATEDISAMBIGUATOR +# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560) +# define SWIGTEMPLATEDISAMBIGUATOR template +# elif defined(__HP_aCC) +/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */ +/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */ +# define SWIGTEMPLATEDISAMBIGUATOR template +# else +# define SWIGTEMPLATEDISAMBIGUATOR +# endif +#endif + +/* inline attribute */ +#ifndef SWIGINLINE +# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__)) +# define SWIGINLINE inline +# else +# define SWIGINLINE +# endif +#endif + +/* attribute recognised by some compilers to avoid 'unused' warnings */ +#ifndef SWIGUNUSED +# if defined(__GNUC__) +# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +# elif defined(__ICC) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +#endif + +#ifndef SWIG_MSC_UNSUPPRESS_4505 +# if defined(_MSC_VER) +# pragma warning(disable : 4505) /* unreferenced local function has been removed */ +# endif +#endif + +#ifndef SWIGUNUSEDPARM +# ifdef __cplusplus +# define SWIGUNUSEDPARM(p) +# else +# define SWIGUNUSEDPARM(p) p SWIGUNUSED +# endif +#endif + +/* internal SWIG method */ +#ifndef SWIGINTERN +# define SWIGINTERN static SWIGUNUSED +#endif + +/* internal inline SWIG method */ +#ifndef SWIGINTERNINLINE +# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE +#endif + +/* exporting methods */ +#if defined(__GNUC__) +# if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +# ifndef GCC_HASCLASSVISIBILITY +# define GCC_HASCLASSVISIBILITY +# endif +# endif +#endif + +#ifndef SWIGEXPORT +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# if defined(STATIC_LINKED) +# define SWIGEXPORT +# else +# define SWIGEXPORT __declspec(dllexport) +# endif +# else +# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY) +# define SWIGEXPORT __attribute__ ((visibility("default"))) +# else +# define SWIGEXPORT +# endif +# endif +#endif + +/* calling conventions for Windows */ +#ifndef SWIGSTDCALL +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# define SWIGSTDCALL __stdcall +# else +# define SWIGSTDCALL +# endif +#endif + +/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ +#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +# define _CRT_SECURE_NO_DEPRECATE +#endif + +/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */ +#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE) +# define _SCL_SECURE_NO_DEPRECATE +#endif + +/* Deal with Apple's deprecated 'AssertMacros.h' from Carbon-framework */ +#if defined(__APPLE__) && !defined(__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES) +# define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0 +#endif + +/* Intel's compiler complains if a variable which was never initialised is + * cast to void, which is a common idiom which we use to indicate that we + * are aware a variable isn't used. So we just silence that warning. + * See: https://github.com/swig/swig/issues/192 for more discussion. + */ +#ifdef __INTEL_COMPILER +# pragma warning disable 592 +#endif + + +#if defined(_DEBUG) && defined(SWIG_PYTHON_INTERPRETER_NO_DEBUG) +/* Use debug wrappers with the Python release dll */ +# undef _DEBUG +# include +# define _DEBUG +#else +# include +#endif + +/* ----------------------------------------------------------------------------- + * swigrun.swg + * + * This file contains generic C API SWIG runtime support for pointer + * type checking. + * ----------------------------------------------------------------------------- */ + +/* This should only be incremented when either the layout of swig_type_info changes, + or for whatever reason, the runtime changes incompatibly */ +#define SWIG_RUNTIME_VERSION "4" + +/* define SWIG_TYPE_TABLE_NAME as "SWIG_TYPE_TABLE" */ +#ifdef SWIG_TYPE_TABLE +# define SWIG_QUOTE_STRING(x) #x +# define SWIG_EXPAND_AND_QUOTE_STRING(x) SWIG_QUOTE_STRING(x) +# define SWIG_TYPE_TABLE_NAME SWIG_EXPAND_AND_QUOTE_STRING(SWIG_TYPE_TABLE) +#else +# define SWIG_TYPE_TABLE_NAME +#endif + +/* + You can use the SWIGRUNTIME and SWIGRUNTIMEINLINE macros for + creating a static or dynamic library from the SWIG runtime code. + In 99.9% of the cases, SWIG just needs to declare them as 'static'. + + But only do this if strictly necessary, ie, if you have problems + with your compiler or suchlike. +*/ + +#ifndef SWIGRUNTIME +# define SWIGRUNTIME SWIGINTERN +#endif + +#ifndef SWIGRUNTIMEINLINE +# define SWIGRUNTIMEINLINE SWIGRUNTIME SWIGINLINE +#endif + +/* Generic buffer size */ +#ifndef SWIG_BUFFER_SIZE +# define SWIG_BUFFER_SIZE 1024 +#endif + +/* Flags for pointer conversions */ +#define SWIG_POINTER_DISOWN 0x1 +#define SWIG_CAST_NEW_MEMORY 0x2 + +/* Flags for new pointer objects */ +#define SWIG_POINTER_OWN 0x1 + + +/* + Flags/methods for returning states. + + The SWIG conversion methods, as ConvertPtr, return an integer + that tells if the conversion was successful or not. And if not, + an error code can be returned (see swigerrors.swg for the codes). + + Use the following macros/flags to set or process the returning + states. + + In old versions of SWIG, code such as the following was usually written: + + if (SWIG_ConvertPtr(obj,vptr,ty.flags) != -1) { + // success code + } else { + //fail code + } + + Now you can be more explicit: + + int res = SWIG_ConvertPtr(obj,vptr,ty.flags); + if (SWIG_IsOK(res)) { + // success code + } else { + // fail code + } + + which is the same really, but now you can also do + + Type *ptr; + int res = SWIG_ConvertPtr(obj,(void **)(&ptr),ty.flags); + if (SWIG_IsOK(res)) { + // success code + if (SWIG_IsNewObj(res) { + ... + delete *ptr; + } else { + ... + } + } else { + // fail code + } + + I.e., now SWIG_ConvertPtr can return new objects and you can + identify the case and take care of the deallocation. Of course that + also requires SWIG_ConvertPtr to return new result values, such as + + int SWIG_ConvertPtr(obj, ptr,...) { + if () { + if () { + *ptr = ; + return SWIG_NEWOBJ; + } else { + *ptr = ; + return SWIG_OLDOBJ; + } + } else { + return SWIG_BADOBJ; + } + } + + Of course, returning the plain '0(success)/-1(fail)' still works, but you can be + more explicit by returning SWIG_BADOBJ, SWIG_ERROR or any of the + SWIG errors code. + + Finally, if the SWIG_CASTRANK_MODE is enabled, the result code + allows to return the 'cast rank', for example, if you have this + + int food(double) + int fooi(int); + + and you call + + food(1) // cast rank '1' (1 -> 1.0) + fooi(1) // cast rank '0' + + just use the SWIG_AddCast()/SWIG_CheckState() +*/ + +#define SWIG_OK (0) +#define SWIG_ERROR (-1) +#define SWIG_IsOK(r) (r >= 0) +#define SWIG_ArgError(r) ((r != SWIG_ERROR) ? r : SWIG_TypeError) + +/* The CastRankLimit says how many bits are used for the cast rank */ +#define SWIG_CASTRANKLIMIT (1 << 8) +/* The NewMask denotes the object was created (using new/malloc) */ +#define SWIG_NEWOBJMASK (SWIG_CASTRANKLIMIT << 1) +/* The TmpMask is for in/out typemaps that use temporal objects */ +#define SWIG_TMPOBJMASK (SWIG_NEWOBJMASK << 1) +/* Simple returning values */ +#define SWIG_BADOBJ (SWIG_ERROR) +#define SWIG_OLDOBJ (SWIG_OK) +#define SWIG_NEWOBJ (SWIG_OK | SWIG_NEWOBJMASK) +#define SWIG_TMPOBJ (SWIG_OK | SWIG_TMPOBJMASK) +/* Check, add and del mask methods */ +#define SWIG_AddNewMask(r) (SWIG_IsOK(r) ? (r | SWIG_NEWOBJMASK) : r) +#define SWIG_DelNewMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_NEWOBJMASK) : r) +#define SWIG_IsNewObj(r) (SWIG_IsOK(r) && (r & SWIG_NEWOBJMASK)) +#define SWIG_AddTmpMask(r) (SWIG_IsOK(r) ? (r | SWIG_TMPOBJMASK) : r) +#define SWIG_DelTmpMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_TMPOBJMASK) : r) +#define SWIG_IsTmpObj(r) (SWIG_IsOK(r) && (r & SWIG_TMPOBJMASK)) + +/* Cast-Rank Mode */ +#if defined(SWIG_CASTRANK_MODE) +# ifndef SWIG_TypeRank +# define SWIG_TypeRank unsigned long +# endif +# ifndef SWIG_MAXCASTRANK /* Default cast allowed */ +# define SWIG_MAXCASTRANK (2) +# endif +# define SWIG_CASTRANKMASK ((SWIG_CASTRANKLIMIT) -1) +# define SWIG_CastRank(r) (r & SWIG_CASTRANKMASK) +SWIGINTERNINLINE int SWIG_AddCast(int r) { + return SWIG_IsOK(r) ? ((SWIG_CastRank(r) < SWIG_MAXCASTRANK) ? (r + 1) : SWIG_ERROR) : r; +} +SWIGINTERNINLINE int SWIG_CheckState(int r) { + return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0; +} +#else /* no cast-rank mode */ +# define SWIG_AddCast(r) (r) +# define SWIG_CheckState(r) (SWIG_IsOK(r) ? 1 : 0) +#endif + + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void *(*swig_converter_func)(void *, int *); +typedef struct swig_type_info *(*swig_dycast_func)(void **); + +/* Structure to store information on one type */ +typedef struct swig_type_info { + const char *name; /* mangled name of this type */ + const char *str; /* human readable name of this type */ + swig_dycast_func dcast; /* dynamic cast function down a hierarchy */ + struct swig_cast_info *cast; /* linked list of types that can cast into this type */ + void *clientdata; /* language specific type data */ + int owndata; /* flag if the structure owns the clientdata */ +} swig_type_info; + +/* Structure to store a type and conversion function used for casting */ +typedef struct swig_cast_info { + swig_type_info *type; /* pointer to type that is equivalent to this type */ + swig_converter_func converter; /* function to cast the void pointers */ + struct swig_cast_info *next; /* pointer to next cast in linked list */ + struct swig_cast_info *prev; /* pointer to the previous cast */ +} swig_cast_info; + +/* Structure used to store module information + * Each module generates one structure like this, and the runtime collects + * all of these structures and stores them in a circularly linked list.*/ +typedef struct swig_module_info { + swig_type_info **types; /* Array of pointers to swig_type_info structures that are in this module */ + size_t size; /* Number of types in this module */ + struct swig_module_info *next; /* Pointer to next element in circularly linked list */ + swig_type_info **type_initial; /* Array of initially generated type structures */ + swig_cast_info **cast_initial; /* Array of initially generated casting structures */ + void *clientdata; /* Language specific module data */ +} swig_module_info; + +/* + Compare two type names skipping the space characters, therefore + "char*" == "char *" and "Class" == "Class", etc. + + Return 0 when the two name types are equivalent, as in + strncmp, but skipping ' '. +*/ +SWIGRUNTIME int +SWIG_TypeNameComp(const char *f1, const char *l1, + const char *f2, const char *l2) { + for (;(f1 != l1) && (f2 != l2); ++f1, ++f2) { + while ((*f1 == ' ') && (f1 != l1)) ++f1; + while ((*f2 == ' ') && (f2 != l2)) ++f2; + if (*f1 != *f2) return (*f1 > *f2) ? 1 : -1; + } + return (int)((l1 - f1) - (l2 - f2)); +} + +/* + Check type equivalence in a name list like ||... + Return 0 if equal, -1 if nb < tb, 1 if nb > tb +*/ +SWIGRUNTIME int +SWIG_TypeCmp(const char *nb, const char *tb) { + int equiv = 1; + const char* te = tb + strlen(tb); + const char* ne = nb; + while (equiv != 0 && *ne) { + for (nb = ne; *ne; ++ne) { + if (*ne == '|') break; + } + equiv = SWIG_TypeNameComp(nb, ne, tb, te); + if (*ne) ++ne; + } + return equiv; +} + +/* + Check type equivalence in a name list like ||... + Return 0 if not equal, 1 if equal +*/ +SWIGRUNTIME int +SWIG_TypeEquiv(const char *nb, const char *tb) { + return SWIG_TypeCmp(nb, tb) == 0 ? 1 : 0; +} + +/* + Check the typename +*/ +SWIGRUNTIME swig_cast_info * +SWIG_TypeCheck(const char *c, swig_type_info *ty) { + if (ty) { + swig_cast_info *iter = ty->cast; + while (iter) { + if (strcmp(iter->type->name, c) == 0) { + if (iter == ty->cast) + return iter; + /* Move iter to the top of the linked list */ + iter->prev->next = iter->next; + if (iter->next) + iter->next->prev = iter->prev; + iter->next = ty->cast; + iter->prev = 0; + if (ty->cast) ty->cast->prev = iter; + ty->cast = iter; + return iter; + } + iter = iter->next; + } + } + return 0; +} + +/* + Identical to SWIG_TypeCheck, except strcmp is replaced with a pointer comparison +*/ +SWIGRUNTIME swig_cast_info * +SWIG_TypeCheckStruct(swig_type_info *from, swig_type_info *ty) { + if (ty) { + swig_cast_info *iter = ty->cast; + while (iter) { + if (iter->type == from) { + if (iter == ty->cast) + return iter; + /* Move iter to the top of the linked list */ + iter->prev->next = iter->next; + if (iter->next) + iter->next->prev = iter->prev; + iter->next = ty->cast; + iter->prev = 0; + if (ty->cast) ty->cast->prev = iter; + ty->cast = iter; + return iter; + } + iter = iter->next; + } + } + return 0; +} + +/* + Cast a pointer up an inheritance hierarchy +*/ +SWIGRUNTIMEINLINE void * +SWIG_TypeCast(swig_cast_info *ty, void *ptr, int *newmemory) { + return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr, newmemory); +} + +/* + Dynamic pointer casting. Down an inheritance hierarchy +*/ +SWIGRUNTIME swig_type_info * +SWIG_TypeDynamicCast(swig_type_info *ty, void **ptr) { + swig_type_info *lastty = ty; + if (!ty || !ty->dcast) return ty; + while (ty && (ty->dcast)) { + ty = (*ty->dcast)(ptr); + if (ty) lastty = ty; + } + return lastty; +} + +/* + Return the name associated with this type +*/ +SWIGRUNTIMEINLINE const char * +SWIG_TypeName(const swig_type_info *ty) { + return ty->name; +} + +/* + Return the pretty name associated with this type, + that is an unmangled type name in a form presentable to the user. +*/ +SWIGRUNTIME const char * +SWIG_TypePrettyName(const swig_type_info *type) { + /* The "str" field contains the equivalent pretty names of the + type, separated by vertical-bar characters. We choose + to print the last name, as it is often (?) the most + specific. */ + if (!type) return NULL; + if (type->str != NULL) { + const char *last_name = type->str; + const char *s; + for (s = type->str; *s; s++) + if (*s == '|') last_name = s+1; + return last_name; + } + else + return type->name; +} + +/* + Set the clientdata field for a type +*/ +SWIGRUNTIME void +SWIG_TypeClientData(swig_type_info *ti, void *clientdata) { + swig_cast_info *cast = ti->cast; + /* if (ti->clientdata == clientdata) return; */ + ti->clientdata = clientdata; + + while (cast) { + if (!cast->converter) { + swig_type_info *tc = cast->type; + if (!tc->clientdata) { + SWIG_TypeClientData(tc, clientdata); + } + } + cast = cast->next; + } +} +SWIGRUNTIME void +SWIG_TypeNewClientData(swig_type_info *ti, void *clientdata) { + SWIG_TypeClientData(ti, clientdata); + ti->owndata = 1; +} + +/* + Search for a swig_type_info structure only by mangled name + Search is a O(log #types) + + We start searching at module start, and finish searching when start == end. + Note: if start == end at the beginning of the function, we go all the way around + the circular list. +*/ +SWIGRUNTIME swig_type_info * +SWIG_MangledTypeQueryModule(swig_module_info *start, + swig_module_info *end, + const char *name) { + swig_module_info *iter = start; + do { + if (iter->size) { + size_t l = 0; + size_t r = iter->size - 1; + do { + /* since l+r >= 0, we can (>> 1) instead (/ 2) */ + size_t i = (l + r) >> 1; + const char *iname = iter->types[i]->name; + if (iname) { + int compare = strcmp(name, iname); + if (compare == 0) { + return iter->types[i]; + } else if (compare < 0) { + if (i) { + r = i - 1; + } else { + break; + } + } else if (compare > 0) { + l = i + 1; + } + } else { + break; /* should never happen */ + } + } while (l <= r); + } + iter = iter->next; + } while (iter != end); + return 0; +} + +/* + Search for a swig_type_info structure for either a mangled name or a human readable name. + It first searches the mangled names of the types, which is a O(log #types) + If a type is not found it then searches the human readable names, which is O(#types). + + We start searching at module start, and finish searching when start == end. + Note: if start == end at the beginning of the function, we go all the way around + the circular list. +*/ +SWIGRUNTIME swig_type_info * +SWIG_TypeQueryModule(swig_module_info *start, + swig_module_info *end, + const char *name) { + /* STEP 1: Search the name field using binary search */ + swig_type_info *ret = SWIG_MangledTypeQueryModule(start, end, name); + if (ret) { + return ret; + } else { + /* STEP 2: If the type hasn't been found, do a complete search + of the str field (the human readable name) */ + swig_module_info *iter = start; + do { + size_t i = 0; + for (; i < iter->size; ++i) { + if (iter->types[i]->str && (SWIG_TypeEquiv(iter->types[i]->str, name))) + return iter->types[i]; + } + iter = iter->next; + } while (iter != end); + } + + /* neither found a match */ + return 0; +} + +/* + Pack binary data into a string +*/ +SWIGRUNTIME char * +SWIG_PackData(char *c, void *ptr, size_t sz) { + static const char hex[17] = "0123456789abcdef"; + const unsigned char *u = (unsigned char *) ptr; + const unsigned char *eu = u + sz; + for (; u != eu; ++u) { + unsigned char uu = *u; + *(c++) = hex[(uu & 0xf0) >> 4]; + *(c++) = hex[uu & 0xf]; + } + return c; +} + +/* + Unpack binary data from a string +*/ +SWIGRUNTIME const char * +SWIG_UnpackData(const char *c, void *ptr, size_t sz) { + unsigned char *u = (unsigned char *) ptr; + const unsigned char *eu = u + sz; + for (; u != eu; ++u) { + char d = *(c++); + unsigned char uu; + if ((d >= '0') && (d <= '9')) + uu = (unsigned char)((d - '0') << 4); + else if ((d >= 'a') && (d <= 'f')) + uu = (unsigned char)((d - ('a'-10)) << 4); + else + return (char *) 0; + d = *(c++); + if ((d >= '0') && (d <= '9')) + uu |= (unsigned char)(d - '0'); + else if ((d >= 'a') && (d <= 'f')) + uu |= (unsigned char)(d - ('a'-10)); + else + return (char *) 0; + *u = uu; + } + return c; +} + +/* + Pack 'void *' into a string buffer. +*/ +SWIGRUNTIME char * +SWIG_PackVoidPtr(char *buff, void *ptr, const char *name, size_t bsz) { + char *r = buff; + if ((2*sizeof(void *) + 2) > bsz) return 0; + *(r++) = '_'; + r = SWIG_PackData(r,&ptr,sizeof(void *)); + if (strlen(name) + 1 > (bsz - (r - buff))) return 0; + strcpy(r,name); + return buff; +} + +SWIGRUNTIME const char * +SWIG_UnpackVoidPtr(const char *c, void **ptr, const char *name) { + if (*c != '_') { + if (strcmp(c,"NULL") == 0) { + *ptr = (void *) 0; + return name; + } else { + return 0; + } + } + return SWIG_UnpackData(++c,ptr,sizeof(void *)); +} + +SWIGRUNTIME char * +SWIG_PackDataName(char *buff, void *ptr, size_t sz, const char *name, size_t bsz) { + char *r = buff; + size_t lname = (name ? strlen(name) : 0); + if ((2*sz + 2 + lname) > bsz) return 0; + *(r++) = '_'; + r = SWIG_PackData(r,ptr,sz); + if (lname) { + strncpy(r,name,lname+1); + } else { + *r = 0; + } + return buff; +} + +SWIGRUNTIME const char * +SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) { + if (*c != '_') { + if (strcmp(c,"NULL") == 0) { + memset(ptr,0,sz); + return name; + } else { + return 0; + } + } + return SWIG_UnpackData(++c,ptr,sz); +} + +#ifdef __cplusplus +} +#endif + +/* Errors in SWIG */ +#define SWIG_UnknownError -1 +#define SWIG_IOError -2 +#define SWIG_RuntimeError -3 +#define SWIG_IndexError -4 +#define SWIG_TypeError -5 +#define SWIG_DivisionByZero -6 +#define SWIG_OverflowError -7 +#define SWIG_SyntaxError -8 +#define SWIG_ValueError -9 +#define SWIG_SystemError -10 +#define SWIG_AttributeError -11 +#define SWIG_MemoryError -12 +#define SWIG_NullReferenceError -13 + + + +/* Compatibility macros for Python 3 */ +#if PY_VERSION_HEX >= 0x03000000 + +#define PyClass_Check(obj) PyObject_IsInstance(obj, (PyObject *)&PyType_Type) +#define PyInt_Check(x) PyLong_Check(x) +#define PyInt_AsLong(x) PyLong_AsLong(x) +#define PyInt_FromLong(x) PyLong_FromLong(x) +#define PyInt_FromSize_t(x) PyLong_FromSize_t(x) +#define PyString_Check(name) PyBytes_Check(name) +#define PyString_FromString(x) PyUnicode_FromString(x) +#define PyString_FromStringAndSize(x, y) PyBytes_FromStringAndSize(x, y) +#define PyString_Format(fmt, args) PyUnicode_Format(fmt, args) +#define PyString_AsString(str) PyBytes_AsString(str) +#define PyString_Size(str) PyBytes_Size(str) +#define PyString_InternFromString(key) PyUnicode_InternFromString(key) +#define Py_TPFLAGS_HAVE_CLASS Py_TPFLAGS_BASETYPE +#define PyString_AS_STRING(x) PyUnicode_AS_STRING(x) +#define _PyLong_FromSsize_t(x) PyLong_FromSsize_t(x) + +#endif + +#ifndef Py_TYPE +# define Py_TYPE(op) ((op)->ob_type) +#endif + +/* SWIG APIs for compatibility of both Python 2 & 3 */ + +#if PY_VERSION_HEX >= 0x03000000 +# define SWIG_Python_str_FromFormat PyUnicode_FromFormat +#else +# define SWIG_Python_str_FromFormat PyString_FromFormat +#endif + + +/* Warning: This function will allocate a new string in Python 3, + * so please call SWIG_Python_str_DelForPy3(x) to free the space. + */ +SWIGINTERN char* +SWIG_Python_str_AsChar(PyObject *str) +{ +#if PY_VERSION_HEX >= 0x03000000 + char *cstr; + char *newstr; + Py_ssize_t len; + str = PyUnicode_AsUTF8String(str); + PyBytes_AsStringAndSize(str, &cstr, &len); + newstr = (char *) malloc(len+1); + memcpy(newstr, cstr, len+1); + Py_XDECREF(str); + return newstr; +#else + return PyString_AsString(str); +#endif +} + +#if PY_VERSION_HEX >= 0x03000000 +# define SWIG_Python_str_DelForPy3(x) free( (void*) (x) ) +#else +# define SWIG_Python_str_DelForPy3(x) +#endif + + +SWIGINTERN PyObject* +SWIG_Python_str_FromChar(const char *c) +{ +#if PY_VERSION_HEX >= 0x03000000 + return PyUnicode_FromString(c); +#else + return PyString_FromString(c); +#endif +} + +/* Add PyOS_snprintf for old Pythons */ +#if PY_VERSION_HEX < 0x02020000 +# if defined(_MSC_VER) || defined(__BORLANDC__) || defined(_WATCOM) +# define PyOS_snprintf _snprintf +# else +# define PyOS_snprintf snprintf +# endif +#endif + +/* A crude PyString_FromFormat implementation for old Pythons */ +#if PY_VERSION_HEX < 0x02020000 + +#ifndef SWIG_PYBUFFER_SIZE +# define SWIG_PYBUFFER_SIZE 1024 +#endif + +static PyObject * +PyString_FromFormat(const char *fmt, ...) { + va_list ap; + char buf[SWIG_PYBUFFER_SIZE * 2]; + int res; + va_start(ap, fmt); + res = vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + return (res < 0 || res >= (int)sizeof(buf)) ? 0 : PyString_FromString(buf); +} +#endif + +#ifndef PyObject_DEL +# define PyObject_DEL PyObject_Del +#endif + +/* A crude PyExc_StopIteration exception for old Pythons */ +#if PY_VERSION_HEX < 0x02020000 +# ifndef PyExc_StopIteration +# define PyExc_StopIteration PyExc_RuntimeError +# endif +# ifndef PyObject_GenericGetAttr +# define PyObject_GenericGetAttr 0 +# endif +#endif + +/* Py_NotImplemented is defined in 2.1 and up. */ +#if PY_VERSION_HEX < 0x02010000 +# ifndef Py_NotImplemented +# define Py_NotImplemented PyExc_RuntimeError +# endif +#endif + +/* A crude PyString_AsStringAndSize implementation for old Pythons */ +#if PY_VERSION_HEX < 0x02010000 +# ifndef PyString_AsStringAndSize +# define PyString_AsStringAndSize(obj, s, len) {*s = PyString_AsString(obj); *len = *s ? strlen(*s) : 0;} +# endif +#endif + +/* PySequence_Size for old Pythons */ +#if PY_VERSION_HEX < 0x02000000 +# ifndef PySequence_Size +# define PySequence_Size PySequence_Length +# endif +#endif + +/* PyBool_FromLong for old Pythons */ +#if PY_VERSION_HEX < 0x02030000 +static +PyObject *PyBool_FromLong(long ok) +{ + PyObject *result = ok ? Py_True : Py_False; + Py_INCREF(result); + return result; +} +#endif + +/* Py_ssize_t for old Pythons */ +/* This code is as recommended by: */ +/* http://www.python.org/dev/peps/pep-0353/#conversion-guidelines */ +#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) +typedef int Py_ssize_t; +# define PY_SSIZE_T_MAX INT_MAX +# define PY_SSIZE_T_MIN INT_MIN +typedef inquiry lenfunc; +typedef intargfunc ssizeargfunc; +typedef intintargfunc ssizessizeargfunc; +typedef intobjargproc ssizeobjargproc; +typedef intintobjargproc ssizessizeobjargproc; +typedef getreadbufferproc readbufferproc; +typedef getwritebufferproc writebufferproc; +typedef getsegcountproc segcountproc; +typedef getcharbufferproc charbufferproc; +static long PyNumber_AsSsize_t (PyObject *x, void *SWIGUNUSEDPARM(exc)) +{ + long result = 0; + PyObject *i = PyNumber_Int(x); + if (i) { + result = PyInt_AsLong(i); + Py_DECREF(i); + } + return result; +} +#endif + +#if PY_VERSION_HEX < 0x02050000 +#define PyInt_FromSize_t(x) PyInt_FromLong((long)x) +#endif + +#if PY_VERSION_HEX < 0x02040000 +#define Py_VISIT(op) \ + do { \ + if (op) { \ + int vret = visit((op), arg); \ + if (vret) \ + return vret; \ + } \ + } while (0) +#endif + +#if PY_VERSION_HEX < 0x02030000 +typedef struct { + PyTypeObject type; + PyNumberMethods as_number; + PyMappingMethods as_mapping; + PySequenceMethods as_sequence; + PyBufferProcs as_buffer; + PyObject *name, *slots; +} PyHeapTypeObject; +#endif + +#if PY_VERSION_HEX < 0x02030000 +typedef destructor freefunc; +#endif + +#if ((PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 6) || \ + (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION > 0) || \ + (PY_MAJOR_VERSION > 3)) +# define SWIGPY_USE_CAPSULE +# define SWIGPY_CAPSULE_NAME ((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer_capsule" SWIG_TYPE_TABLE_NAME) +#endif + +#if PY_VERSION_HEX < 0x03020000 +#define PyDescr_TYPE(x) (((PyDescrObject *)(x))->d_type) +#define PyDescr_NAME(x) (((PyDescrObject *)(x))->d_name) +#define Py_hash_t long +#endif + +/* ----------------------------------------------------------------------------- + * error manipulation + * ----------------------------------------------------------------------------- */ + +SWIGRUNTIME PyObject* +SWIG_Python_ErrorType(int code) { + PyObject* type = 0; + switch(code) { + case SWIG_MemoryError: + type = PyExc_MemoryError; + break; + case SWIG_IOError: + type = PyExc_IOError; + break; + case SWIG_RuntimeError: + type = PyExc_RuntimeError; + break; + case SWIG_IndexError: + type = PyExc_IndexError; + break; + case SWIG_TypeError: + type = PyExc_TypeError; + break; + case SWIG_DivisionByZero: + type = PyExc_ZeroDivisionError; + break; + case SWIG_OverflowError: + type = PyExc_OverflowError; + break; + case SWIG_SyntaxError: + type = PyExc_SyntaxError; + break; + case SWIG_ValueError: + type = PyExc_ValueError; + break; + case SWIG_SystemError: + type = PyExc_SystemError; + break; + case SWIG_AttributeError: + type = PyExc_AttributeError; + break; + default: + type = PyExc_RuntimeError; + } + return type; +} + + +SWIGRUNTIME void +SWIG_Python_AddErrorMsg(const char* mesg) +{ + PyObject *type = 0; + PyObject *value = 0; + PyObject *traceback = 0; + + if (PyErr_Occurred()) PyErr_Fetch(&type, &value, &traceback); + if (value) { + char *tmp; + PyObject *old_str = PyObject_Str(value); + PyErr_Clear(); + Py_XINCREF(type); + + PyErr_Format(type, "%s %s", tmp = SWIG_Python_str_AsChar(old_str), mesg); + SWIG_Python_str_DelForPy3(tmp); + Py_DECREF(old_str); + Py_DECREF(value); + } else { + PyErr_SetString(PyExc_RuntimeError, mesg); + } +} + +#if defined(SWIG_PYTHON_NO_THREADS) +# if defined(SWIG_PYTHON_THREADS) +# undef SWIG_PYTHON_THREADS +# endif +#endif +#if defined(SWIG_PYTHON_THREADS) /* Threading support is enabled */ +# if !defined(SWIG_PYTHON_USE_GIL) && !defined(SWIG_PYTHON_NO_USE_GIL) +# if (PY_VERSION_HEX >= 0x02030000) /* For 2.3 or later, use the PyGILState calls */ +# define SWIG_PYTHON_USE_GIL +# endif +# endif +# if defined(SWIG_PYTHON_USE_GIL) /* Use PyGILState threads calls */ +# ifndef SWIG_PYTHON_INITIALIZE_THREADS +# define SWIG_PYTHON_INITIALIZE_THREADS PyEval_InitThreads() +# endif +# ifdef __cplusplus /* C++ code */ + class SWIG_Python_Thread_Block { + bool status; + PyGILState_STATE state; + public: + void end() { if (status) { PyGILState_Release(state); status = false;} } + SWIG_Python_Thread_Block() : status(true), state(PyGILState_Ensure()) {} + ~SWIG_Python_Thread_Block() { end(); } + }; + class SWIG_Python_Thread_Allow { + bool status; + PyThreadState *save; + public: + void end() { if (status) { PyEval_RestoreThread(save); status = false; }} + SWIG_Python_Thread_Allow() : status(true), save(PyEval_SaveThread()) {} + ~SWIG_Python_Thread_Allow() { end(); } + }; +# define SWIG_PYTHON_THREAD_BEGIN_BLOCK SWIG_Python_Thread_Block _swig_thread_block +# define SWIG_PYTHON_THREAD_END_BLOCK _swig_thread_block.end() +# define SWIG_PYTHON_THREAD_BEGIN_ALLOW SWIG_Python_Thread_Allow _swig_thread_allow +# define SWIG_PYTHON_THREAD_END_ALLOW _swig_thread_allow.end() +# else /* C code */ +# define SWIG_PYTHON_THREAD_BEGIN_BLOCK PyGILState_STATE _swig_thread_block = PyGILState_Ensure() +# define SWIG_PYTHON_THREAD_END_BLOCK PyGILState_Release(_swig_thread_block) +# define SWIG_PYTHON_THREAD_BEGIN_ALLOW PyThreadState *_swig_thread_allow = PyEval_SaveThread() +# define SWIG_PYTHON_THREAD_END_ALLOW PyEval_RestoreThread(_swig_thread_allow) +# endif +# else /* Old thread way, not implemented, user must provide it */ +# if !defined(SWIG_PYTHON_INITIALIZE_THREADS) +# define SWIG_PYTHON_INITIALIZE_THREADS +# endif +# if !defined(SWIG_PYTHON_THREAD_BEGIN_BLOCK) +# define SWIG_PYTHON_THREAD_BEGIN_BLOCK +# endif +# if !defined(SWIG_PYTHON_THREAD_END_BLOCK) +# define SWIG_PYTHON_THREAD_END_BLOCK +# endif +# if !defined(SWIG_PYTHON_THREAD_BEGIN_ALLOW) +# define SWIG_PYTHON_THREAD_BEGIN_ALLOW +# endif +# if !defined(SWIG_PYTHON_THREAD_END_ALLOW) +# define SWIG_PYTHON_THREAD_END_ALLOW +# endif +# endif +#else /* No thread support */ +# define SWIG_PYTHON_INITIALIZE_THREADS +# define SWIG_PYTHON_THREAD_BEGIN_BLOCK +# define SWIG_PYTHON_THREAD_END_BLOCK +# define SWIG_PYTHON_THREAD_BEGIN_ALLOW +# define SWIG_PYTHON_THREAD_END_ALLOW +#endif + +/* ----------------------------------------------------------------------------- + * Python API portion that goes into the runtime + * ----------------------------------------------------------------------------- */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ----------------------------------------------------------------------------- + * Constant declarations + * ----------------------------------------------------------------------------- */ + +/* Constant Types */ +#define SWIG_PY_POINTER 4 +#define SWIG_PY_BINARY 5 + +/* Constant information structure */ +typedef struct swig_const_info { + int type; + char *name; + long lvalue; + double dvalue; + void *pvalue; + swig_type_info **ptype; +} swig_const_info; + + +/* ----------------------------------------------------------------------------- + * Wrapper of PyInstanceMethod_New() used in Python 3 + * It is exported to the generated module, used for -fastproxy + * ----------------------------------------------------------------------------- */ +#if PY_VERSION_HEX >= 0x03000000 +SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *func) +{ + return PyInstanceMethod_New(func); +} +#else +SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *SWIGUNUSEDPARM(func)) +{ + return NULL; +} +#endif + +#ifdef __cplusplus +} +#endif + + +/* ----------------------------------------------------------------------------- + * pyrun.swg + * + * This file contains the runtime support for Python modules + * and includes code for managing global variables and pointer + * type checking. + * + * ----------------------------------------------------------------------------- */ + +/* Common SWIG API */ + +/* for raw pointers */ +#define SWIG_Python_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, 0) +#define SWIG_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtr(obj, pptr, type, flags) +#define SWIG_ConvertPtrAndOwn(obj,pptr,type,flags,own) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, own) + +#ifdef SWIGPYTHON_BUILTIN +#define SWIG_NewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(self, ptr, type, flags) +#else +#define SWIG_NewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(NULL, ptr, type, flags) +#endif + +#define SWIG_InternalNewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(NULL, ptr, type, flags) + +#define SWIG_CheckImplicit(ty) SWIG_Python_CheckImplicit(ty) +#define SWIG_AcquirePtr(ptr, src) SWIG_Python_AcquirePtr(ptr, src) +#define swig_owntype int + +/* for raw packed data */ +#define SWIG_ConvertPacked(obj, ptr, sz, ty) SWIG_Python_ConvertPacked(obj, ptr, sz, ty) +#define SWIG_NewPackedObj(ptr, sz, type) SWIG_Python_NewPackedObj(ptr, sz, type) + +/* for class or struct pointers */ +#define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_ConvertPtr(obj, pptr, type, flags) +#define SWIG_NewInstanceObj(ptr, type, flags) SWIG_NewPointerObj(ptr, type, flags) + +/* for C or C++ function pointers */ +#define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_Python_ConvertFunctionPtr(obj, pptr, type) +#define SWIG_NewFunctionPtrObj(ptr, type) SWIG_Python_NewPointerObj(NULL, ptr, type, 0) + +/* for C++ member pointers, ie, member methods */ +#define SWIG_ConvertMember(obj, ptr, sz, ty) SWIG_Python_ConvertPacked(obj, ptr, sz, ty) +#define SWIG_NewMemberObj(ptr, sz, type) SWIG_Python_NewPackedObj(ptr, sz, type) + + +/* Runtime API */ + +#define SWIG_GetModule(clientdata) SWIG_Python_GetModule(clientdata) +#define SWIG_SetModule(clientdata, pointer) SWIG_Python_SetModule(pointer) +#define SWIG_NewClientData(obj) SwigPyClientData_New(obj) + +#define SWIG_SetErrorObj SWIG_Python_SetErrorObj +#define SWIG_SetErrorMsg SWIG_Python_SetErrorMsg +#define SWIG_ErrorType(code) SWIG_Python_ErrorType(code) +#define SWIG_Error(code, msg) SWIG_Python_SetErrorMsg(SWIG_ErrorType(code), msg) +#define SWIG_fail goto fail + + +/* Runtime API implementation */ + +/* Error manipulation */ + +SWIGINTERN void +SWIG_Python_SetErrorObj(PyObject *errtype, PyObject *obj) { + SWIG_PYTHON_THREAD_BEGIN_BLOCK; + PyErr_SetObject(errtype, obj); + Py_DECREF(obj); + SWIG_PYTHON_THREAD_END_BLOCK; +} + +SWIGINTERN void +SWIG_Python_SetErrorMsg(PyObject *errtype, const char *msg) { + SWIG_PYTHON_THREAD_BEGIN_BLOCK; + PyErr_SetString(errtype, msg); + SWIG_PYTHON_THREAD_END_BLOCK; +} + +#define SWIG_Python_Raise(obj, type, desc) SWIG_Python_SetErrorObj(SWIG_Python_ExceptionType(desc), obj) + +/* Set a constant value */ + +#if defined(SWIGPYTHON_BUILTIN) + +SWIGINTERN void +SwigPyBuiltin_AddPublicSymbol(PyObject *seq, const char *key) { + PyObject *s = PyString_InternFromString(key); + PyList_Append(seq, s); + Py_DECREF(s); +} + +SWIGINTERN void +SWIG_Python_SetConstant(PyObject *d, PyObject *public_interface, const char *name, PyObject *obj) { +#if PY_VERSION_HEX < 0x02030000 + PyDict_SetItemString(d, (char *)name, obj); +#else + PyDict_SetItemString(d, name, obj); +#endif + Py_DECREF(obj); + if (public_interface) + SwigPyBuiltin_AddPublicSymbol(public_interface, name); +} + +#else + +SWIGINTERN void +SWIG_Python_SetConstant(PyObject *d, const char *name, PyObject *obj) { +#if PY_VERSION_HEX < 0x02030000 + PyDict_SetItemString(d, (char *)name, obj); +#else + PyDict_SetItemString(d, name, obj); +#endif + Py_DECREF(obj); +} + +#endif + +/* Append a value to the result obj */ + +SWIGINTERN PyObject* +SWIG_Python_AppendOutput(PyObject* result, PyObject* obj) { +#if !defined(SWIG_PYTHON_OUTPUT_TUPLE) + if (!result) { + result = obj; + } else if (result == Py_None) { + Py_DECREF(result); + result = obj; + } else { + if (!PyList_Check(result)) { + PyObject *o2 = result; + result = PyList_New(1); + PyList_SetItem(result, 0, o2); + } + PyList_Append(result,obj); + Py_DECREF(obj); + } + return result; +#else + PyObject* o2; + PyObject* o3; + if (!result) { + result = obj; + } else if (result == Py_None) { + Py_DECREF(result); + result = obj; + } else { + if (!PyTuple_Check(result)) { + o2 = result; + result = PyTuple_New(1); + PyTuple_SET_ITEM(result, 0, o2); + } + o3 = PyTuple_New(1); + PyTuple_SET_ITEM(o3, 0, obj); + o2 = result; + result = PySequence_Concat(o2, o3); + Py_DECREF(o2); + Py_DECREF(o3); + } + return result; +#endif +} + +/* Unpack the argument tuple */ + +SWIGINTERN Py_ssize_t +SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, PyObject **objs) +{ + if (!args) { + if (!min && !max) { + return 1; + } else { + PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got none", + name, (min == max ? "" : "at least "), (int)min); + return 0; + } + } + if (!PyTuple_Check(args)) { + if (min <= 1 && max >= 1) { + Py_ssize_t i; + objs[0] = args; + for (i = 1; i < max; ++i) { + objs[i] = 0; + } + return 2; + } + PyErr_SetString(PyExc_SystemError, "UnpackTuple() argument list is not a tuple"); + return 0; + } else { + Py_ssize_t l = PyTuple_GET_SIZE(args); + if (l < min) { + PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", + name, (min == max ? "" : "at least "), (int)min, (int)l); + return 0; + } else if (l > max) { + PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", + name, (min == max ? "" : "at most "), (int)max, (int)l); + return 0; + } else { + Py_ssize_t i; + for (i = 0; i < l; ++i) { + objs[i] = PyTuple_GET_ITEM(args, i); + } + for (; l < max; ++l) { + objs[l] = 0; + } + return i + 1; + } + } +} + +/* A functor is a function object with one single object argument */ +#if PY_VERSION_HEX >= 0x02020000 +#define SWIG_Python_CallFunctor(functor, obj) PyObject_CallFunctionObjArgs(functor, obj, NULL); +#else +#define SWIG_Python_CallFunctor(functor, obj) PyObject_CallFunction(functor, "O", obj); +#endif + +/* + Helper for static pointer initialization for both C and C++ code, for example + static PyObject *SWIG_STATIC_POINTER(MyVar) = NewSomething(...); +*/ +#ifdef __cplusplus +#define SWIG_STATIC_POINTER(var) var +#else +#define SWIG_STATIC_POINTER(var) var = 0; if (!var) var +#endif + +/* ----------------------------------------------------------------------------- + * Pointer declarations + * ----------------------------------------------------------------------------- */ + +/* Flags for new pointer objects */ +#define SWIG_POINTER_NOSHADOW (SWIG_POINTER_OWN << 1) +#define SWIG_POINTER_NEW (SWIG_POINTER_NOSHADOW | SWIG_POINTER_OWN) + +#define SWIG_POINTER_IMPLICIT_CONV (SWIG_POINTER_DISOWN << 1) + +#define SWIG_BUILTIN_TP_INIT (SWIG_POINTER_OWN << 2) +#define SWIG_BUILTIN_INIT (SWIG_BUILTIN_TP_INIT | SWIG_POINTER_OWN) + +#ifdef __cplusplus +extern "C" { +#endif + +/* How to access Py_None */ +#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# ifndef SWIG_PYTHON_NO_BUILD_NONE +# ifndef SWIG_PYTHON_BUILD_NONE +# define SWIG_PYTHON_BUILD_NONE +# endif +# endif +#endif + +#ifdef SWIG_PYTHON_BUILD_NONE +# ifdef Py_None +# undef Py_None +# define Py_None SWIG_Py_None() +# endif +SWIGRUNTIMEINLINE PyObject * +_SWIG_Py_None(void) +{ + PyObject *none = Py_BuildValue((char*)""); + Py_DECREF(none); + return none; +} +SWIGRUNTIME PyObject * +SWIG_Py_None(void) +{ + static PyObject *SWIG_STATIC_POINTER(none) = _SWIG_Py_None(); + return none; +} +#endif + +/* The python void return value */ + +SWIGRUNTIMEINLINE PyObject * +SWIG_Py_Void(void) +{ + PyObject *none = Py_None; + Py_INCREF(none); + return none; +} + +/* SwigPyClientData */ + +typedef struct { + PyObject *klass; + PyObject *newraw; + PyObject *newargs; + PyObject *destroy; + int delargs; + int implicitconv; + PyTypeObject *pytype; +} SwigPyClientData; + +SWIGRUNTIMEINLINE int +SWIG_Python_CheckImplicit(swig_type_info *ty) +{ + SwigPyClientData *data = (SwigPyClientData *)ty->clientdata; + return data ? data->implicitconv : 0; +} + +SWIGRUNTIMEINLINE PyObject * +SWIG_Python_ExceptionType(swig_type_info *desc) { + SwigPyClientData *data = desc ? (SwigPyClientData *) desc->clientdata : 0; + PyObject *klass = data ? data->klass : 0; + return (klass ? klass : PyExc_RuntimeError); +} + + +SWIGRUNTIME SwigPyClientData * +SwigPyClientData_New(PyObject* obj) +{ + if (!obj) { + return 0; + } else { + SwigPyClientData *data = (SwigPyClientData *)malloc(sizeof(SwigPyClientData)); + /* the klass element */ + data->klass = obj; + Py_INCREF(data->klass); + /* the newraw method and newargs arguments used to create a new raw instance */ + if (PyClass_Check(obj)) { + data->newraw = 0; + data->newargs = obj; + Py_INCREF(obj); + } else { +#if (PY_VERSION_HEX < 0x02020000) + data->newraw = 0; +#else + data->newraw = PyObject_GetAttrString(data->klass, (char *)"__new__"); +#endif + if (data->newraw) { + Py_INCREF(data->newraw); + data->newargs = PyTuple_New(1); + PyTuple_SetItem(data->newargs, 0, obj); + } else { + data->newargs = obj; + } + Py_INCREF(data->newargs); + } + /* the destroy method, aka as the C++ delete method */ + data->destroy = PyObject_GetAttrString(data->klass, (char *)"__swig_destroy__"); + if (PyErr_Occurred()) { + PyErr_Clear(); + data->destroy = 0; + } + if (data->destroy) { + int flags; + Py_INCREF(data->destroy); + flags = PyCFunction_GET_FLAGS(data->destroy); +#ifdef METH_O + data->delargs = !(flags & (METH_O)); +#else + data->delargs = 0; +#endif + } else { + data->delargs = 0; + } + data->implicitconv = 0; + data->pytype = 0; + return data; + } +} + +SWIGRUNTIME void +SwigPyClientData_Del(SwigPyClientData *data) { + Py_XDECREF(data->newraw); + Py_XDECREF(data->newargs); + Py_XDECREF(data->destroy); +} + +/* =============== SwigPyObject =====================*/ + +typedef struct { + PyObject_HEAD + void *ptr; + swig_type_info *ty; + int own; + PyObject *next; +#ifdef SWIGPYTHON_BUILTIN + PyObject *dict; +#endif +} SwigPyObject; + + +#ifdef SWIGPYTHON_BUILTIN + +SWIGRUNTIME PyObject * +SwigPyObject_get___dict__(PyObject *v, PyObject *SWIGUNUSEDPARM(args)) +{ + SwigPyObject *sobj = (SwigPyObject *)v; + + if (!sobj->dict) + sobj->dict = PyDict_New(); + + Py_INCREF(sobj->dict); + return sobj->dict; +} + +#endif + +SWIGRUNTIME PyObject * +SwigPyObject_long(SwigPyObject *v) +{ + return PyLong_FromVoidPtr(v->ptr); +} + +SWIGRUNTIME PyObject * +SwigPyObject_format(const char* fmt, SwigPyObject *v) +{ + PyObject *res = NULL; + PyObject *args = PyTuple_New(1); + if (args) { + if (PyTuple_SetItem(args, 0, SwigPyObject_long(v)) == 0) { + PyObject *ofmt = SWIG_Python_str_FromChar(fmt); + if (ofmt) { +#if PY_VERSION_HEX >= 0x03000000 + res = PyUnicode_Format(ofmt,args); +#else + res = PyString_Format(ofmt,args); +#endif + Py_DECREF(ofmt); + } + Py_DECREF(args); + } + } + return res; +} + +SWIGRUNTIME PyObject * +SwigPyObject_oct(SwigPyObject *v) +{ + return SwigPyObject_format("%o",v); +} + +SWIGRUNTIME PyObject * +SwigPyObject_hex(SwigPyObject *v) +{ + return SwigPyObject_format("%x",v); +} + +SWIGRUNTIME PyObject * +#ifdef METH_NOARGS +SwigPyObject_repr(SwigPyObject *v) +#else +SwigPyObject_repr(SwigPyObject *v, PyObject *args) +#endif +{ + const char *name = SWIG_TypePrettyName(v->ty); + PyObject *repr = SWIG_Python_str_FromFormat("", (name ? name : "unknown"), (void *)v); + if (v->next) { +# ifdef METH_NOARGS + PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next); +# else + PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next, args); +# endif +# if PY_VERSION_HEX >= 0x03000000 + PyObject *joined = PyUnicode_Concat(repr, nrep); + Py_DecRef(repr); + Py_DecRef(nrep); + repr = joined; +# else + PyString_ConcatAndDel(&repr,nrep); +# endif + } + return repr; +} + +/* We need a version taking two PyObject* parameters so it's a valid + * PyCFunction to use in swigobject_methods[]. */ +SWIGRUNTIME PyObject * +SwigPyObject_repr2(PyObject *v, PyObject *SWIGUNUSEDPARM(args)) +{ + return SwigPyObject_repr((SwigPyObject*)v); +} + +SWIGRUNTIME int +SwigPyObject_compare(SwigPyObject *v, SwigPyObject *w) +{ + void *i = v->ptr; + void *j = w->ptr; + return (i < j) ? -1 : ((i > j) ? 1 : 0); +} + +/* Added for Python 3.x, would it also be useful for Python 2.x? */ +SWIGRUNTIME PyObject* +SwigPyObject_richcompare(SwigPyObject *v, SwigPyObject *w, int op) +{ + PyObject* res; + if( op != Py_EQ && op != Py_NE ) { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + res = PyBool_FromLong( (SwigPyObject_compare(v, w)==0) == (op == Py_EQ) ? 1 : 0); + return res; +} + + +SWIGRUNTIME PyTypeObject* SwigPyObject_TypeOnce(void); + +#ifdef SWIGPYTHON_BUILTIN +static swig_type_info *SwigPyObject_stype = 0; +SWIGRUNTIME PyTypeObject* +SwigPyObject_type(void) { + SwigPyClientData *cd; + assert(SwigPyObject_stype); + cd = (SwigPyClientData*) SwigPyObject_stype->clientdata; + assert(cd); + assert(cd->pytype); + return cd->pytype; +} +#else +SWIGRUNTIME PyTypeObject* +SwigPyObject_type(void) { + static PyTypeObject *SWIG_STATIC_POINTER(type) = SwigPyObject_TypeOnce(); + return type; +} +#endif + +SWIGRUNTIMEINLINE int +SwigPyObject_Check(PyObject *op) { +#ifdef SWIGPYTHON_BUILTIN + PyTypeObject *target_tp = SwigPyObject_type(); + if (PyType_IsSubtype(op->ob_type, target_tp)) + return 1; + return (strcmp(op->ob_type->tp_name, "SwigPyObject") == 0); +#else + return (Py_TYPE(op) == SwigPyObject_type()) + || (strcmp(Py_TYPE(op)->tp_name,"SwigPyObject") == 0); +#endif +} + +SWIGRUNTIME PyObject * +SwigPyObject_New(void *ptr, swig_type_info *ty, int own); + +SWIGRUNTIME void +SwigPyObject_dealloc(PyObject *v) +{ + SwigPyObject *sobj = (SwigPyObject *) v; + PyObject *next = sobj->next; + if (sobj->own == SWIG_POINTER_OWN) { + swig_type_info *ty = sobj->ty; + SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0; + PyObject *destroy = data ? data->destroy : 0; + if (destroy) { + /* destroy is always a VARARGS method */ + PyObject *res; + + /* PyObject_CallFunction() has the potential to silently drop + the active active exception. In cases of unnamed temporary + variable or where we just finished iterating over a generator + StopIteration will be active right now, and this needs to + remain true upon return from SwigPyObject_dealloc. So save + and restore. */ + + PyObject *val = NULL, *type = NULL, *tb = NULL; + PyErr_Fetch(&val, &type, &tb); + + if (data->delargs) { + /* we need to create a temporary object to carry the destroy operation */ + PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0); + res = SWIG_Python_CallFunctor(destroy, tmp); + Py_DECREF(tmp); + } else { + PyCFunction meth = PyCFunction_GET_FUNCTION(destroy); + PyObject *mself = PyCFunction_GET_SELF(destroy); + res = ((*meth)(mself, v)); + } + if (!res) + PyErr_WriteUnraisable(destroy); + + PyErr_Restore(val, type, tb); + + Py_XDECREF(res); + } +#if !defined(SWIG_PYTHON_SILENT_MEMLEAK) + else { + const char *name = SWIG_TypePrettyName(ty); + printf("swig/python detected a memory leak of type '%s', no destructor found.\n", (name ? name : "unknown")); + } +#endif + } + Py_XDECREF(next); + PyObject_DEL(v); +} + +SWIGRUNTIME PyObject* +SwigPyObject_append(PyObject* v, PyObject* next) +{ + SwigPyObject *sobj = (SwigPyObject *) v; +#ifndef METH_O + PyObject *tmp = 0; + if (!PyArg_ParseTuple(next,(char *)"O:append", &tmp)) return NULL; + next = tmp; +#endif + if (!SwigPyObject_Check(next)) { + PyErr_SetString(PyExc_TypeError, "Attempt to append a non SwigPyObject"); + return NULL; + } + sobj->next = next; + Py_INCREF(next); + return SWIG_Py_Void(); +} + +SWIGRUNTIME PyObject* +SwigPyObject_next(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) +{ + SwigPyObject *sobj = (SwigPyObject *) v; + if (sobj->next) { + Py_INCREF(sobj->next); + return sobj->next; + } else { + return SWIG_Py_Void(); + } +} + +SWIGINTERN PyObject* +#ifdef METH_NOARGS +SwigPyObject_disown(PyObject *v) +#else +SwigPyObject_disown(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) +#endif +{ + SwigPyObject *sobj = (SwigPyObject *)v; + sobj->own = 0; + return SWIG_Py_Void(); +} + +SWIGINTERN PyObject* +#ifdef METH_NOARGS +SwigPyObject_acquire(PyObject *v) +#else +SwigPyObject_acquire(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) +#endif +{ + SwigPyObject *sobj = (SwigPyObject *)v; + sobj->own = SWIG_POINTER_OWN; + return SWIG_Py_Void(); +} + +#ifdef METH_NOARGS +static PyObject* +SwigPyObject_disown2(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) +{ + return SwigPyObject_disown(v); +} + +static PyObject* +SwigPyObject_acquire2(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) +{ + return SwigPyObject_acquire(v); +} +#endif + +SWIGINTERN PyObject* +SwigPyObject_own(PyObject *v, PyObject *args) +{ + PyObject *val = 0; +#if (PY_VERSION_HEX < 0x02020000) + if (!PyArg_ParseTuple(args,(char *)"|O:own",&val)) +#elif (PY_VERSION_HEX < 0x02050000) + if (!PyArg_UnpackTuple(args, (char *)"own", 0, 1, &val)) +#else + if (!PyArg_UnpackTuple(args, "own", 0, 1, &val)) +#endif + { + return NULL; + } + else + { + SwigPyObject *sobj = (SwigPyObject *)v; + PyObject *obj = PyBool_FromLong(sobj->own); + if (val) { +#ifdef METH_NOARGS + if (PyObject_IsTrue(val)) { + SwigPyObject_acquire(v); + } else { + SwigPyObject_disown(v); + } +#else + if (PyObject_IsTrue(val)) { + SwigPyObject_acquire(v,args); + } else { + SwigPyObject_disown(v,args); + } +#endif + } + return obj; + } +} + +#ifdef METH_O +static PyMethodDef +swigobject_methods[] = { + {(char *)"disown", (PyCFunction)SwigPyObject_disown2, METH_NOARGS, (char *)"releases ownership of the pointer"}, + {(char *)"acquire", (PyCFunction)SwigPyObject_acquire2,METH_NOARGS, (char *)"acquires ownership of the pointer"}, + {(char *)"own", (PyCFunction)SwigPyObject_own, METH_VARARGS, (char *)"returns/sets ownership of the pointer"}, + {(char *)"append", (PyCFunction)SwigPyObject_append, METH_O, (char *)"appends another 'this' object"}, + {(char *)"next", (PyCFunction)SwigPyObject_next, METH_NOARGS, (char *)"returns the next 'this' object"}, + {(char *)"__repr__",(PyCFunction)SwigPyObject_repr2, METH_NOARGS, (char *)"returns object representation"}, + {0, 0, 0, 0} +}; +#else +static PyMethodDef +swigobject_methods[] = { + {(char *)"disown", (PyCFunction)SwigPyObject_disown, METH_VARARGS, (char *)"releases ownership of the pointer"}, + {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_VARARGS, (char *)"acquires ownership of the pointer"}, + {(char *)"own", (PyCFunction)SwigPyObject_own, METH_VARARGS, (char *)"returns/sets ownership of the pointer"}, + {(char *)"append", (PyCFunction)SwigPyObject_append, METH_VARARGS, (char *)"appends another 'this' object"}, + {(char *)"next", (PyCFunction)SwigPyObject_next, METH_VARARGS, (char *)"returns the next 'this' object"}, + {(char *)"__repr__",(PyCFunction)SwigPyObject_repr, METH_VARARGS, (char *)"returns object representation"}, + {0, 0, 0, 0} +}; +#endif + +#if PY_VERSION_HEX < 0x02020000 +SWIGINTERN PyObject * +SwigPyObject_getattr(SwigPyObject *sobj,char *name) +{ + return Py_FindMethod(swigobject_methods, (PyObject *)sobj, name); +} +#endif + +SWIGRUNTIME PyTypeObject* +SwigPyObject_TypeOnce(void) { + static char swigobject_doc[] = "Swig object carries a C/C++ instance pointer"; + + static PyNumberMethods SwigPyObject_as_number = { + (binaryfunc)0, /*nb_add*/ + (binaryfunc)0, /*nb_subtract*/ + (binaryfunc)0, /*nb_multiply*/ + /* nb_divide removed in Python 3 */ +#if PY_VERSION_HEX < 0x03000000 + (binaryfunc)0, /*nb_divide*/ +#endif + (binaryfunc)0, /*nb_remainder*/ + (binaryfunc)0, /*nb_divmod*/ + (ternaryfunc)0,/*nb_power*/ + (unaryfunc)0, /*nb_negative*/ + (unaryfunc)0, /*nb_positive*/ + (unaryfunc)0, /*nb_absolute*/ + (inquiry)0, /*nb_nonzero*/ + 0, /*nb_invert*/ + 0, /*nb_lshift*/ + 0, /*nb_rshift*/ + 0, /*nb_and*/ + 0, /*nb_xor*/ + 0, /*nb_or*/ +#if PY_VERSION_HEX < 0x03000000 + 0, /*nb_coerce*/ +#endif + (unaryfunc)SwigPyObject_long, /*nb_int*/ +#if PY_VERSION_HEX < 0x03000000 + (unaryfunc)SwigPyObject_long, /*nb_long*/ +#else + 0, /*nb_reserved*/ +#endif + (unaryfunc)0, /*nb_float*/ +#if PY_VERSION_HEX < 0x03000000 + (unaryfunc)SwigPyObject_oct, /*nb_oct*/ + (unaryfunc)SwigPyObject_hex, /*nb_hex*/ +#endif +#if PY_VERSION_HEX >= 0x03050000 /* 3.5 */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_matrix_multiply */ +#elif PY_VERSION_HEX >= 0x03000000 /* 3.0 */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index, nb_inplace_divide removed */ +#elif PY_VERSION_HEX >= 0x02050000 /* 2.5.0 */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index */ +#elif PY_VERSION_HEX >= 0x02020000 /* 2.2.0 */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_true_divide */ +#elif PY_VERSION_HEX >= 0x02000000 /* 2.0.0 */ + 0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_or */ +#endif + }; + + static PyTypeObject swigpyobject_type; + static int type_init = 0; + if (!type_init) { + const PyTypeObject tmp = { +#if PY_VERSION_HEX >= 0x03000000 + PyVarObject_HEAD_INIT(NULL, 0) +#else + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ +#endif + (char *)"SwigPyObject", /* tp_name */ + sizeof(SwigPyObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)SwigPyObject_dealloc, /* tp_dealloc */ + 0, /* tp_print */ +#if PY_VERSION_HEX < 0x02020000 + (getattrfunc)SwigPyObject_getattr, /* tp_getattr */ +#else + (getattrfunc)0, /* tp_getattr */ +#endif + (setattrfunc)0, /* tp_setattr */ +#if PY_VERSION_HEX >= 0x03000000 + 0, /* tp_reserved in 3.0.1, tp_compare in 3.0.0 but not used */ +#else + (cmpfunc)SwigPyObject_compare, /* tp_compare */ +#endif + (reprfunc)SwigPyObject_repr, /* tp_repr */ + &SwigPyObject_as_number, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + (hashfunc)0, /* tp_hash */ + (ternaryfunc)0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + swigobject_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + (richcmpfunc)SwigPyObject_richcompare,/* tp_richcompare */ + 0, /* tp_weaklistoffset */ +#if PY_VERSION_HEX >= 0x02020000 + 0, /* tp_iter */ + 0, /* tp_iternext */ + swigobject_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ + 0, /* tp_mro */ + 0, /* tp_cache */ + 0, /* tp_subclasses */ + 0, /* tp_weaklist */ +#endif +#if PY_VERSION_HEX >= 0x02030000 + 0, /* tp_del */ +#endif +#if PY_VERSION_HEX >= 0x02060000 + 0, /* tp_version_tag */ +#endif +#if PY_VERSION_HEX >= 0x03040000 + 0, /* tp_finalize */ +#endif +#ifdef COUNT_ALLOCS + 0, /* tp_allocs */ + 0, /* tp_frees */ + 0, /* tp_maxalloc */ +#if PY_VERSION_HEX >= 0x02050000 + 0, /* tp_prev */ +#endif + 0 /* tp_next */ +#endif + }; + swigpyobject_type = tmp; + type_init = 1; +#if PY_VERSION_HEX < 0x02020000 + swigpyobject_type.ob_type = &PyType_Type; +#else + if (PyType_Ready(&swigpyobject_type) < 0) + return NULL; +#endif + } + return &swigpyobject_type; +} + +SWIGRUNTIME PyObject * +SwigPyObject_New(void *ptr, swig_type_info *ty, int own) +{ + SwigPyObject *sobj = PyObject_NEW(SwigPyObject, SwigPyObject_type()); + if (sobj) { + sobj->ptr = ptr; + sobj->ty = ty; + sobj->own = own; + sobj->next = 0; + } + return (PyObject *)sobj; +} + +/* ----------------------------------------------------------------------------- + * Implements a simple Swig Packed type, and use it instead of string + * ----------------------------------------------------------------------------- */ + +typedef struct { + PyObject_HEAD + void *pack; + swig_type_info *ty; + size_t size; +} SwigPyPacked; + +SWIGRUNTIME int +SwigPyPacked_print(SwigPyPacked *v, FILE *fp, int SWIGUNUSEDPARM(flags)) +{ + char result[SWIG_BUFFER_SIZE]; + fputs("pack, v->size, 0, sizeof(result))) { + fputs("at ", fp); + fputs(result, fp); + } + fputs(v->ty->name,fp); + fputs(">", fp); + return 0; +} + +SWIGRUNTIME PyObject * +SwigPyPacked_repr(SwigPyPacked *v) +{ + char result[SWIG_BUFFER_SIZE]; + if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))) { + return SWIG_Python_str_FromFormat("", result, v->ty->name); + } else { + return SWIG_Python_str_FromFormat("", v->ty->name); + } +} + +SWIGRUNTIME PyObject * +SwigPyPacked_str(SwigPyPacked *v) +{ + char result[SWIG_BUFFER_SIZE]; + if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))){ + return SWIG_Python_str_FromFormat("%s%s", result, v->ty->name); + } else { + return SWIG_Python_str_FromChar(v->ty->name); + } +} + +SWIGRUNTIME int +SwigPyPacked_compare(SwigPyPacked *v, SwigPyPacked *w) +{ + size_t i = v->size; + size_t j = w->size; + int s = (i < j) ? -1 : ((i > j) ? 1 : 0); + return s ? s : strncmp((char *)v->pack, (char *)w->pack, 2*v->size); +} + +SWIGRUNTIME PyTypeObject* SwigPyPacked_TypeOnce(void); + +SWIGRUNTIME PyTypeObject* +SwigPyPacked_type(void) { + static PyTypeObject *SWIG_STATIC_POINTER(type) = SwigPyPacked_TypeOnce(); + return type; +} + +SWIGRUNTIMEINLINE int +SwigPyPacked_Check(PyObject *op) { + return ((op)->ob_type == SwigPyPacked_TypeOnce()) + || (strcmp((op)->ob_type->tp_name,"SwigPyPacked") == 0); +} + +SWIGRUNTIME void +SwigPyPacked_dealloc(PyObject *v) +{ + if (SwigPyPacked_Check(v)) { + SwigPyPacked *sobj = (SwigPyPacked *) v; + free(sobj->pack); + } + PyObject_DEL(v); +} + +SWIGRUNTIME PyTypeObject* +SwigPyPacked_TypeOnce(void) { + static char swigpacked_doc[] = "Swig object carries a C/C++ instance pointer"; + static PyTypeObject swigpypacked_type; + static int type_init = 0; + if (!type_init) { + const PyTypeObject tmp = { +#if PY_VERSION_HEX>=0x03000000 + PyVarObject_HEAD_INIT(NULL, 0) +#else + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ +#endif + (char *)"SwigPyPacked", /* tp_name */ + sizeof(SwigPyPacked), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)SwigPyPacked_dealloc, /* tp_dealloc */ + (printfunc)SwigPyPacked_print, /* tp_print */ + (getattrfunc)0, /* tp_getattr */ + (setattrfunc)0, /* tp_setattr */ +#if PY_VERSION_HEX>=0x03000000 + 0, /* tp_reserved in 3.0.1 */ +#else + (cmpfunc)SwigPyPacked_compare, /* tp_compare */ +#endif + (reprfunc)SwigPyPacked_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + (hashfunc)0, /* tp_hash */ + (ternaryfunc)0, /* tp_call */ + (reprfunc)SwigPyPacked_str, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + swigpacked_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ +#if PY_VERSION_HEX >= 0x02020000 + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ + 0, /* tp_mro */ + 0, /* tp_cache */ + 0, /* tp_subclasses */ + 0, /* tp_weaklist */ +#endif +#if PY_VERSION_HEX >= 0x02030000 + 0, /* tp_del */ +#endif +#if PY_VERSION_HEX >= 0x02060000 + 0, /* tp_version_tag */ +#endif +#if PY_VERSION_HEX >= 0x03040000 + 0, /* tp_finalize */ +#endif +#ifdef COUNT_ALLOCS + 0, /* tp_allocs */ + 0, /* tp_frees */ + 0, /* tp_maxalloc */ +#if PY_VERSION_HEX >= 0x02050000 + 0, /* tp_prev */ +#endif + 0 /* tp_next */ +#endif + }; + swigpypacked_type = tmp; + type_init = 1; +#if PY_VERSION_HEX < 0x02020000 + swigpypacked_type.ob_type = &PyType_Type; +#else + if (PyType_Ready(&swigpypacked_type) < 0) + return NULL; +#endif + } + return &swigpypacked_type; +} + +SWIGRUNTIME PyObject * +SwigPyPacked_New(void *ptr, size_t size, swig_type_info *ty) +{ + SwigPyPacked *sobj = PyObject_NEW(SwigPyPacked, SwigPyPacked_type()); + if (sobj) { + void *pack = malloc(size); + if (pack) { + memcpy(pack, ptr, size); + sobj->pack = pack; + sobj->ty = ty; + sobj->size = size; + } else { + PyObject_DEL((PyObject *) sobj); + sobj = 0; + } + } + return (PyObject *) sobj; +} + +SWIGRUNTIME swig_type_info * +SwigPyPacked_UnpackData(PyObject *obj, void *ptr, size_t size) +{ + if (SwigPyPacked_Check(obj)) { + SwigPyPacked *sobj = (SwigPyPacked *)obj; + if (sobj->size != size) return 0; + memcpy(ptr, sobj->pack, size); + return sobj->ty; + } else { + return 0; + } +} + +/* ----------------------------------------------------------------------------- + * pointers/data manipulation + * ----------------------------------------------------------------------------- */ + +SWIGRUNTIMEINLINE PyObject * +_SWIG_This(void) +{ + return SWIG_Python_str_FromChar("this"); +} + +static PyObject *swig_this = NULL; + +SWIGRUNTIME PyObject * +SWIG_This(void) +{ + if (swig_this == NULL) + swig_this = _SWIG_This(); + return swig_this; +} + +/* #define SWIG_PYTHON_SLOW_GETSET_THIS */ + +/* TODO: I don't know how to implement the fast getset in Python 3 right now */ +#if PY_VERSION_HEX>=0x03000000 +#define SWIG_PYTHON_SLOW_GETSET_THIS +#endif + +SWIGRUNTIME SwigPyObject * +SWIG_Python_GetSwigThis(PyObject *pyobj) +{ + PyObject *obj; + + if (SwigPyObject_Check(pyobj)) + return (SwigPyObject *) pyobj; + +#ifdef SWIGPYTHON_BUILTIN + (void)obj; +# ifdef PyWeakref_CheckProxy + if (PyWeakref_CheckProxy(pyobj)) { + pyobj = PyWeakref_GET_OBJECT(pyobj); + if (pyobj && SwigPyObject_Check(pyobj)) + return (SwigPyObject*) pyobj; + } +# endif + return NULL; +#else + + obj = 0; + +#if (!defined(SWIG_PYTHON_SLOW_GETSET_THIS) && (PY_VERSION_HEX >= 0x02030000)) + if (PyInstance_Check(pyobj)) { + obj = _PyInstance_Lookup(pyobj, SWIG_This()); + } else { + PyObject **dictptr = _PyObject_GetDictPtr(pyobj); + if (dictptr != NULL) { + PyObject *dict = *dictptr; + obj = dict ? PyDict_GetItem(dict, SWIG_This()) : 0; + } else { +#ifdef PyWeakref_CheckProxy + if (PyWeakref_CheckProxy(pyobj)) { + PyObject *wobj = PyWeakref_GET_OBJECT(pyobj); + return wobj ? SWIG_Python_GetSwigThis(wobj) : 0; + } +#endif + obj = PyObject_GetAttr(pyobj,SWIG_This()); + if (obj) { + Py_DECREF(obj); + } else { + if (PyErr_Occurred()) PyErr_Clear(); + return 0; + } + } + } +#else + obj = PyObject_GetAttr(pyobj,SWIG_This()); + if (obj) { + Py_DECREF(obj); + } else { + if (PyErr_Occurred()) PyErr_Clear(); + return 0; + } +#endif + if (obj && !SwigPyObject_Check(obj)) { + /* a PyObject is called 'this', try to get the 'real this' + SwigPyObject from it */ + return SWIG_Python_GetSwigThis(obj); + } + return (SwigPyObject *)obj; +#endif +} + +/* Acquire a pointer value */ + +SWIGRUNTIME int +SWIG_Python_AcquirePtr(PyObject *obj, int own) { + if (own == SWIG_POINTER_OWN) { + SwigPyObject *sobj = SWIG_Python_GetSwigThis(obj); + if (sobj) { + int oldown = sobj->own; + sobj->own = own; + return oldown; + } + } + return 0; +} + +/* Convert a pointer value */ + +SWIGRUNTIME int +SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int flags, int *own) { + int res; + SwigPyObject *sobj; + int implicit_conv = (flags & SWIG_POINTER_IMPLICIT_CONV) != 0; + + if (!obj) + return SWIG_ERROR; + if (obj == Py_None && !implicit_conv) { + if (ptr) + *ptr = 0; + return SWIG_OK; + } + + res = SWIG_ERROR; + + sobj = SWIG_Python_GetSwigThis(obj); + if (own) + *own = 0; + while (sobj) { + void *vptr = sobj->ptr; + if (ty) { + swig_type_info *to = sobj->ty; + if (to == ty) { + /* no type cast needed */ + if (ptr) *ptr = vptr; + break; + } else { + swig_cast_info *tc = SWIG_TypeCheck(to->name,ty); + if (!tc) { + sobj = (SwigPyObject *)sobj->next; + } else { + if (ptr) { + int newmemory = 0; + *ptr = SWIG_TypeCast(tc,vptr,&newmemory); + if (newmemory == SWIG_CAST_NEW_MEMORY) { + assert(own); /* badly formed typemap which will lead to a memory leak - it must set and use own to delete *ptr */ + if (own) + *own = *own | SWIG_CAST_NEW_MEMORY; + } + } + break; + } + } + } else { + if (ptr) *ptr = vptr; + break; + } + } + if (sobj) { + if (own) + *own = *own | sobj->own; + if (flags & SWIG_POINTER_DISOWN) { + sobj->own = 0; + } + res = SWIG_OK; + } else { + if (implicit_conv) { + SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0; + if (data && !data->implicitconv) { + PyObject *klass = data->klass; + if (klass) { + PyObject *impconv; + data->implicitconv = 1; /* avoid recursion and call 'explicit' constructors*/ + impconv = SWIG_Python_CallFunctor(klass, obj); + data->implicitconv = 0; + if (PyErr_Occurred()) { + PyErr_Clear(); + impconv = 0; + } + if (impconv) { + SwigPyObject *iobj = SWIG_Python_GetSwigThis(impconv); + if (iobj) { + void *vptr; + res = SWIG_Python_ConvertPtrAndOwn((PyObject*)iobj, &vptr, ty, 0, 0); + if (SWIG_IsOK(res)) { + if (ptr) { + *ptr = vptr; + /* transfer the ownership to 'ptr' */ + iobj->own = 0; + res = SWIG_AddCast(res); + res = SWIG_AddNewMask(res); + } else { + res = SWIG_AddCast(res); + } + } + } + Py_DECREF(impconv); + } + } + } + } + if (!SWIG_IsOK(res) && obj == Py_None) { + if (ptr) + *ptr = 0; + if (PyErr_Occurred()) + PyErr_Clear(); + res = SWIG_OK; + } + } + return res; +} + +/* Convert a function ptr value */ + +SWIGRUNTIME int +SWIG_Python_ConvertFunctionPtr(PyObject *obj, void **ptr, swig_type_info *ty) { + if (!PyCFunction_Check(obj)) { + return SWIG_ConvertPtr(obj, ptr, ty, 0); + } else { + void *vptr = 0; + + /* here we get the method pointer for callbacks */ + const char *doc = (((PyCFunctionObject *)obj) -> m_ml -> ml_doc); + const char *desc = doc ? strstr(doc, "swig_ptr: ") : 0; + if (desc) + desc = ty ? SWIG_UnpackVoidPtr(desc + 10, &vptr, ty->name) : 0; + if (!desc) + return SWIG_ERROR; + if (ty) { + swig_cast_info *tc = SWIG_TypeCheck(desc,ty); + if (tc) { + int newmemory = 0; + *ptr = SWIG_TypeCast(tc,vptr,&newmemory); + assert(!newmemory); /* newmemory handling not yet implemented */ + } else { + return SWIG_ERROR; + } + } else { + *ptr = vptr; + } + return SWIG_OK; + } +} + +/* Convert a packed value value */ + +SWIGRUNTIME int +SWIG_Python_ConvertPacked(PyObject *obj, void *ptr, size_t sz, swig_type_info *ty) { + swig_type_info *to = SwigPyPacked_UnpackData(obj, ptr, sz); + if (!to) return SWIG_ERROR; + if (ty) { + if (to != ty) { + /* check type cast? */ + swig_cast_info *tc = SWIG_TypeCheck(to->name,ty); + if (!tc) return SWIG_ERROR; + } + } + return SWIG_OK; +} + +/* ----------------------------------------------------------------------------- + * Create a new pointer object + * ----------------------------------------------------------------------------- */ + +/* + Create a new instance object, without calling __init__, and set the + 'this' attribute. +*/ + +SWIGRUNTIME PyObject* +SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this) +{ +#if (PY_VERSION_HEX >= 0x02020000) + PyObject *inst = 0; + PyObject *newraw = data->newraw; + if (newraw) { + inst = PyObject_Call(newraw, data->newargs, NULL); + if (inst) { +#if !defined(SWIG_PYTHON_SLOW_GETSET_THIS) + PyObject **dictptr = _PyObject_GetDictPtr(inst); + if (dictptr != NULL) { + PyObject *dict = *dictptr; + if (dict == NULL) { + dict = PyDict_New(); + *dictptr = dict; + PyDict_SetItem(dict, SWIG_This(), swig_this); + } + } +#else + PyObject *key = SWIG_This(); + PyObject_SetAttr(inst, key, swig_this); +#endif + } + } else { +#if PY_VERSION_HEX >= 0x03000000 + inst = ((PyTypeObject*) data->newargs)->tp_new((PyTypeObject*) data->newargs, Py_None, Py_None); + if (inst) { + PyObject_SetAttr(inst, SWIG_This(), swig_this); + Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG; + } +#else + PyObject *dict = PyDict_New(); + if (dict) { + PyDict_SetItem(dict, SWIG_This(), swig_this); + inst = PyInstance_NewRaw(data->newargs, dict); + Py_DECREF(dict); + } +#endif + } + return inst; +#else +#if (PY_VERSION_HEX >= 0x02010000) + PyObject *inst = 0; + PyObject *dict = PyDict_New(); + if (dict) { + PyDict_SetItem(dict, SWIG_This(), swig_this); + inst = PyInstance_NewRaw(data->newargs, dict); + Py_DECREF(dict); + } + return (PyObject *) inst; +#else + PyInstanceObject *inst = PyObject_NEW(PyInstanceObject, &PyInstance_Type); + if (inst == NULL) { + return NULL; + } + inst->in_class = (PyClassObject *)data->newargs; + Py_INCREF(inst->in_class); + inst->in_dict = PyDict_New(); + if (inst->in_dict == NULL) { + Py_DECREF(inst); + return NULL; + } +#ifdef Py_TPFLAGS_HAVE_WEAKREFS + inst->in_weakreflist = NULL; +#endif +#ifdef Py_TPFLAGS_GC + PyObject_GC_Init(inst); +#endif + PyDict_SetItem(inst->in_dict, SWIG_This(), swig_this); + return (PyObject *) inst; +#endif +#endif +} + +SWIGRUNTIME void +SWIG_Python_SetSwigThis(PyObject *inst, PyObject *swig_this) +{ + PyObject *dict; +#if (PY_VERSION_HEX >= 0x02020000) && !defined(SWIG_PYTHON_SLOW_GETSET_THIS) + PyObject **dictptr = _PyObject_GetDictPtr(inst); + if (dictptr != NULL) { + dict = *dictptr; + if (dict == NULL) { + dict = PyDict_New(); + *dictptr = dict; + } + PyDict_SetItem(dict, SWIG_This(), swig_this); + return; + } +#endif + dict = PyObject_GetAttrString(inst, (char*)"__dict__"); + PyDict_SetItem(dict, SWIG_This(), swig_this); + Py_DECREF(dict); +} + + +SWIGINTERN PyObject * +SWIG_Python_InitShadowInstance(PyObject *args) { + PyObject *obj[2]; + if (!SWIG_Python_UnpackTuple(args, "swiginit", 2, 2, obj)) { + return NULL; + } else { + SwigPyObject *sthis = SWIG_Python_GetSwigThis(obj[0]); + if (sthis) { + SwigPyObject_append((PyObject*) sthis, obj[1]); + } else { + SWIG_Python_SetSwigThis(obj[0], obj[1]); + } + return SWIG_Py_Void(); + } +} + +/* Create a new pointer object */ + +SWIGRUNTIME PyObject * +SWIG_Python_NewPointerObj(PyObject *self, void *ptr, swig_type_info *type, int flags) { + SwigPyClientData *clientdata; + PyObject * robj; + int own; + + if (!ptr) + return SWIG_Py_Void(); + + clientdata = type ? (SwigPyClientData *)(type->clientdata) : 0; + own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0; + if (clientdata && clientdata->pytype) { + SwigPyObject *newobj; + if (flags & SWIG_BUILTIN_TP_INIT) { + newobj = (SwigPyObject*) self; + if (newobj->ptr) { + PyObject *next_self = clientdata->pytype->tp_alloc(clientdata->pytype, 0); + while (newobj->next) + newobj = (SwigPyObject *) newobj->next; + newobj->next = next_self; + newobj = (SwigPyObject *)next_self; +#ifdef SWIGPYTHON_BUILTIN + newobj->dict = 0; +#endif + } + } else { + newobj = PyObject_New(SwigPyObject, clientdata->pytype); +#ifdef SWIGPYTHON_BUILTIN + newobj->dict = 0; +#endif + } + if (newobj) { + newobj->ptr = ptr; + newobj->ty = type; + newobj->own = own; + newobj->next = 0; + return (PyObject*) newobj; + } + return SWIG_Py_Void(); + } + + assert(!(flags & SWIG_BUILTIN_TP_INIT)); + + robj = SwigPyObject_New(ptr, type, own); + if (robj && clientdata && !(flags & SWIG_POINTER_NOSHADOW)) { + PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj); + Py_DECREF(robj); + robj = inst; + } + return robj; +} + +/* Create a new packed object */ + +SWIGRUNTIMEINLINE PyObject * +SWIG_Python_NewPackedObj(void *ptr, size_t sz, swig_type_info *type) { + return ptr ? SwigPyPacked_New((void *) ptr, sz, type) : SWIG_Py_Void(); +} + +/* -----------------------------------------------------------------------------* + * Get type list + * -----------------------------------------------------------------------------*/ + +#ifdef SWIG_LINK_RUNTIME +void *SWIG_ReturnGlobalTypeList(void *); +#endif + +SWIGRUNTIME swig_module_info * +SWIG_Python_GetModule(void *SWIGUNUSEDPARM(clientdata)) { + static void *type_pointer = (void *)0; + /* first check if module already created */ + if (!type_pointer) { +#ifdef SWIG_LINK_RUNTIME + type_pointer = SWIG_ReturnGlobalTypeList((void *)0); +#else +# ifdef SWIGPY_USE_CAPSULE + type_pointer = PyCapsule_Import(SWIGPY_CAPSULE_NAME, 0); +# else + type_pointer = PyCObject_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION, + (char*)"type_pointer" SWIG_TYPE_TABLE_NAME); +# endif + if (PyErr_Occurred()) { + PyErr_Clear(); + type_pointer = (void *)0; + } +#endif + } + return (swig_module_info *) type_pointer; +} + +#if PY_MAJOR_VERSION < 2 +/* PyModule_AddObject function was introduced in Python 2.0. The following function + is copied out of Python/modsupport.c in python version 2.3.4 */ +SWIGINTERN int +PyModule_AddObject(PyObject *m, char *name, PyObject *o) +{ + PyObject *dict; + if (!PyModule_Check(m)) { + PyErr_SetString(PyExc_TypeError, "PyModule_AddObject() needs module as first arg"); + return SWIG_ERROR; + } + if (!o) { + PyErr_SetString(PyExc_TypeError, "PyModule_AddObject() needs non-NULL value"); + return SWIG_ERROR; + } + + dict = PyModule_GetDict(m); + if (dict == NULL) { + /* Internal error -- modules must have a dict! */ + PyErr_Format(PyExc_SystemError, "module '%s' has no __dict__", + PyModule_GetName(m)); + return SWIG_ERROR; + } + if (PyDict_SetItemString(dict, name, o)) + return SWIG_ERROR; + Py_DECREF(o); + return SWIG_OK; +} +#endif + +SWIGRUNTIME void +#ifdef SWIGPY_USE_CAPSULE +SWIG_Python_DestroyModule(PyObject *obj) +#else +SWIG_Python_DestroyModule(void *vptr) +#endif +{ +#ifdef SWIGPY_USE_CAPSULE + swig_module_info *swig_module = (swig_module_info *) PyCapsule_GetPointer(obj, SWIGPY_CAPSULE_NAME); +#else + swig_module_info *swig_module = (swig_module_info *) vptr; +#endif + swig_type_info **types = swig_module->types; + size_t i; + for (i =0; i < swig_module->size; ++i) { + swig_type_info *ty = types[i]; + if (ty->owndata) { + SwigPyClientData *data = (SwigPyClientData *) ty->clientdata; + if (data) SwigPyClientData_Del(data); + } + } + Py_DECREF(SWIG_This()); + swig_this = NULL; +} + +SWIGRUNTIME void +SWIG_Python_SetModule(swig_module_info *swig_module) { +#if PY_VERSION_HEX >= 0x03000000 + /* Add a placeholder module object into sys.modules */ + PyObject *module = PyImport_AddModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION); +#else + static PyMethodDef swig_empty_runtime_method_table[] = { {NULL, NULL, 0, NULL} }; /* Sentinel */ + PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION, swig_empty_runtime_method_table); +#endif +#ifdef SWIGPY_USE_CAPSULE + PyObject *pointer = PyCapsule_New((void *) swig_module, SWIGPY_CAPSULE_NAME, SWIG_Python_DestroyModule); + if (pointer && module) { + PyModule_AddObject(module, (char*)"type_pointer_capsule" SWIG_TYPE_TABLE_NAME, pointer); + } else { + Py_XDECREF(pointer); + } +#else + PyObject *pointer = PyCObject_FromVoidPtr((void *) swig_module, SWIG_Python_DestroyModule); + if (pointer && module) { + PyModule_AddObject(module, (char*)"type_pointer" SWIG_TYPE_TABLE_NAME, pointer); + } else { + Py_XDECREF(pointer); + } +#endif +} + +/* The python cached type query */ +SWIGRUNTIME PyObject * +SWIG_Python_TypeCache(void) { + static PyObject *SWIG_STATIC_POINTER(cache) = PyDict_New(); + return cache; +} + +SWIGRUNTIME swig_type_info * +SWIG_Python_TypeQuery(const char *type) +{ + PyObject *cache = SWIG_Python_TypeCache(); + PyObject *key = SWIG_Python_str_FromChar(type); + PyObject *obj = PyDict_GetItem(cache, key); + swig_type_info *descriptor; + if (obj) { +#ifdef SWIGPY_USE_CAPSULE + descriptor = (swig_type_info *) PyCapsule_GetPointer(obj, NULL); +#else + descriptor = (swig_type_info *) PyCObject_AsVoidPtr(obj); +#endif + } else { + swig_module_info *swig_module = SWIG_GetModule(0); + descriptor = SWIG_TypeQueryModule(swig_module, swig_module, type); + if (descriptor) { +#ifdef SWIGPY_USE_CAPSULE + obj = PyCapsule_New((void*) descriptor, NULL, NULL); +#else + obj = PyCObject_FromVoidPtr(descriptor, NULL); +#endif + PyDict_SetItem(cache, key, obj); + Py_DECREF(obj); + } + } + Py_DECREF(key); + return descriptor; +} + +/* + For backward compatibility only +*/ +#define SWIG_POINTER_EXCEPTION 0 +#define SWIG_arg_fail(arg) SWIG_Python_ArgFail(arg) +#define SWIG_MustGetPtr(p, type, argnum, flags) SWIG_Python_MustGetPtr(p, type, argnum, flags) + +SWIGRUNTIME int +SWIG_Python_AddErrMesg(const char* mesg, int infront) +{ + if (PyErr_Occurred()) { + PyObject *type = 0; + PyObject *value = 0; + PyObject *traceback = 0; + PyErr_Fetch(&type, &value, &traceback); + if (value) { + char *tmp; + PyObject *old_str = PyObject_Str(value); + Py_XINCREF(type); + PyErr_Clear(); + if (infront) { + PyErr_Format(type, "%s %s", mesg, tmp = SWIG_Python_str_AsChar(old_str)); + } else { + PyErr_Format(type, "%s %s", tmp = SWIG_Python_str_AsChar(old_str), mesg); + } + SWIG_Python_str_DelForPy3(tmp); + Py_DECREF(old_str); + } + return 1; + } else { + return 0; + } +} + +SWIGRUNTIME int +SWIG_Python_ArgFail(int argnum) +{ + if (PyErr_Occurred()) { + /* add information about failing argument */ + char mesg[256]; + PyOS_snprintf(mesg, sizeof(mesg), "argument number %d:", argnum); + return SWIG_Python_AddErrMesg(mesg, 1); + } else { + return 0; + } +} + +SWIGRUNTIMEINLINE const char * +SwigPyObject_GetDesc(PyObject *self) +{ + SwigPyObject *v = (SwigPyObject *)self; + swig_type_info *ty = v ? v->ty : 0; + return ty ? ty->str : ""; +} + +SWIGRUNTIME void +SWIG_Python_TypeError(const char *type, PyObject *obj) +{ + if (type) { +#if defined(SWIG_COBJECT_TYPES) + if (obj && SwigPyObject_Check(obj)) { + const char *otype = (const char *) SwigPyObject_GetDesc(obj); + if (otype) { + PyErr_Format(PyExc_TypeError, "a '%s' is expected, 'SwigPyObject(%s)' is received", + type, otype); + return; + } + } else +#endif + { + const char *otype = (obj ? obj->ob_type->tp_name : 0); + if (otype) { + PyObject *str = PyObject_Str(obj); + const char *cstr = str ? SWIG_Python_str_AsChar(str) : 0; + if (cstr) { + PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s(%s)' is received", + type, otype, cstr); + SWIG_Python_str_DelForPy3(cstr); + } else { + PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s' is received", + type, otype); + } + Py_XDECREF(str); + return; + } + } + PyErr_Format(PyExc_TypeError, "a '%s' is expected", type); + } else { + PyErr_Format(PyExc_TypeError, "unexpected type is received"); + } +} + + +/* Convert a pointer value, signal an exception on a type mismatch */ +SWIGRUNTIME void * +SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int SWIGUNUSEDPARM(argnum), int flags) { + void *result; + if (SWIG_Python_ConvertPtr(obj, &result, ty, flags) == -1) { + PyErr_Clear(); +#if SWIG_POINTER_EXCEPTION + if (flags) { + SWIG_Python_TypeError(SWIG_TypePrettyName(ty), obj); + SWIG_Python_ArgFail(argnum); + } +#endif + } + return result; +} + +#ifdef SWIGPYTHON_BUILTIN +SWIGRUNTIME int +SWIG_Python_NonDynamicSetAttr(PyObject *obj, PyObject *name, PyObject *value) { + PyTypeObject *tp = obj->ob_type; + PyObject *descr; + PyObject *encoded_name; + descrsetfunc f; + int res = -1; + +# ifdef Py_USING_UNICODE + if (PyString_Check(name)) { + name = PyUnicode_Decode(PyString_AsString(name), PyString_Size(name), NULL, NULL); + if (!name) + return -1; + } else if (!PyUnicode_Check(name)) +# else + if (!PyString_Check(name)) +# endif + { + PyErr_Format(PyExc_TypeError, "attribute name must be string, not '%.200s'", name->ob_type->tp_name); + return -1; + } else { + Py_INCREF(name); + } + + if (!tp->tp_dict) { + if (PyType_Ready(tp) < 0) + goto done; + } + + descr = _PyType_Lookup(tp, name); + f = NULL; + if (descr != NULL) + f = descr->ob_type->tp_descr_set; + if (!f) { + if (PyString_Check(name)) { + encoded_name = name; + Py_INCREF(name); + } else { + encoded_name = PyUnicode_AsUTF8String(name); + } + PyErr_Format(PyExc_AttributeError, "'%.100s' object has no attribute '%.200s'", tp->tp_name, PyString_AsString(encoded_name)); + Py_DECREF(encoded_name); + } else { + res = f(descr, obj, value); + } + + done: + Py_DECREF(name); + return res; +} +#endif + + +#ifdef __cplusplus +} +#endif + + + +#define SWIG_exception_fail(code, msg) do { SWIG_Error(code, msg); SWIG_fail; } while(0) + +#define SWIG_contract_assert(expr, msg) if (!(expr)) { SWIG_Error(SWIG_RuntimeError, msg); SWIG_fail; } else + + + + #define SWIG_exception(code, msg) do { SWIG_Error(code, msg); SWIG_fail;; } while(0) + + +/* -------- TYPES TABLE (BEGIN) -------- */ + +#define SWIGTYPE_p_char swig_types[0] +#define SWIGTYPE_p_int swig_types[1] +#define SWIGTYPE_p_uint8_t swig_types[2] +static swig_type_info *swig_types[4]; +static swig_module_info swig_module = {swig_types, 3, 0, 0, 0, 0}; +#define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name) +#define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name) + +/* -------- TYPES TABLE (END) -------- */ + +#if (PY_VERSION_HEX <= 0x02000000) +# if !defined(SWIG_PYTHON_CLASSIC) +# error "This python version requires swig to be run with the '-classic' option" +# endif +#endif + +/*----------------------------------------------- + @(target):= _libwebp.so + ------------------------------------------------*/ +#if PY_VERSION_HEX >= 0x03000000 +# define SWIG_init PyInit__libwebp + +#else +# define SWIG_init init_libwebp + +#endif +#define SWIG_name "_libwebp" + +#define SWIGVERSION 0x030012 +#define SWIG_VERSION SWIGVERSION + + +#define SWIG_as_voidptr(a) (void *)((const void *)(a)) +#define SWIG_as_voidptrptr(a) ((void)SWIG_as_voidptr(*a),(void**)(a)) + + +SWIGINTERNINLINE PyObject* + SWIG_From_int (int value) +{ + return PyInt_FromLong((long) value); +} + + +SWIGINTERN swig_type_info* +SWIG_pchar_descriptor(void) +{ + static int init = 0; + static swig_type_info* info = 0; + if (!init) { + info = SWIG_TypeQuery("_p_char"); + init = 1; + } + return info; +} + + +SWIGINTERN int +SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc) +{ +#if PY_VERSION_HEX>=0x03000000 +#if defined(SWIG_PYTHON_STRICT_BYTE_CHAR) + if (PyBytes_Check(obj)) +#else + if (PyUnicode_Check(obj)) +#endif +#else + if (PyString_Check(obj)) +#endif + { + char *cstr; Py_ssize_t len; +#if PY_VERSION_HEX>=0x03000000 +#if !defined(SWIG_PYTHON_STRICT_BYTE_CHAR) + if (!alloc && cptr) { + /* We can't allow converting without allocation, since the internal + representation of string in Python 3 is UCS-2/UCS-4 but we require + a UTF-8 representation. + TODO(bhy) More detailed explanation */ + return SWIG_RuntimeError; + } + obj = PyUnicode_AsUTF8String(obj); + if(alloc) *alloc = SWIG_NEWOBJ; +#endif + PyBytes_AsStringAndSize(obj, &cstr, &len); +#else + PyString_AsStringAndSize(obj, &cstr, &len); +#endif + if (cptr) { + if (alloc) { + /* + In python the user should not be able to modify the inner + string representation. To warranty that, if you define + SWIG_PYTHON_SAFE_CSTRINGS, a new/copy of the python string + buffer is always returned. + + The default behavior is just to return the pointer value, + so, be careful. + */ +#if defined(SWIG_PYTHON_SAFE_CSTRINGS) + if (*alloc != SWIG_OLDOBJ) +#else + if (*alloc == SWIG_NEWOBJ) +#endif + { + *cptr = (char *)memcpy(malloc((len + 1)*sizeof(char)), cstr, sizeof(char)*(len + 1)); + *alloc = SWIG_NEWOBJ; + } else { + *cptr = cstr; + *alloc = SWIG_OLDOBJ; + } + } else { +#if PY_VERSION_HEX>=0x03000000 +#if defined(SWIG_PYTHON_STRICT_BYTE_CHAR) + *cptr = PyBytes_AsString(obj); +#else + assert(0); /* Should never reach here with Unicode strings in Python 3 */ +#endif +#else + *cptr = SWIG_Python_str_AsChar(obj); +#endif + } + } + if (psize) *psize = len + 1; +#if PY_VERSION_HEX>=0x03000000 && !defined(SWIG_PYTHON_STRICT_BYTE_CHAR) + Py_XDECREF(obj); +#endif + return SWIG_OK; + } else { +#if defined(SWIG_PYTHON_2_UNICODE) +#if defined(SWIG_PYTHON_STRICT_BYTE_CHAR) +#error "Cannot use both SWIG_PYTHON_2_UNICODE and SWIG_PYTHON_STRICT_BYTE_CHAR at once" +#endif +#if PY_VERSION_HEX<0x03000000 + if (PyUnicode_Check(obj)) { + char *cstr; Py_ssize_t len; + if (!alloc && cptr) { + return SWIG_RuntimeError; + } + obj = PyUnicode_AsUTF8String(obj); + if (PyString_AsStringAndSize(obj, &cstr, &len) != -1) { + if (cptr) { + if (alloc) *alloc = SWIG_NEWOBJ; + *cptr = (char *)memcpy(malloc((len + 1)*sizeof(char)), cstr, sizeof(char)*(len + 1)); + } + if (psize) *psize = len + 1; + + Py_XDECREF(obj); + return SWIG_OK; + } else { + Py_XDECREF(obj); + } + } +#endif +#endif + + swig_type_info* pchar_descriptor = SWIG_pchar_descriptor(); + if (pchar_descriptor) { + void* vptr = 0; + if (SWIG_ConvertPtr(obj, &vptr, pchar_descriptor, 0) == SWIG_OK) { + if (cptr) *cptr = (char *) vptr; + if (psize) *psize = vptr ? (strlen((char *)vptr) + 1) : 0; + if (alloc) *alloc = SWIG_OLDOBJ; + return SWIG_OK; + } + } + } + return SWIG_TypeError; +} + + +SWIGINTERN int +SWIG_AsVal_double (PyObject *obj, double *val) +{ + int res = SWIG_TypeError; + if (PyFloat_Check(obj)) { + if (val) *val = PyFloat_AsDouble(obj); + return SWIG_OK; +#if PY_VERSION_HEX < 0x03000000 + } else if (PyInt_Check(obj)) { + if (val) *val = (double) PyInt_AsLong(obj); + return SWIG_OK; +#endif + } else if (PyLong_Check(obj)) { + double v = PyLong_AsDouble(obj); + if (!PyErr_Occurred()) { + if (val) *val = v; + return SWIG_OK; + } else { + PyErr_Clear(); + } + } +#ifdef SWIG_PYTHON_CAST_MODE + { + int dispatch = 0; + double d = PyFloat_AsDouble(obj); + if (!PyErr_Occurred()) { + if (val) *val = d; + return SWIG_AddCast(SWIG_OK); + } else { + PyErr_Clear(); + } + if (!dispatch) { + long v = PyLong_AsLong(obj); + if (!PyErr_Occurred()) { + if (val) *val = v; + return SWIG_AddCast(SWIG_AddCast(SWIG_OK)); + } else { + PyErr_Clear(); + } + } + } +#endif + return res; +} + + +#include + + +#include + + +SWIGINTERNINLINE int +SWIG_CanCastAsInteger(double *d, double min, double max) { + double x = *d; + if ((min <= x && x <= max)) { + double fx = floor(x); + double cx = ceil(x); + double rd = ((x - fx) < 0.5) ? fx : cx; /* simple rint */ + if ((errno == EDOM) || (errno == ERANGE)) { + errno = 0; + } else { + double summ, reps, diff; + if (rd < x) { + diff = x - rd; + } else if (rd > x) { + diff = rd - x; + } else { + return 1; + } + summ = rd + x; + reps = diff/summ; + if (reps < 8*DBL_EPSILON) { + *d = rd; + return 1; + } + } + } + return 0; +} + + +SWIGINTERN int +SWIG_AsVal_unsigned_SS_long (PyObject *obj, unsigned long *val) +{ +#if PY_VERSION_HEX < 0x03000000 + if (PyInt_Check(obj)) { + long v = PyInt_AsLong(obj); + if (v >= 0) { + if (val) *val = v; + return SWIG_OK; + } else { + return SWIG_OverflowError; + } + } else +#endif + if (PyLong_Check(obj)) { + unsigned long v = PyLong_AsUnsignedLong(obj); + if (!PyErr_Occurred()) { + if (val) *val = v; + return SWIG_OK; + } else { + PyErr_Clear(); + return SWIG_OverflowError; + } + } +#ifdef SWIG_PYTHON_CAST_MODE + { + int dispatch = 0; + unsigned long v = PyLong_AsUnsignedLong(obj); + if (!PyErr_Occurred()) { + if (val) *val = v; + return SWIG_AddCast(SWIG_OK); + } else { + PyErr_Clear(); + } + if (!dispatch) { + double d; + int res = SWIG_AddCast(SWIG_AsVal_double (obj,&d)); + if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, ULONG_MAX)) { + if (val) *val = (unsigned long)(d); + return res; + } + } + } +#endif + return SWIG_TypeError; +} + + +#include +#if !defined(SWIG_NO_LLONG_MAX) +# if !defined(LLONG_MAX) && defined(__GNUC__) && defined (__LONG_LONG_MAX__) +# define LLONG_MAX __LONG_LONG_MAX__ +# define LLONG_MIN (-LLONG_MAX - 1LL) +# define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL) +# endif +#endif + + +#if defined(LLONG_MAX) && !defined(SWIG_LONG_LONG_AVAILABLE) +# define SWIG_LONG_LONG_AVAILABLE +#endif + + +#ifdef SWIG_LONG_LONG_AVAILABLE +SWIGINTERN int +SWIG_AsVal_unsigned_SS_long_SS_long (PyObject *obj, unsigned long long *val) +{ + int res = SWIG_TypeError; + if (PyLong_Check(obj)) { + unsigned long long v = PyLong_AsUnsignedLongLong(obj); + if (!PyErr_Occurred()) { + if (val) *val = v; + return SWIG_OK; + } else { + PyErr_Clear(); + res = SWIG_OverflowError; + } + } else { + unsigned long v; + res = SWIG_AsVal_unsigned_SS_long (obj,&v); + if (SWIG_IsOK(res)) { + if (val) *val = v; + return res; + } + } +#ifdef SWIG_PYTHON_CAST_MODE + { + const double mant_max = 1LL << DBL_MANT_DIG; + double d; + res = SWIG_AsVal_double (obj,&d); + if (SWIG_IsOK(res) && !SWIG_CanCastAsInteger(&d, 0, mant_max)) + return SWIG_OverflowError; + if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, mant_max)) { + if (val) *val = (unsigned long long)(d); + return SWIG_AddCast(res); + } + res = SWIG_TypeError; + } +#endif + return res; +} +#endif + + +SWIGINTERNINLINE int +SWIG_AsVal_size_t (PyObject * obj, size_t *val) +{ + int res = SWIG_TypeError; +#ifdef SWIG_LONG_LONG_AVAILABLE + if (sizeof(size_t) <= sizeof(unsigned long)) { +#endif + unsigned long v; + res = SWIG_AsVal_unsigned_SS_long (obj, val ? &v : 0); + if (SWIG_IsOK(res) && val) *val = (size_t)(v); +#ifdef SWIG_LONG_LONG_AVAILABLE + } else if (sizeof(size_t) <= sizeof(unsigned long long)) { + unsigned long long v; + res = SWIG_AsVal_unsigned_SS_long_SS_long (obj, val ? &v : 0); + if (SWIG_IsOK(res) && val) *val = (size_t)(v); + } +#endif + return res; +} + + +#include "webp/decode.h" +#include "webp/encode.h" + + +static size_t ReturnedBufferSize( + const char* function, int* width, int* height) { + static const struct sizemap { + const char* function; + int size_multiplier; + } size_map[] = { +#ifdef SWIGJAVA + { "Java_com_google_webp_libwebpJNI_WebPDecodeRGB", 3 }, + { "Java_com_google_webp_libwebpJNI_WebPDecodeRGBA", 4 }, + { "Java_com_google_webp_libwebpJNI_WebPDecodeARGB", 4 }, + { "Java_com_google_webp_libwebpJNI_WebPDecodeBGR", 3 }, + { "Java_com_google_webp_libwebpJNI_WebPDecodeBGRA", 4 }, + { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeRGB", 1 }, + { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeBGR", 1 }, + { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeRGBA", 1 }, + { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeBGRA", 1 }, + { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessRGB", 1 }, + { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessBGR", 1 }, + { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessRGBA", 1 }, + { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessBGRA", 1 }, +#endif +#ifdef SWIGPYTHON + { "WebPDecodeRGB", 3 }, + { "WebPDecodeRGBA", 4 }, + { "WebPDecodeARGB", 4 }, + { "WebPDecodeBGR", 3 }, + { "WebPDecodeBGRA", 4 }, + { "wrap_WebPEncodeRGB", 1 }, + { "wrap_WebPEncodeBGR", 1 }, + { "wrap_WebPEncodeRGBA", 1 }, + { "wrap_WebPEncodeBGRA", 1 }, + { "wrap_WebPEncodeLosslessRGB", 1 }, + { "wrap_WebPEncodeLosslessBGR", 1 }, + { "wrap_WebPEncodeLosslessRGBA", 1 }, + { "wrap_WebPEncodeLosslessBGRA", 1 }, +#endif + { NULL, 0 } + }; + const struct sizemap* p; + size_t size = 0; + + for (p = size_map; p->function; ++p) { + if (!strcmp(function, p->function)) { + size = *width * *height * p->size_multiplier; + break; + } + } + + return size; +} + + +typedef size_t (*WebPEncodeFunction)(const uint8_t* rgb, + int width, int height, int stride, + float quality_factor, uint8_t** output); +typedef size_t (*WebPEncodeLosslessFunction)(const uint8_t* rgb, + int width, int height, int stride, + uint8_t** output); + +static uint8_t* EncodeLossy(const uint8_t* rgb, + int width, int height, int stride, + float quality_factor, + WebPEncodeFunction encfn, + int* output_size, int* unused) { + uint8_t* output = NULL; + const size_t image_size = + encfn(rgb, width, height, stride, quality_factor, &output); + // the values of following two will be interpreted by ReturnedBufferSize() + // as 'width' and 'height' in the size calculation. + *output_size = image_size; + *unused = 1; + return image_size ? output : NULL; +} + +static uint8_t* EncodeLossless(const uint8_t* rgb, + int width, int height, int stride, + WebPEncodeLosslessFunction encfn, + int* output_size, int* unused) { + uint8_t* output = NULL; + const size_t image_size = encfn(rgb, width, height, stride, &output); + // the values of the following two will be interpreted by + // ReturnedBufferSize() as 'width' and 'height' in the size calculation. + *output_size = image_size; + *unused = 1; + return image_size ? output : NULL; +} + + +// Changes the return type of WebPEncode* to more closely match Decode*. +// This also makes it easier to wrap the output buffer in a native type rather +// than dealing with the return pointer. +// The additional parameters are to allow reuse of ReturnedBufferSize(), +// unused2 and output_size will be used in this case. +#define LOSSY_WRAPPER(FUNC) \ + static uint8_t* wrap_##FUNC( \ + const uint8_t* rgb, int* unused1, int* unused2, int* output_size, \ + int width, int height, int stride, float quality_factor) { \ + return EncodeLossy(rgb, width, height, stride, quality_factor, \ + FUNC, output_size, unused2); \ + } \ + +LOSSY_WRAPPER(WebPEncodeRGB) +LOSSY_WRAPPER(WebPEncodeBGR) +LOSSY_WRAPPER(WebPEncodeRGBA) +LOSSY_WRAPPER(WebPEncodeBGRA) + +#undef LOSSY_WRAPPER + +#define LOSSLESS_WRAPPER(FUNC) \ + static uint8_t* wrap_##FUNC( \ + const uint8_t* rgb, int* unused1, int* unused2, int* output_size, \ + int width, int height, int stride) { \ + return EncodeLossless(rgb, width, height, stride, \ + FUNC, output_size, unused2); \ + } \ + +LOSSLESS_WRAPPER(WebPEncodeLosslessRGB) +LOSSLESS_WRAPPER(WebPEncodeLosslessBGR) +LOSSLESS_WRAPPER(WebPEncodeLosslessRGBA) +LOSSLESS_WRAPPER(WebPEncodeLosslessBGRA) + +#undef LOSSLESS_WRAPPER + + + +SWIGINTERN int +SWIG_AsVal_long (PyObject *obj, long* val) +{ +#if PY_VERSION_HEX < 0x03000000 + if (PyInt_Check(obj)) { + if (val) *val = PyInt_AsLong(obj); + return SWIG_OK; + } else +#endif + if (PyLong_Check(obj)) { + long v = PyLong_AsLong(obj); + if (!PyErr_Occurred()) { + if (val) *val = v; + return SWIG_OK; + } else { + PyErr_Clear(); + return SWIG_OverflowError; + } + } +#ifdef SWIG_PYTHON_CAST_MODE + { + int dispatch = 0; + long v = PyInt_AsLong(obj); + if (!PyErr_Occurred()) { + if (val) *val = v; + return SWIG_AddCast(SWIG_OK); + } else { + PyErr_Clear(); + } + if (!dispatch) { + double d; + int res = SWIG_AddCast(SWIG_AsVal_double (obj,&d)); + if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LONG_MIN, LONG_MAX)) { + if (val) *val = (long)(d); + return res; + } + } + } +#endif + return SWIG_TypeError; +} + + +SWIGINTERN int +SWIG_AsVal_int (PyObject * obj, int *val) +{ + long v; + int res = SWIG_AsVal_long (obj, &v); + if (SWIG_IsOK(res)) { + if ((v < INT_MIN || v > INT_MAX)) { + return SWIG_OverflowError; + } else { + if (val) *val = (int)(v); + } + } + return res; +} + + +/* Getting isfinite working pre C99 across multiple platforms is non-trivial. Users can provide SWIG_isfinite on older platforms. */ +#ifndef SWIG_isfinite +/* isfinite() is a macro for C99 */ +# if defined(isfinite) +# define SWIG_isfinite(X) (isfinite(X)) +# elif defined __cplusplus && __cplusplus >= 201103L +/* Use a template so that this works whether isfinite() is std::isfinite() or + * in the global namespace. The reality seems to vary between compiler + * versions. + * + * Make sure namespace std exists to avoid compiler warnings. + * + * extern "C++" is required as this fragment can end up inside an extern "C" { } block + */ +namespace std { } +extern "C++" template +inline int SWIG_isfinite_func(T x) { + using namespace std; + return isfinite(x); +} +# define SWIG_isfinite(X) (SWIG_isfinite_func(X)) +# elif defined(_MSC_VER) +# define SWIG_isfinite(X) (_finite(X)) +# elif defined(__sun) && defined(__SVR4) +# include +# define SWIG_isfinite(X) (finite(X)) +# endif +#endif + + +/* Accept infinite as a valid float value unless we are unable to check if a value is finite */ +#ifdef SWIG_isfinite +# define SWIG_Float_Overflow_Check(X) ((X < -FLT_MAX || X > FLT_MAX) && SWIG_isfinite(X)) +#else +# define SWIG_Float_Overflow_Check(X) ((X < -FLT_MAX || X > FLT_MAX)) +#endif + + +SWIGINTERN int +SWIG_AsVal_float (PyObject * obj, float *val) +{ + double v; + int res = SWIG_AsVal_double (obj, &v); + if (SWIG_IsOK(res)) { + if (SWIG_Float_Overflow_Check(v)) { + return SWIG_OverflowError; + } else { + if (val) *val = (float)(v); + } + } + return res; +} + +#ifdef __cplusplus +extern "C" { +#endif +SWIGINTERN PyObject *_wrap_WebPGetDecoderVersion(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + int result; + + if (!PyArg_ParseTuple(args,(char *)":WebPGetDecoderVersion")) SWIG_fail; + result = (int)WebPGetDecoderVersion(); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_WebPGetInfo(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + uint8_t *arg1 = (uint8_t *) 0 ; + size_t arg2 ; + int *arg3 = (int *) 0 ; + int *arg4 = (int *) 0 ; + int res1 ; + char *buf1 = 0 ; + size_t size1 = 0 ; + int alloc1 = 0 ; + int temp3 ; + int res3 = SWIG_TMPOBJ ; + int temp4 ; + int res4 = SWIG_TMPOBJ ; + PyObject * obj0 = 0 ; + int result; + + arg3 = &temp3; + arg4 = &temp4; + if (!PyArg_ParseTuple(args,(char *)"O:WebPGetInfo",&obj0)) SWIG_fail; + res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, &size1, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "WebPGetInfo" "', argument " "1"" of type '" "uint8_t const *""'"); + } + arg1 = (uint8_t *)(buf1); + arg2 = (size_t)(size1 - 1); + result = (int)WebPGetInfo((uint8_t const *)arg1,arg2,arg3,arg4); + resultobj = SWIG_From_int((int)(result)); + if (SWIG_IsTmpObj(res3)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg3))); + } else { + int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_int, new_flags)); + } + if (SWIG_IsTmpObj(res4)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4))); + } else { + int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags)); + } + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_WebPDecodeRGB(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + uint8_t *arg1 = (uint8_t *) 0 ; + size_t arg2 ; + int *arg3 = (int *) 0 ; + int *arg4 = (int *) 0 ; + int res1 ; + char *buf1 = 0 ; + size_t size1 = 0 ; + int alloc1 = 0 ; + int temp3 ; + int res3 = SWIG_TMPOBJ ; + int temp4 ; + int res4 = SWIG_TMPOBJ ; + PyObject * obj0 = 0 ; + uint8_t *result = 0 ; + + arg3 = &temp3; + arg4 = &temp4; + if (!PyArg_ParseTuple(args,(char *)"O:WebPDecodeRGB",&obj0)) SWIG_fail; + res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, &size1, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "WebPDecodeRGB" "', argument " "1"" of type '" "uint8_t const *""'"); + } + arg1 = (uint8_t *)(buf1); + arg2 = (size_t)(size1 - 1); + result = (uint8_t *)WebPDecodeRGB((uint8_t const *)arg1,arg2,arg3,arg4); + { + resultobj = PyString_FromStringAndSize( + (const char*)result, + (result == NULL) ? 0 : ReturnedBufferSize("WebPDecodeRGB", arg3, arg4)); + } + if (SWIG_IsTmpObj(res3)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg3))); + } else { + int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_int, new_flags)); + } + if (SWIG_IsTmpObj(res4)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4))); + } else { + int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags)); + } + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + free(result); + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_WebPDecodeRGBA(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + uint8_t *arg1 = (uint8_t *) 0 ; + size_t arg2 ; + int *arg3 = (int *) 0 ; + int *arg4 = (int *) 0 ; + int res1 ; + char *buf1 = 0 ; + size_t size1 = 0 ; + int alloc1 = 0 ; + int temp3 ; + int res3 = SWIG_TMPOBJ ; + int temp4 ; + int res4 = SWIG_TMPOBJ ; + PyObject * obj0 = 0 ; + uint8_t *result = 0 ; + + arg3 = &temp3; + arg4 = &temp4; + if (!PyArg_ParseTuple(args,(char *)"O:WebPDecodeRGBA",&obj0)) SWIG_fail; + res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, &size1, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "WebPDecodeRGBA" "', argument " "1"" of type '" "uint8_t const *""'"); + } + arg1 = (uint8_t *)(buf1); + arg2 = (size_t)(size1 - 1); + result = (uint8_t *)WebPDecodeRGBA((uint8_t const *)arg1,arg2,arg3,arg4); + { + resultobj = PyString_FromStringAndSize( + (const char*)result, + (result == NULL) ? 0 : ReturnedBufferSize("WebPDecodeRGBA", arg3, arg4)); + } + if (SWIG_IsTmpObj(res3)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg3))); + } else { + int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_int, new_flags)); + } + if (SWIG_IsTmpObj(res4)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4))); + } else { + int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags)); + } + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + free(result); + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_WebPDecodeARGB(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + uint8_t *arg1 = (uint8_t *) 0 ; + size_t arg2 ; + int *arg3 = (int *) 0 ; + int *arg4 = (int *) 0 ; + int res1 ; + char *buf1 = 0 ; + size_t size1 = 0 ; + int alloc1 = 0 ; + int temp3 ; + int res3 = SWIG_TMPOBJ ; + int temp4 ; + int res4 = SWIG_TMPOBJ ; + PyObject * obj0 = 0 ; + uint8_t *result = 0 ; + + arg3 = &temp3; + arg4 = &temp4; + if (!PyArg_ParseTuple(args,(char *)"O:WebPDecodeARGB",&obj0)) SWIG_fail; + res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, &size1, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "WebPDecodeARGB" "', argument " "1"" of type '" "uint8_t const *""'"); + } + arg1 = (uint8_t *)(buf1); + arg2 = (size_t)(size1 - 1); + result = (uint8_t *)WebPDecodeARGB((uint8_t const *)arg1,arg2,arg3,arg4); + { + resultobj = PyString_FromStringAndSize( + (const char*)result, + (result == NULL) ? 0 : ReturnedBufferSize("WebPDecodeARGB", arg3, arg4)); + } + if (SWIG_IsTmpObj(res3)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg3))); + } else { + int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_int, new_flags)); + } + if (SWIG_IsTmpObj(res4)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4))); + } else { + int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags)); + } + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + free(result); + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_WebPDecodeBGR(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + uint8_t *arg1 = (uint8_t *) 0 ; + size_t arg2 ; + int *arg3 = (int *) 0 ; + int *arg4 = (int *) 0 ; + int res1 ; + char *buf1 = 0 ; + size_t size1 = 0 ; + int alloc1 = 0 ; + int temp3 ; + int res3 = SWIG_TMPOBJ ; + int temp4 ; + int res4 = SWIG_TMPOBJ ; + PyObject * obj0 = 0 ; + uint8_t *result = 0 ; + + arg3 = &temp3; + arg4 = &temp4; + if (!PyArg_ParseTuple(args,(char *)"O:WebPDecodeBGR",&obj0)) SWIG_fail; + res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, &size1, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "WebPDecodeBGR" "', argument " "1"" of type '" "uint8_t const *""'"); + } + arg1 = (uint8_t *)(buf1); + arg2 = (size_t)(size1 - 1); + result = (uint8_t *)WebPDecodeBGR((uint8_t const *)arg1,arg2,arg3,arg4); + { + resultobj = PyString_FromStringAndSize( + (const char*)result, + (result == NULL) ? 0 : ReturnedBufferSize("WebPDecodeBGR", arg3, arg4)); + } + if (SWIG_IsTmpObj(res3)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg3))); + } else { + int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_int, new_flags)); + } + if (SWIG_IsTmpObj(res4)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4))); + } else { + int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags)); + } + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + free(result); + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_WebPDecodeBGRA(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + uint8_t *arg1 = (uint8_t *) 0 ; + size_t arg2 ; + int *arg3 = (int *) 0 ; + int *arg4 = (int *) 0 ; + int res1 ; + char *buf1 = 0 ; + size_t size1 = 0 ; + int alloc1 = 0 ; + int temp3 ; + int res3 = SWIG_TMPOBJ ; + int temp4 ; + int res4 = SWIG_TMPOBJ ; + PyObject * obj0 = 0 ; + uint8_t *result = 0 ; + + arg3 = &temp3; + arg4 = &temp4; + if (!PyArg_ParseTuple(args,(char *)"O:WebPDecodeBGRA",&obj0)) SWIG_fail; + res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, &size1, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "WebPDecodeBGRA" "', argument " "1"" of type '" "uint8_t const *""'"); + } + arg1 = (uint8_t *)(buf1); + arg2 = (size_t)(size1 - 1); + result = (uint8_t *)WebPDecodeBGRA((uint8_t const *)arg1,arg2,arg3,arg4); + { + resultobj = PyString_FromStringAndSize( + (const char*)result, + (result == NULL) ? 0 : ReturnedBufferSize("WebPDecodeBGRA", arg3, arg4)); + } + if (SWIG_IsTmpObj(res3)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg3))); + } else { + int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_int, new_flags)); + } + if (SWIG_IsTmpObj(res4)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4))); + } else { + int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags)); + } + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + free(result); + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_WebPGetEncoderVersion(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + int result; + + if (!PyArg_ParseTuple(args,(char *)":WebPGetEncoderVersion")) SWIG_fail; + result = (int)WebPGetEncoderVersion(); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_wrap_WebPEncodeRGB(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + uint8_t *arg1 = (uint8_t *) 0 ; + int *arg2 = (int *) 0 ; + int *arg3 = (int *) 0 ; + int *arg4 = (int *) 0 ; + int arg5 ; + int arg6 ; + int arg7 ; + float arg8 ; + Py_buffer rgb_buffer1 ; + int temp2 ; + int res2 = 0 ; + int temp3 ; + int res3 = 0 ; + int temp4 ; + int res4 = SWIG_TMPOBJ ; + int val5 ; + int ecode5 = 0 ; + int val6 ; + int ecode6 = 0 ; + int val7 ; + int ecode7 = 0 ; + float val8 ; + int ecode8 = 0 ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + PyObject * obj2 = 0 ; + PyObject * obj3 = 0 ; + PyObject * obj4 = 0 ; + PyObject * obj5 = 0 ; + PyObject * obj6 = 0 ; + uint8_t *result = 0 ; + + arg4 = &temp4; + if (!PyArg_ParseTuple(args,(char *)"OOOOOOO:wrap_WebPEncodeRGB",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6)) SWIG_fail; + { + // NB: with Python < 2.6 the old style buffer protocol may be used: + // Py_ssize_t unused; + // PyObject_AsReadBuffer(obj0, (const void**)(&arg1), &unused); + if (!PyObject_CheckBuffer(obj0)) { + SWIG_exception_fail(SWIG_TypeError, + "in method 'wrap_WebPEncodeRGB', argument 1" + " does not support the buffer interface"); + } + if (PyObject_GetBuffer(obj0, &rgb_buffer1, PyBUF_SIMPLE)) { + SWIG_exception_fail(SWIG_RuntimeError, + "in method 'wrap_WebPEncodeRGB', unable to get buffer view"); + } + arg1 = (uint8_t *)rgb_buffer1.buf; + } + if (!(SWIG_IsOK((res2 = SWIG_ConvertPtr(obj1,SWIG_as_voidptrptr(&arg2),SWIGTYPE_p_int,0))))) { + int val; + int ecode = SWIG_AsVal_int(obj1, &val); + if (!SWIG_IsOK(ecode)) { + SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeRGB" "', argument " "2"" of type '" "int""'"); + } + temp2 = (int)(val); + arg2 = &temp2; + res2 = SWIG_AddTmpMask(ecode); + } + if (!(SWIG_IsOK((res3 = SWIG_ConvertPtr(obj2,SWIG_as_voidptrptr(&arg3),SWIGTYPE_p_int,0))))) { + int val; + int ecode = SWIG_AsVal_int(obj2, &val); + if (!SWIG_IsOK(ecode)) { + SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeRGB" "', argument " "3"" of type '" "int""'"); + } + temp3 = (int)(val); + arg3 = &temp3; + res3 = SWIG_AddTmpMask(ecode); + } + ecode5 = SWIG_AsVal_int(obj3, &val5); + if (!SWIG_IsOK(ecode5)) { + SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "wrap_WebPEncodeRGB" "', argument " "5"" of type '" "int""'"); + } + arg5 = (int)(val5); + ecode6 = SWIG_AsVal_int(obj4, &val6); + if (!SWIG_IsOK(ecode6)) { + SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "wrap_WebPEncodeRGB" "', argument " "6"" of type '" "int""'"); + } + arg6 = (int)(val6); + ecode7 = SWIG_AsVal_int(obj5, &val7); + if (!SWIG_IsOK(ecode7)) { + SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "wrap_WebPEncodeRGB" "', argument " "7"" of type '" "int""'"); + } + arg7 = (int)(val7); + ecode8 = SWIG_AsVal_float(obj6, &val8); + if (!SWIG_IsOK(ecode8)) { + SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "wrap_WebPEncodeRGB" "', argument " "8"" of type '" "float""'"); + } + arg8 = (float)(val8); + result = (uint8_t *)wrap_WebPEncodeRGB((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8); + { + resultobj = PyString_FromStringAndSize( + (const char*)result, + (result == NULL) ? 0 : ReturnedBufferSize("wrap_WebPEncodeRGB", arg3, arg4)); + } + if (SWIG_IsTmpObj(res4)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4))); + } else { + int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags)); + } + { + PyBuffer_Release(&rgb_buffer1); + } + if (SWIG_IsNewObj(res2)) free((char*)arg2); + if (SWIG_IsNewObj(res3)) free((char*)arg3); + free(result); + return resultobj; +fail: + { + PyBuffer_Release(&rgb_buffer1); + } + if (SWIG_IsNewObj(res2)) free((char*)arg2); + if (SWIG_IsNewObj(res3)) free((char*)arg3); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_wrap_WebPEncodeBGR(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + uint8_t *arg1 = (uint8_t *) 0 ; + int *arg2 = (int *) 0 ; + int *arg3 = (int *) 0 ; + int *arg4 = (int *) 0 ; + int arg5 ; + int arg6 ; + int arg7 ; + float arg8 ; + Py_buffer rgb_buffer1 ; + int temp2 ; + int res2 = 0 ; + int temp3 ; + int res3 = 0 ; + int temp4 ; + int res4 = SWIG_TMPOBJ ; + int val5 ; + int ecode5 = 0 ; + int val6 ; + int ecode6 = 0 ; + int val7 ; + int ecode7 = 0 ; + float val8 ; + int ecode8 = 0 ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + PyObject * obj2 = 0 ; + PyObject * obj3 = 0 ; + PyObject * obj4 = 0 ; + PyObject * obj5 = 0 ; + PyObject * obj6 = 0 ; + uint8_t *result = 0 ; + + arg4 = &temp4; + if (!PyArg_ParseTuple(args,(char *)"OOOOOOO:wrap_WebPEncodeBGR",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6)) SWIG_fail; + { + // NB: with Python < 2.6 the old style buffer protocol may be used: + // Py_ssize_t unused; + // PyObject_AsReadBuffer(obj0, (const void**)(&arg1), &unused); + if (!PyObject_CheckBuffer(obj0)) { + SWIG_exception_fail(SWIG_TypeError, + "in method 'wrap_WebPEncodeBGR', argument 1" + " does not support the buffer interface"); + } + if (PyObject_GetBuffer(obj0, &rgb_buffer1, PyBUF_SIMPLE)) { + SWIG_exception_fail(SWIG_RuntimeError, + "in method 'wrap_WebPEncodeBGR', unable to get buffer view"); + } + arg1 = (uint8_t *)rgb_buffer1.buf; + } + if (!(SWIG_IsOK((res2 = SWIG_ConvertPtr(obj1,SWIG_as_voidptrptr(&arg2),SWIGTYPE_p_int,0))))) { + int val; + int ecode = SWIG_AsVal_int(obj1, &val); + if (!SWIG_IsOK(ecode)) { + SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeBGR" "', argument " "2"" of type '" "int""'"); + } + temp2 = (int)(val); + arg2 = &temp2; + res2 = SWIG_AddTmpMask(ecode); + } + if (!(SWIG_IsOK((res3 = SWIG_ConvertPtr(obj2,SWIG_as_voidptrptr(&arg3),SWIGTYPE_p_int,0))))) { + int val; + int ecode = SWIG_AsVal_int(obj2, &val); + if (!SWIG_IsOK(ecode)) { + SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeBGR" "', argument " "3"" of type '" "int""'"); + } + temp3 = (int)(val); + arg3 = &temp3; + res3 = SWIG_AddTmpMask(ecode); + } + ecode5 = SWIG_AsVal_int(obj3, &val5); + if (!SWIG_IsOK(ecode5)) { + SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "wrap_WebPEncodeBGR" "', argument " "5"" of type '" "int""'"); + } + arg5 = (int)(val5); + ecode6 = SWIG_AsVal_int(obj4, &val6); + if (!SWIG_IsOK(ecode6)) { + SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "wrap_WebPEncodeBGR" "', argument " "6"" of type '" "int""'"); + } + arg6 = (int)(val6); + ecode7 = SWIG_AsVal_int(obj5, &val7); + if (!SWIG_IsOK(ecode7)) { + SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "wrap_WebPEncodeBGR" "', argument " "7"" of type '" "int""'"); + } + arg7 = (int)(val7); + ecode8 = SWIG_AsVal_float(obj6, &val8); + if (!SWIG_IsOK(ecode8)) { + SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "wrap_WebPEncodeBGR" "', argument " "8"" of type '" "float""'"); + } + arg8 = (float)(val8); + result = (uint8_t *)wrap_WebPEncodeBGR((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8); + { + resultobj = PyString_FromStringAndSize( + (const char*)result, + (result == NULL) ? 0 : ReturnedBufferSize("wrap_WebPEncodeBGR", arg3, arg4)); + } + if (SWIG_IsTmpObj(res4)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4))); + } else { + int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags)); + } + { + PyBuffer_Release(&rgb_buffer1); + } + if (SWIG_IsNewObj(res2)) free((char*)arg2); + if (SWIG_IsNewObj(res3)) free((char*)arg3); + free(result); + return resultobj; +fail: + { + PyBuffer_Release(&rgb_buffer1); + } + if (SWIG_IsNewObj(res2)) free((char*)arg2); + if (SWIG_IsNewObj(res3)) free((char*)arg3); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_wrap_WebPEncodeRGBA(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + uint8_t *arg1 = (uint8_t *) 0 ; + int *arg2 = (int *) 0 ; + int *arg3 = (int *) 0 ; + int *arg4 = (int *) 0 ; + int arg5 ; + int arg6 ; + int arg7 ; + float arg8 ; + Py_buffer rgb_buffer1 ; + int temp2 ; + int res2 = 0 ; + int temp3 ; + int res3 = 0 ; + int temp4 ; + int res4 = SWIG_TMPOBJ ; + int val5 ; + int ecode5 = 0 ; + int val6 ; + int ecode6 = 0 ; + int val7 ; + int ecode7 = 0 ; + float val8 ; + int ecode8 = 0 ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + PyObject * obj2 = 0 ; + PyObject * obj3 = 0 ; + PyObject * obj4 = 0 ; + PyObject * obj5 = 0 ; + PyObject * obj6 = 0 ; + uint8_t *result = 0 ; + + arg4 = &temp4; + if (!PyArg_ParseTuple(args,(char *)"OOOOOOO:wrap_WebPEncodeRGBA",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6)) SWIG_fail; + { + // NB: with Python < 2.6 the old style buffer protocol may be used: + // Py_ssize_t unused; + // PyObject_AsReadBuffer(obj0, (const void**)(&arg1), &unused); + if (!PyObject_CheckBuffer(obj0)) { + SWIG_exception_fail(SWIG_TypeError, + "in method 'wrap_WebPEncodeRGBA', argument 1" + " does not support the buffer interface"); + } + if (PyObject_GetBuffer(obj0, &rgb_buffer1, PyBUF_SIMPLE)) { + SWIG_exception_fail(SWIG_RuntimeError, + "in method 'wrap_WebPEncodeRGBA', unable to get buffer view"); + } + arg1 = (uint8_t *)rgb_buffer1.buf; + } + if (!(SWIG_IsOK((res2 = SWIG_ConvertPtr(obj1,SWIG_as_voidptrptr(&arg2),SWIGTYPE_p_int,0))))) { + int val; + int ecode = SWIG_AsVal_int(obj1, &val); + if (!SWIG_IsOK(ecode)) { + SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeRGBA" "', argument " "2"" of type '" "int""'"); + } + temp2 = (int)(val); + arg2 = &temp2; + res2 = SWIG_AddTmpMask(ecode); + } + if (!(SWIG_IsOK((res3 = SWIG_ConvertPtr(obj2,SWIG_as_voidptrptr(&arg3),SWIGTYPE_p_int,0))))) { + int val; + int ecode = SWIG_AsVal_int(obj2, &val); + if (!SWIG_IsOK(ecode)) { + SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeRGBA" "', argument " "3"" of type '" "int""'"); + } + temp3 = (int)(val); + arg3 = &temp3; + res3 = SWIG_AddTmpMask(ecode); + } + ecode5 = SWIG_AsVal_int(obj3, &val5); + if (!SWIG_IsOK(ecode5)) { + SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "wrap_WebPEncodeRGBA" "', argument " "5"" of type '" "int""'"); + } + arg5 = (int)(val5); + ecode6 = SWIG_AsVal_int(obj4, &val6); + if (!SWIG_IsOK(ecode6)) { + SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "wrap_WebPEncodeRGBA" "', argument " "6"" of type '" "int""'"); + } + arg6 = (int)(val6); + ecode7 = SWIG_AsVal_int(obj5, &val7); + if (!SWIG_IsOK(ecode7)) { + SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "wrap_WebPEncodeRGBA" "', argument " "7"" of type '" "int""'"); + } + arg7 = (int)(val7); + ecode8 = SWIG_AsVal_float(obj6, &val8); + if (!SWIG_IsOK(ecode8)) { + SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "wrap_WebPEncodeRGBA" "', argument " "8"" of type '" "float""'"); + } + arg8 = (float)(val8); + result = (uint8_t *)wrap_WebPEncodeRGBA((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8); + { + resultobj = PyString_FromStringAndSize( + (const char*)result, + (result == NULL) ? 0 : ReturnedBufferSize("wrap_WebPEncodeRGBA", arg3, arg4)); + } + if (SWIG_IsTmpObj(res4)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4))); + } else { + int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags)); + } + { + PyBuffer_Release(&rgb_buffer1); + } + if (SWIG_IsNewObj(res2)) free((char*)arg2); + if (SWIG_IsNewObj(res3)) free((char*)arg3); + free(result); + return resultobj; +fail: + { + PyBuffer_Release(&rgb_buffer1); + } + if (SWIG_IsNewObj(res2)) free((char*)arg2); + if (SWIG_IsNewObj(res3)) free((char*)arg3); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_wrap_WebPEncodeBGRA(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + uint8_t *arg1 = (uint8_t *) 0 ; + int *arg2 = (int *) 0 ; + int *arg3 = (int *) 0 ; + int *arg4 = (int *) 0 ; + int arg5 ; + int arg6 ; + int arg7 ; + float arg8 ; + Py_buffer rgb_buffer1 ; + int temp2 ; + int res2 = 0 ; + int temp3 ; + int res3 = 0 ; + int temp4 ; + int res4 = SWIG_TMPOBJ ; + int val5 ; + int ecode5 = 0 ; + int val6 ; + int ecode6 = 0 ; + int val7 ; + int ecode7 = 0 ; + float val8 ; + int ecode8 = 0 ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + PyObject * obj2 = 0 ; + PyObject * obj3 = 0 ; + PyObject * obj4 = 0 ; + PyObject * obj5 = 0 ; + PyObject * obj6 = 0 ; + uint8_t *result = 0 ; + + arg4 = &temp4; + if (!PyArg_ParseTuple(args,(char *)"OOOOOOO:wrap_WebPEncodeBGRA",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6)) SWIG_fail; + { + // NB: with Python < 2.6 the old style buffer protocol may be used: + // Py_ssize_t unused; + // PyObject_AsReadBuffer(obj0, (const void**)(&arg1), &unused); + if (!PyObject_CheckBuffer(obj0)) { + SWIG_exception_fail(SWIG_TypeError, + "in method 'wrap_WebPEncodeBGRA', argument 1" + " does not support the buffer interface"); + } + if (PyObject_GetBuffer(obj0, &rgb_buffer1, PyBUF_SIMPLE)) { + SWIG_exception_fail(SWIG_RuntimeError, + "in method 'wrap_WebPEncodeBGRA', unable to get buffer view"); + } + arg1 = (uint8_t *)rgb_buffer1.buf; + } + if (!(SWIG_IsOK((res2 = SWIG_ConvertPtr(obj1,SWIG_as_voidptrptr(&arg2),SWIGTYPE_p_int,0))))) { + int val; + int ecode = SWIG_AsVal_int(obj1, &val); + if (!SWIG_IsOK(ecode)) { + SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeBGRA" "', argument " "2"" of type '" "int""'"); + } + temp2 = (int)(val); + arg2 = &temp2; + res2 = SWIG_AddTmpMask(ecode); + } + if (!(SWIG_IsOK((res3 = SWIG_ConvertPtr(obj2,SWIG_as_voidptrptr(&arg3),SWIGTYPE_p_int,0))))) { + int val; + int ecode = SWIG_AsVal_int(obj2, &val); + if (!SWIG_IsOK(ecode)) { + SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeBGRA" "', argument " "3"" of type '" "int""'"); + } + temp3 = (int)(val); + arg3 = &temp3; + res3 = SWIG_AddTmpMask(ecode); + } + ecode5 = SWIG_AsVal_int(obj3, &val5); + if (!SWIG_IsOK(ecode5)) { + SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "wrap_WebPEncodeBGRA" "', argument " "5"" of type '" "int""'"); + } + arg5 = (int)(val5); + ecode6 = SWIG_AsVal_int(obj4, &val6); + if (!SWIG_IsOK(ecode6)) { + SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "wrap_WebPEncodeBGRA" "', argument " "6"" of type '" "int""'"); + } + arg6 = (int)(val6); + ecode7 = SWIG_AsVal_int(obj5, &val7); + if (!SWIG_IsOK(ecode7)) { + SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "wrap_WebPEncodeBGRA" "', argument " "7"" of type '" "int""'"); + } + arg7 = (int)(val7); + ecode8 = SWIG_AsVal_float(obj6, &val8); + if (!SWIG_IsOK(ecode8)) { + SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "wrap_WebPEncodeBGRA" "', argument " "8"" of type '" "float""'"); + } + arg8 = (float)(val8); + result = (uint8_t *)wrap_WebPEncodeBGRA((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8); + { + resultobj = PyString_FromStringAndSize( + (const char*)result, + (result == NULL) ? 0 : ReturnedBufferSize("wrap_WebPEncodeBGRA", arg3, arg4)); + } + if (SWIG_IsTmpObj(res4)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4))); + } else { + int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags)); + } + { + PyBuffer_Release(&rgb_buffer1); + } + if (SWIG_IsNewObj(res2)) free((char*)arg2); + if (SWIG_IsNewObj(res3)) free((char*)arg3); + free(result); + return resultobj; +fail: + { + PyBuffer_Release(&rgb_buffer1); + } + if (SWIG_IsNewObj(res2)) free((char*)arg2); + if (SWIG_IsNewObj(res3)) free((char*)arg3); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_wrap_WebPEncodeLosslessRGB(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + uint8_t *arg1 = (uint8_t *) 0 ; + int *arg2 = (int *) 0 ; + int *arg3 = (int *) 0 ; + int *arg4 = (int *) 0 ; + int arg5 ; + int arg6 ; + int arg7 ; + Py_buffer rgb_buffer1 ; + int temp2 ; + int res2 = 0 ; + int temp3 ; + int res3 = 0 ; + int temp4 ; + int res4 = SWIG_TMPOBJ ; + int val5 ; + int ecode5 = 0 ; + int val6 ; + int ecode6 = 0 ; + int val7 ; + int ecode7 = 0 ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + PyObject * obj2 = 0 ; + PyObject * obj3 = 0 ; + PyObject * obj4 = 0 ; + PyObject * obj5 = 0 ; + uint8_t *result = 0 ; + + arg4 = &temp4; + if (!PyArg_ParseTuple(args,(char *)"OOOOOO:wrap_WebPEncodeLosslessRGB",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail; + { + // NB: with Python < 2.6 the old style buffer protocol may be used: + // Py_ssize_t unused; + // PyObject_AsReadBuffer(obj0, (const void**)(&arg1), &unused); + if (!PyObject_CheckBuffer(obj0)) { + SWIG_exception_fail(SWIG_TypeError, + "in method 'wrap_WebPEncodeLosslessRGB', argument 1" + " does not support the buffer interface"); + } + if (PyObject_GetBuffer(obj0, &rgb_buffer1, PyBUF_SIMPLE)) { + SWIG_exception_fail(SWIG_RuntimeError, + "in method 'wrap_WebPEncodeLosslessRGB', unable to get buffer view"); + } + arg1 = (uint8_t *)rgb_buffer1.buf; + } + if (!(SWIG_IsOK((res2 = SWIG_ConvertPtr(obj1,SWIG_as_voidptrptr(&arg2),SWIGTYPE_p_int,0))))) { + int val; + int ecode = SWIG_AsVal_int(obj1, &val); + if (!SWIG_IsOK(ecode)) { + SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeLosslessRGB" "', argument " "2"" of type '" "int""'"); + } + temp2 = (int)(val); + arg2 = &temp2; + res2 = SWIG_AddTmpMask(ecode); + } + if (!(SWIG_IsOK((res3 = SWIG_ConvertPtr(obj2,SWIG_as_voidptrptr(&arg3),SWIGTYPE_p_int,0))))) { + int val; + int ecode = SWIG_AsVal_int(obj2, &val); + if (!SWIG_IsOK(ecode)) { + SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeLosslessRGB" "', argument " "3"" of type '" "int""'"); + } + temp3 = (int)(val); + arg3 = &temp3; + res3 = SWIG_AddTmpMask(ecode); + } + ecode5 = SWIG_AsVal_int(obj3, &val5); + if (!SWIG_IsOK(ecode5)) { + SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "wrap_WebPEncodeLosslessRGB" "', argument " "5"" of type '" "int""'"); + } + arg5 = (int)(val5); + ecode6 = SWIG_AsVal_int(obj4, &val6); + if (!SWIG_IsOK(ecode6)) { + SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "wrap_WebPEncodeLosslessRGB" "', argument " "6"" of type '" "int""'"); + } + arg6 = (int)(val6); + ecode7 = SWIG_AsVal_int(obj5, &val7); + if (!SWIG_IsOK(ecode7)) { + SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "wrap_WebPEncodeLosslessRGB" "', argument " "7"" of type '" "int""'"); + } + arg7 = (int)(val7); + result = (uint8_t *)wrap_WebPEncodeLosslessRGB((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7); + { + resultobj = PyString_FromStringAndSize( + (const char*)result, + (result == NULL) ? 0 : ReturnedBufferSize("wrap_WebPEncodeLosslessRGB", arg3, arg4)); + } + if (SWIG_IsTmpObj(res4)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4))); + } else { + int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags)); + } + { + PyBuffer_Release(&rgb_buffer1); + } + if (SWIG_IsNewObj(res2)) free((char*)arg2); + if (SWIG_IsNewObj(res3)) free((char*)arg3); + free(result); + return resultobj; +fail: + { + PyBuffer_Release(&rgb_buffer1); + } + if (SWIG_IsNewObj(res2)) free((char*)arg2); + if (SWIG_IsNewObj(res3)) free((char*)arg3); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_wrap_WebPEncodeLosslessBGR(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + uint8_t *arg1 = (uint8_t *) 0 ; + int *arg2 = (int *) 0 ; + int *arg3 = (int *) 0 ; + int *arg4 = (int *) 0 ; + int arg5 ; + int arg6 ; + int arg7 ; + Py_buffer rgb_buffer1 ; + int temp2 ; + int res2 = 0 ; + int temp3 ; + int res3 = 0 ; + int temp4 ; + int res4 = SWIG_TMPOBJ ; + int val5 ; + int ecode5 = 0 ; + int val6 ; + int ecode6 = 0 ; + int val7 ; + int ecode7 = 0 ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + PyObject * obj2 = 0 ; + PyObject * obj3 = 0 ; + PyObject * obj4 = 0 ; + PyObject * obj5 = 0 ; + uint8_t *result = 0 ; + + arg4 = &temp4; + if (!PyArg_ParseTuple(args,(char *)"OOOOOO:wrap_WebPEncodeLosslessBGR",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail; + { + // NB: with Python < 2.6 the old style buffer protocol may be used: + // Py_ssize_t unused; + // PyObject_AsReadBuffer(obj0, (const void**)(&arg1), &unused); + if (!PyObject_CheckBuffer(obj0)) { + SWIG_exception_fail(SWIG_TypeError, + "in method 'wrap_WebPEncodeLosslessBGR', argument 1" + " does not support the buffer interface"); + } + if (PyObject_GetBuffer(obj0, &rgb_buffer1, PyBUF_SIMPLE)) { + SWIG_exception_fail(SWIG_RuntimeError, + "in method 'wrap_WebPEncodeLosslessBGR', unable to get buffer view"); + } + arg1 = (uint8_t *)rgb_buffer1.buf; + } + if (!(SWIG_IsOK((res2 = SWIG_ConvertPtr(obj1,SWIG_as_voidptrptr(&arg2),SWIGTYPE_p_int,0))))) { + int val; + int ecode = SWIG_AsVal_int(obj1, &val); + if (!SWIG_IsOK(ecode)) { + SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeLosslessBGR" "', argument " "2"" of type '" "int""'"); + } + temp2 = (int)(val); + arg2 = &temp2; + res2 = SWIG_AddTmpMask(ecode); + } + if (!(SWIG_IsOK((res3 = SWIG_ConvertPtr(obj2,SWIG_as_voidptrptr(&arg3),SWIGTYPE_p_int,0))))) { + int val; + int ecode = SWIG_AsVal_int(obj2, &val); + if (!SWIG_IsOK(ecode)) { + SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeLosslessBGR" "', argument " "3"" of type '" "int""'"); + } + temp3 = (int)(val); + arg3 = &temp3; + res3 = SWIG_AddTmpMask(ecode); + } + ecode5 = SWIG_AsVal_int(obj3, &val5); + if (!SWIG_IsOK(ecode5)) { + SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "wrap_WebPEncodeLosslessBGR" "', argument " "5"" of type '" "int""'"); + } + arg5 = (int)(val5); + ecode6 = SWIG_AsVal_int(obj4, &val6); + if (!SWIG_IsOK(ecode6)) { + SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "wrap_WebPEncodeLosslessBGR" "', argument " "6"" of type '" "int""'"); + } + arg6 = (int)(val6); + ecode7 = SWIG_AsVal_int(obj5, &val7); + if (!SWIG_IsOK(ecode7)) { + SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "wrap_WebPEncodeLosslessBGR" "', argument " "7"" of type '" "int""'"); + } + arg7 = (int)(val7); + result = (uint8_t *)wrap_WebPEncodeLosslessBGR((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7); + { + resultobj = PyString_FromStringAndSize( + (const char*)result, + (result == NULL) ? 0 : ReturnedBufferSize("wrap_WebPEncodeLosslessBGR", arg3, arg4)); + } + if (SWIG_IsTmpObj(res4)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4))); + } else { + int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags)); + } + { + PyBuffer_Release(&rgb_buffer1); + } + if (SWIG_IsNewObj(res2)) free((char*)arg2); + if (SWIG_IsNewObj(res3)) free((char*)arg3); + free(result); + return resultobj; +fail: + { + PyBuffer_Release(&rgb_buffer1); + } + if (SWIG_IsNewObj(res2)) free((char*)arg2); + if (SWIG_IsNewObj(res3)) free((char*)arg3); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_wrap_WebPEncodeLosslessRGBA(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + uint8_t *arg1 = (uint8_t *) 0 ; + int *arg2 = (int *) 0 ; + int *arg3 = (int *) 0 ; + int *arg4 = (int *) 0 ; + int arg5 ; + int arg6 ; + int arg7 ; + Py_buffer rgb_buffer1 ; + int temp2 ; + int res2 = 0 ; + int temp3 ; + int res3 = 0 ; + int temp4 ; + int res4 = SWIG_TMPOBJ ; + int val5 ; + int ecode5 = 0 ; + int val6 ; + int ecode6 = 0 ; + int val7 ; + int ecode7 = 0 ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + PyObject * obj2 = 0 ; + PyObject * obj3 = 0 ; + PyObject * obj4 = 0 ; + PyObject * obj5 = 0 ; + uint8_t *result = 0 ; + + arg4 = &temp4; + if (!PyArg_ParseTuple(args,(char *)"OOOOOO:wrap_WebPEncodeLosslessRGBA",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail; + { + // NB: with Python < 2.6 the old style buffer protocol may be used: + // Py_ssize_t unused; + // PyObject_AsReadBuffer(obj0, (const void**)(&arg1), &unused); + if (!PyObject_CheckBuffer(obj0)) { + SWIG_exception_fail(SWIG_TypeError, + "in method 'wrap_WebPEncodeLosslessRGBA', argument 1" + " does not support the buffer interface"); + } + if (PyObject_GetBuffer(obj0, &rgb_buffer1, PyBUF_SIMPLE)) { + SWIG_exception_fail(SWIG_RuntimeError, + "in method 'wrap_WebPEncodeLosslessRGBA', unable to get buffer view"); + } + arg1 = (uint8_t *)rgb_buffer1.buf; + } + if (!(SWIG_IsOK((res2 = SWIG_ConvertPtr(obj1,SWIG_as_voidptrptr(&arg2),SWIGTYPE_p_int,0))))) { + int val; + int ecode = SWIG_AsVal_int(obj1, &val); + if (!SWIG_IsOK(ecode)) { + SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeLosslessRGBA" "', argument " "2"" of type '" "int""'"); + } + temp2 = (int)(val); + arg2 = &temp2; + res2 = SWIG_AddTmpMask(ecode); + } + if (!(SWIG_IsOK((res3 = SWIG_ConvertPtr(obj2,SWIG_as_voidptrptr(&arg3),SWIGTYPE_p_int,0))))) { + int val; + int ecode = SWIG_AsVal_int(obj2, &val); + if (!SWIG_IsOK(ecode)) { + SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeLosslessRGBA" "', argument " "3"" of type '" "int""'"); + } + temp3 = (int)(val); + arg3 = &temp3; + res3 = SWIG_AddTmpMask(ecode); + } + ecode5 = SWIG_AsVal_int(obj3, &val5); + if (!SWIG_IsOK(ecode5)) { + SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "wrap_WebPEncodeLosslessRGBA" "', argument " "5"" of type '" "int""'"); + } + arg5 = (int)(val5); + ecode6 = SWIG_AsVal_int(obj4, &val6); + if (!SWIG_IsOK(ecode6)) { + SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "wrap_WebPEncodeLosslessRGBA" "', argument " "6"" of type '" "int""'"); + } + arg6 = (int)(val6); + ecode7 = SWIG_AsVal_int(obj5, &val7); + if (!SWIG_IsOK(ecode7)) { + SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "wrap_WebPEncodeLosslessRGBA" "', argument " "7"" of type '" "int""'"); + } + arg7 = (int)(val7); + result = (uint8_t *)wrap_WebPEncodeLosslessRGBA((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7); + { + resultobj = PyString_FromStringAndSize( + (const char*)result, + (result == NULL) ? 0 : ReturnedBufferSize("wrap_WebPEncodeLosslessRGBA", arg3, arg4)); + } + if (SWIG_IsTmpObj(res4)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4))); + } else { + int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags)); + } + { + PyBuffer_Release(&rgb_buffer1); + } + if (SWIG_IsNewObj(res2)) free((char*)arg2); + if (SWIG_IsNewObj(res3)) free((char*)arg3); + free(result); + return resultobj; +fail: + { + PyBuffer_Release(&rgb_buffer1); + } + if (SWIG_IsNewObj(res2)) free((char*)arg2); + if (SWIG_IsNewObj(res3)) free((char*)arg3); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_wrap_WebPEncodeLosslessBGRA(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + uint8_t *arg1 = (uint8_t *) 0 ; + int *arg2 = (int *) 0 ; + int *arg3 = (int *) 0 ; + int *arg4 = (int *) 0 ; + int arg5 ; + int arg6 ; + int arg7 ; + Py_buffer rgb_buffer1 ; + int temp2 ; + int res2 = 0 ; + int temp3 ; + int res3 = 0 ; + int temp4 ; + int res4 = SWIG_TMPOBJ ; + int val5 ; + int ecode5 = 0 ; + int val6 ; + int ecode6 = 0 ; + int val7 ; + int ecode7 = 0 ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + PyObject * obj2 = 0 ; + PyObject * obj3 = 0 ; + PyObject * obj4 = 0 ; + PyObject * obj5 = 0 ; + uint8_t *result = 0 ; + + arg4 = &temp4; + if (!PyArg_ParseTuple(args,(char *)"OOOOOO:wrap_WebPEncodeLosslessBGRA",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail; + { + // NB: with Python < 2.6 the old style buffer protocol may be used: + // Py_ssize_t unused; + // PyObject_AsReadBuffer(obj0, (const void**)(&arg1), &unused); + if (!PyObject_CheckBuffer(obj0)) { + SWIG_exception_fail(SWIG_TypeError, + "in method 'wrap_WebPEncodeLosslessBGRA', argument 1" + " does not support the buffer interface"); + } + if (PyObject_GetBuffer(obj0, &rgb_buffer1, PyBUF_SIMPLE)) { + SWIG_exception_fail(SWIG_RuntimeError, + "in method 'wrap_WebPEncodeLosslessBGRA', unable to get buffer view"); + } + arg1 = (uint8_t *)rgb_buffer1.buf; + } + if (!(SWIG_IsOK((res2 = SWIG_ConvertPtr(obj1,SWIG_as_voidptrptr(&arg2),SWIGTYPE_p_int,0))))) { + int val; + int ecode = SWIG_AsVal_int(obj1, &val); + if (!SWIG_IsOK(ecode)) { + SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeLosslessBGRA" "', argument " "2"" of type '" "int""'"); + } + temp2 = (int)(val); + arg2 = &temp2; + res2 = SWIG_AddTmpMask(ecode); + } + if (!(SWIG_IsOK((res3 = SWIG_ConvertPtr(obj2,SWIG_as_voidptrptr(&arg3),SWIGTYPE_p_int,0))))) { + int val; + int ecode = SWIG_AsVal_int(obj2, &val); + if (!SWIG_IsOK(ecode)) { + SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeLosslessBGRA" "', argument " "3"" of type '" "int""'"); + } + temp3 = (int)(val); + arg3 = &temp3; + res3 = SWIG_AddTmpMask(ecode); + } + ecode5 = SWIG_AsVal_int(obj3, &val5); + if (!SWIG_IsOK(ecode5)) { + SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "wrap_WebPEncodeLosslessBGRA" "', argument " "5"" of type '" "int""'"); + } + arg5 = (int)(val5); + ecode6 = SWIG_AsVal_int(obj4, &val6); + if (!SWIG_IsOK(ecode6)) { + SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "wrap_WebPEncodeLosslessBGRA" "', argument " "6"" of type '" "int""'"); + } + arg6 = (int)(val6); + ecode7 = SWIG_AsVal_int(obj5, &val7); + if (!SWIG_IsOK(ecode7)) { + SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "wrap_WebPEncodeLosslessBGRA" "', argument " "7"" of type '" "int""'"); + } + arg7 = (int)(val7); + result = (uint8_t *)wrap_WebPEncodeLosslessBGRA((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7); + { + resultobj = PyString_FromStringAndSize( + (const char*)result, + (result == NULL) ? 0 : ReturnedBufferSize("wrap_WebPEncodeLosslessBGRA", arg3, arg4)); + } + if (SWIG_IsTmpObj(res4)) { + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4))); + } else { + int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; + resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags)); + } + { + PyBuffer_Release(&rgb_buffer1); + } + if (SWIG_IsNewObj(res2)) free((char*)arg2); + if (SWIG_IsNewObj(res3)) free((char*)arg3); + free(result); + return resultobj; +fail: + { + PyBuffer_Release(&rgb_buffer1); + } + if (SWIG_IsNewObj(res2)) free((char*)arg2); + if (SWIG_IsNewObj(res3)) free((char*)arg3); + return NULL; +} + + +static PyMethodDef SwigMethods[] = { + { "SWIG_PyInstanceMethod_New", SWIG_PyInstanceMethod_New, METH_O, NULL}, + { "WebPGetDecoderVersion", _wrap_WebPGetDecoderVersion, METH_VARARGS, (char *)"WebPGetDecoderVersion() -> int"}, + { "WebPGetInfo", _wrap_WebPGetInfo, METH_VARARGS, (char *)"WebPGetInfo(uint8_t data) -> (width, height)"}, + { "WebPDecodeRGB", _wrap_WebPDecodeRGB, METH_VARARGS, (char *)"WebPDecodeRGB(uint8_t data) -> (rgb, width, height)"}, + { "WebPDecodeRGBA", _wrap_WebPDecodeRGBA, METH_VARARGS, (char *)"WebPDecodeRGBA(uint8_t data) -> (rgb, width, height)"}, + { "WebPDecodeARGB", _wrap_WebPDecodeARGB, METH_VARARGS, (char *)"WebPDecodeARGB(uint8_t data) -> (rgb, width, height)"}, + { "WebPDecodeBGR", _wrap_WebPDecodeBGR, METH_VARARGS, (char *)"WebPDecodeBGR(uint8_t data) -> (rgb, width, height)"}, + { "WebPDecodeBGRA", _wrap_WebPDecodeBGRA, METH_VARARGS, (char *)"WebPDecodeBGRA(uint8_t data) -> (rgb, width, height)"}, + { "WebPGetEncoderVersion", _wrap_WebPGetEncoderVersion, METH_VARARGS, (char *)"WebPGetEncoderVersion() -> int"}, + { "wrap_WebPEncodeRGB", _wrap_wrap_WebPEncodeRGB, METH_VARARGS, (char *)"private, do not call directly."}, + { "wrap_WebPEncodeBGR", _wrap_wrap_WebPEncodeBGR, METH_VARARGS, (char *)"private, do not call directly."}, + { "wrap_WebPEncodeRGBA", _wrap_wrap_WebPEncodeRGBA, METH_VARARGS, (char *)"private, do not call directly."}, + { "wrap_WebPEncodeBGRA", _wrap_wrap_WebPEncodeBGRA, METH_VARARGS, (char *)"private, do not call directly."}, + { "wrap_WebPEncodeLosslessRGB", _wrap_wrap_WebPEncodeLosslessRGB, METH_VARARGS, (char *)"private, do not call directly."}, + { "wrap_WebPEncodeLosslessBGR", _wrap_wrap_WebPEncodeLosslessBGR, METH_VARARGS, (char *)"private, do not call directly."}, + { "wrap_WebPEncodeLosslessRGBA", _wrap_wrap_WebPEncodeLosslessRGBA, METH_VARARGS, (char *)"private, do not call directly."}, + { "wrap_WebPEncodeLosslessBGRA", _wrap_wrap_WebPEncodeLosslessBGRA, METH_VARARGS, (char *)"private, do not call directly."}, + { NULL, NULL, 0, NULL } +}; + + +/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */ + +static swig_type_info _swigt__p_char = {"_p_char", "char *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_int = {"_p_int", "int *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_uint8_t = {"_p_uint8_t", "uint8_t *", 0, 0, (void*)0, 0}; + +static swig_type_info *swig_type_initial[] = { + &_swigt__p_char, + &_swigt__p_int, + &_swigt__p_uint8_t, +}; + +static swig_cast_info _swigc__p_char[] = { {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_int[] = { {&_swigt__p_int, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_uint8_t[] = { {&_swigt__p_uint8_t, 0, 0, 0},{0, 0, 0, 0}}; + +static swig_cast_info *swig_cast_initial[] = { + _swigc__p_char, + _swigc__p_int, + _swigc__p_uint8_t, +}; + + +/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */ + +static swig_const_info swig_const_table[] = { +{0, 0, 0, 0.0, 0, 0}}; + +#ifdef __cplusplus +} +#endif +/* ----------------------------------------------------------------------------- + * Type initialization: + * This problem is tough by the requirement that no dynamic + * memory is used. Also, since swig_type_info structures store pointers to + * swig_cast_info structures and swig_cast_info structures store pointers back + * to swig_type_info structures, we need some lookup code at initialization. + * The idea is that swig generates all the structures that are needed. + * The runtime then collects these partially filled structures. + * The SWIG_InitializeModule function takes these initial arrays out of + * swig_module, and does all the lookup, filling in the swig_module.types + * array with the correct data and linking the correct swig_cast_info + * structures together. + * + * The generated swig_type_info structures are assigned statically to an initial + * array. We just loop through that array, and handle each type individually. + * First we lookup if this type has been already loaded, and if so, use the + * loaded structure instead of the generated one. Then we have to fill in the + * cast linked list. The cast data is initially stored in something like a + * two-dimensional array. Each row corresponds to a type (there are the same + * number of rows as there are in the swig_type_initial array). Each entry in + * a column is one of the swig_cast_info structures for that type. + * The cast_initial array is actually an array of arrays, because each row has + * a variable number of columns. So to actually build the cast linked list, + * we find the array of casts associated with the type, and loop through it + * adding the casts to the list. The one last trick we need to do is making + * sure the type pointer in the swig_cast_info struct is correct. + * + * First off, we lookup the cast->type name to see if it is already loaded. + * There are three cases to handle: + * 1) If the cast->type has already been loaded AND the type we are adding + * casting info to has not been loaded (it is in this module), THEN we + * replace the cast->type pointer with the type pointer that has already + * been loaded. + * 2) If BOTH types (the one we are adding casting info to, and the + * cast->type) are loaded, THEN the cast info has already been loaded by + * the previous module so we just ignore it. + * 3) Finally, if cast->type has not already been loaded, then we add that + * swig_cast_info to the linked list (because the cast->type) pointer will + * be correct. + * ----------------------------------------------------------------------------- */ + +#ifdef __cplusplus +extern "C" { +#if 0 +} /* c-mode */ +#endif +#endif + +#if 0 +#define SWIGRUNTIME_DEBUG +#endif + + +SWIGRUNTIME void +SWIG_InitializeModule(void *clientdata) { + size_t i; + swig_module_info *module_head, *iter; + int init; + + /* check to see if the circular list has been setup, if not, set it up */ + if (swig_module.next==0) { + /* Initialize the swig_module */ + swig_module.type_initial = swig_type_initial; + swig_module.cast_initial = swig_cast_initial; + swig_module.next = &swig_module; + init = 1; + } else { + init = 0; + } + + /* Try and load any already created modules */ + module_head = SWIG_GetModule(clientdata); + if (!module_head) { + /* This is the first module loaded for this interpreter */ + /* so set the swig module into the interpreter */ + SWIG_SetModule(clientdata, &swig_module); + } else { + /* the interpreter has loaded a SWIG module, but has it loaded this one? */ + iter=module_head; + do { + if (iter==&swig_module) { + /* Our module is already in the list, so there's nothing more to do. */ + return; + } + iter=iter->next; + } while (iter!= module_head); + + /* otherwise we must add our module into the list */ + swig_module.next = module_head->next; + module_head->next = &swig_module; + } + + /* When multiple interpreters are used, a module could have already been initialized in + a different interpreter, but not yet have a pointer in this interpreter. + In this case, we do not want to continue adding types... everything should be + set up already */ + if (init == 0) return; + + /* Now work on filling in swig_module.types */ +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: size %d\n", swig_module.size); +#endif + for (i = 0; i < swig_module.size; ++i) { + swig_type_info *type = 0; + swig_type_info *ret; + swig_cast_info *cast; + +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name); +#endif + + /* if there is another module already loaded */ + if (swig_module.next != &swig_module) { + type = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, swig_module.type_initial[i]->name); + } + if (type) { + /* Overwrite clientdata field */ +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: found type %s\n", type->name); +#endif + if (swig_module.type_initial[i]->clientdata) { + type->clientdata = swig_module.type_initial[i]->clientdata; +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: found and overwrite type %s \n", type->name); +#endif + } + } else { + type = swig_module.type_initial[i]; + } + + /* Insert casting types */ + cast = swig_module.cast_initial[i]; + while (cast->type) { + /* Don't need to add information already in the list */ + ret = 0; +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: look cast %s\n", cast->type->name); +#endif + if (swig_module.next != &swig_module) { + ret = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, cast->type->name); +#ifdef SWIGRUNTIME_DEBUG + if (ret) printf("SWIG_InitializeModule: found cast %s\n", ret->name); +#endif + } + if (ret) { + if (type == swig_module.type_initial[i]) { +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: skip old type %s\n", ret->name); +#endif + cast->type = ret; + ret = 0; + } else { + /* Check for casting already in the list */ + swig_cast_info *ocast = SWIG_TypeCheck(ret->name, type); +#ifdef SWIGRUNTIME_DEBUG + if (ocast) printf("SWIG_InitializeModule: skip old cast %s\n", ret->name); +#endif + if (!ocast) ret = 0; + } + } + + if (!ret) { +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: adding cast %s\n", cast->type->name); +#endif + if (type->cast) { + type->cast->prev = cast; + cast->next = type->cast; + } + type->cast = cast; + } + cast++; + } + /* Set entry in modules->types array equal to the type */ + swig_module.types[i] = type; + } + swig_module.types[i] = 0; + +#ifdef SWIGRUNTIME_DEBUG + printf("**** SWIG_InitializeModule: Cast List ******\n"); + for (i = 0; i < swig_module.size; ++i) { + int j = 0; + swig_cast_info *cast = swig_module.cast_initial[i]; + printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name); + while (cast->type) { + printf("SWIG_InitializeModule: cast type %s\n", cast->type->name); + cast++; + ++j; + } + printf("---- Total casts: %d\n",j); + } + printf("**** SWIG_InitializeModule: Cast List ******\n"); +#endif +} + +/* This function will propagate the clientdata field of type to +* any new swig_type_info structures that have been added into the list +* of equivalent types. It is like calling +* SWIG_TypeClientData(type, clientdata) a second time. +*/ +SWIGRUNTIME void +SWIG_PropagateClientData(void) { + size_t i; + swig_cast_info *equiv; + static int init_run = 0; + + if (init_run) return; + init_run = 1; + + for (i = 0; i < swig_module.size; i++) { + if (swig_module.types[i]->clientdata) { + equiv = swig_module.types[i]->cast; + while (equiv) { + if (!equiv->converter) { + if (equiv->type && !equiv->type->clientdata) + SWIG_TypeClientData(equiv->type, swig_module.types[i]->clientdata); + } + equiv = equiv->next; + } + } + } +} + +#ifdef __cplusplus +#if 0 +{ + /* c-mode */ +#endif +} +#endif + + + +#ifdef __cplusplus +extern "C" { +#endif + + /* Python-specific SWIG API */ +#define SWIG_newvarlink() SWIG_Python_newvarlink() +#define SWIG_addvarlink(p, name, get_attr, set_attr) SWIG_Python_addvarlink(p, name, get_attr, set_attr) +#define SWIG_InstallConstants(d, constants) SWIG_Python_InstallConstants(d, constants) + + /* ----------------------------------------------------------------------------- + * global variable support code. + * ----------------------------------------------------------------------------- */ + + typedef struct swig_globalvar { + char *name; /* Name of global variable */ + PyObject *(*get_attr)(void); /* Return the current value */ + int (*set_attr)(PyObject *); /* Set the value */ + struct swig_globalvar *next; + } swig_globalvar; + + typedef struct swig_varlinkobject { + PyObject_HEAD + swig_globalvar *vars; + } swig_varlinkobject; + + SWIGINTERN PyObject * + swig_varlink_repr(swig_varlinkobject *SWIGUNUSEDPARM(v)) { +#if PY_VERSION_HEX >= 0x03000000 + return PyUnicode_InternFromString(""); +#else + return PyString_FromString(""); +#endif + } + + SWIGINTERN PyObject * + swig_varlink_str(swig_varlinkobject *v) { +#if PY_VERSION_HEX >= 0x03000000 + PyObject *str = PyUnicode_InternFromString("("); + PyObject *tail; + PyObject *joined; + swig_globalvar *var; + for (var = v->vars; var; var=var->next) { + tail = PyUnicode_FromString(var->name); + joined = PyUnicode_Concat(str, tail); + Py_DecRef(str); + Py_DecRef(tail); + str = joined; + if (var->next) { + tail = PyUnicode_InternFromString(", "); + joined = PyUnicode_Concat(str, tail); + Py_DecRef(str); + Py_DecRef(tail); + str = joined; + } + } + tail = PyUnicode_InternFromString(")"); + joined = PyUnicode_Concat(str, tail); + Py_DecRef(str); + Py_DecRef(tail); + str = joined; +#else + PyObject *str = PyString_FromString("("); + swig_globalvar *var; + for (var = v->vars; var; var=var->next) { + PyString_ConcatAndDel(&str,PyString_FromString(var->name)); + if (var->next) PyString_ConcatAndDel(&str,PyString_FromString(", ")); + } + PyString_ConcatAndDel(&str,PyString_FromString(")")); +#endif + return str; + } + + SWIGINTERN int + swig_varlink_print(swig_varlinkobject *v, FILE *fp, int SWIGUNUSEDPARM(flags)) { + char *tmp; + PyObject *str = swig_varlink_str(v); + fprintf(fp,"Swig global variables "); + fprintf(fp,"%s\n", tmp = SWIG_Python_str_AsChar(str)); + SWIG_Python_str_DelForPy3(tmp); + Py_DECREF(str); + return 0; + } + + SWIGINTERN void + swig_varlink_dealloc(swig_varlinkobject *v) { + swig_globalvar *var = v->vars; + while (var) { + swig_globalvar *n = var->next; + free(var->name); + free(var); + var = n; + } + } + + SWIGINTERN PyObject * + swig_varlink_getattr(swig_varlinkobject *v, char *n) { + PyObject *res = NULL; + swig_globalvar *var = v->vars; + while (var) { + if (strcmp(var->name,n) == 0) { + res = (*var->get_attr)(); + break; + } + var = var->next; + } + if (res == NULL && !PyErr_Occurred()) { + PyErr_Format(PyExc_AttributeError, "Unknown C global variable '%s'", n); + } + return res; + } + + SWIGINTERN int + swig_varlink_setattr(swig_varlinkobject *v, char *n, PyObject *p) { + int res = 1; + swig_globalvar *var = v->vars; + while (var) { + if (strcmp(var->name,n) == 0) { + res = (*var->set_attr)(p); + break; + } + var = var->next; + } + if (res == 1 && !PyErr_Occurred()) { + PyErr_Format(PyExc_AttributeError, "Unknown C global variable '%s'", n); + } + return res; + } + + SWIGINTERN PyTypeObject* + swig_varlink_type(void) { + static char varlink__doc__[] = "Swig var link object"; + static PyTypeObject varlink_type; + static int type_init = 0; + if (!type_init) { + const PyTypeObject tmp = { +#if PY_VERSION_HEX >= 0x03000000 + PyVarObject_HEAD_INIT(NULL, 0) +#else + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ +#endif + (char *)"swigvarlink", /* tp_name */ + sizeof(swig_varlinkobject), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor) swig_varlink_dealloc, /* tp_dealloc */ + (printfunc) swig_varlink_print, /* tp_print */ + (getattrfunc) swig_varlink_getattr, /* tp_getattr */ + (setattrfunc) swig_varlink_setattr, /* tp_setattr */ + 0, /* tp_compare */ + (reprfunc) swig_varlink_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + (reprfunc) swig_varlink_str, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + 0, /* tp_flags */ + varlink__doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ +#if PY_VERSION_HEX >= 0x02020000 + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* tp_iter -> tp_weaklist */ +#endif +#if PY_VERSION_HEX >= 0x02030000 + 0, /* tp_del */ +#endif +#if PY_VERSION_HEX >= 0x02060000 + 0, /* tp_version_tag */ +#endif +#if PY_VERSION_HEX >= 0x03040000 + 0, /* tp_finalize */ +#endif +#ifdef COUNT_ALLOCS + 0, /* tp_allocs */ + 0, /* tp_frees */ + 0, /* tp_maxalloc */ +#if PY_VERSION_HEX >= 0x02050000 + 0, /* tp_prev */ +#endif + 0 /* tp_next */ +#endif + }; + varlink_type = tmp; + type_init = 1; +#if PY_VERSION_HEX < 0x02020000 + varlink_type.ob_type = &PyType_Type; +#else + if (PyType_Ready(&varlink_type) < 0) + return NULL; +#endif + } + return &varlink_type; + } + + /* Create a variable linking object for use later */ + SWIGINTERN PyObject * + SWIG_Python_newvarlink(void) { + swig_varlinkobject *result = PyObject_NEW(swig_varlinkobject, swig_varlink_type()); + if (result) { + result->vars = 0; + } + return ((PyObject*) result); + } + + SWIGINTERN void + SWIG_Python_addvarlink(PyObject *p, char *name, PyObject *(*get_attr)(void), int (*set_attr)(PyObject *p)) { + swig_varlinkobject *v = (swig_varlinkobject *) p; + swig_globalvar *gv = (swig_globalvar *) malloc(sizeof(swig_globalvar)); + if (gv) { + size_t size = strlen(name)+1; + gv->name = (char *)malloc(size); + if (gv->name) { + strncpy(gv->name,name,size); + gv->get_attr = get_attr; + gv->set_attr = set_attr; + gv->next = v->vars; + } + } + v->vars = gv; + } + + SWIGINTERN PyObject * + SWIG_globals(void) { + static PyObject *_SWIG_globals = 0; + if (!_SWIG_globals) _SWIG_globals = SWIG_newvarlink(); + return _SWIG_globals; + } + + /* ----------------------------------------------------------------------------- + * constants/methods manipulation + * ----------------------------------------------------------------------------- */ + + /* Install Constants */ + SWIGINTERN void + SWIG_Python_InstallConstants(PyObject *d, swig_const_info constants[]) { + PyObject *obj = 0; + size_t i; + for (i = 0; constants[i].type; ++i) { + switch(constants[i].type) { + case SWIG_PY_POINTER: + obj = SWIG_InternalNewPointerObj(constants[i].pvalue, *(constants[i]).ptype,0); + break; + case SWIG_PY_BINARY: + obj = SWIG_NewPackedObj(constants[i].pvalue, constants[i].lvalue, *(constants[i].ptype)); + break; + default: + obj = 0; + break; + } + if (obj) { + PyDict_SetItemString(d, constants[i].name, obj); + Py_DECREF(obj); + } + } + } + + /* -----------------------------------------------------------------------------*/ + /* Fix SwigMethods to carry the callback ptrs when needed */ + /* -----------------------------------------------------------------------------*/ + + SWIGINTERN void + SWIG_Python_FixMethods(PyMethodDef *methods, + swig_const_info *const_table, + swig_type_info **types, + swig_type_info **types_initial) { + size_t i; + for (i = 0; methods[i].ml_name; ++i) { + const char *c = methods[i].ml_doc; + if (!c) continue; + c = strstr(c, "swig_ptr: "); + if (c) { + int j; + swig_const_info *ci = 0; + const char *name = c + 10; + for (j = 0; const_table[j].type; ++j) { + if (strncmp(const_table[j].name, name, + strlen(const_table[j].name)) == 0) { + ci = &(const_table[j]); + break; + } + } + if (ci) { + void *ptr = (ci->type == SWIG_PY_POINTER) ? ci->pvalue : 0; + if (ptr) { + size_t shift = (ci->ptype) - types; + swig_type_info *ty = types_initial[shift]; + size_t ldoc = (c - methods[i].ml_doc); + size_t lptr = strlen(ty->name)+2*sizeof(void*)+2; + char *ndoc = (char*)malloc(ldoc + lptr + 10); + if (ndoc) { + char *buff = ndoc; + memcpy(buff, methods[i].ml_doc, ldoc); + buff += ldoc; + memcpy(buff, "swig_ptr: ", 10); + buff += 10; + SWIG_PackVoidPtr(buff, ptr, ty->name, lptr); + methods[i].ml_doc = ndoc; + } + } + } + } + } + } + +#ifdef __cplusplus +} +#endif + +/* -----------------------------------------------------------------------------* + * Partial Init method + * -----------------------------------------------------------------------------*/ + +#ifdef __cplusplus +extern "C" +#endif + +SWIGEXPORT +#if PY_VERSION_HEX >= 0x03000000 +PyObject* +#else +void +#endif +SWIG_init(void) { + PyObject *m, *d, *md; +#if PY_VERSION_HEX >= 0x03000000 + static struct PyModuleDef SWIG_module = { +# if PY_VERSION_HEX >= 0x03020000 + PyModuleDef_HEAD_INIT, +# else + { + PyObject_HEAD_INIT(NULL) + NULL, /* m_init */ + 0, /* m_index */ + NULL, /* m_copy */ + }, +# endif + (char *) SWIG_name, + NULL, + -1, + SwigMethods, + NULL, + NULL, + NULL, + NULL + }; +#endif + +#if defined(SWIGPYTHON_BUILTIN) + static SwigPyClientData SwigPyObject_clientdata = { + 0, 0, 0, 0, 0, 0, 0 + }; + static PyGetSetDef this_getset_def = { + (char *)"this", &SwigPyBuiltin_ThisClosure, NULL, NULL, NULL + }; + static SwigPyGetSet thisown_getset_closure = { + SwigPyObject_own, + SwigPyObject_own + }; + static PyGetSetDef thisown_getset_def = { + (char *)"thisown", SwigPyBuiltin_GetterClosure, SwigPyBuiltin_SetterClosure, NULL, &thisown_getset_closure + }; + PyTypeObject *builtin_pytype; + int builtin_base_count; + swig_type_info *builtin_basetype; + PyObject *tuple; + PyGetSetDescrObject *static_getset; + PyTypeObject *metatype; + PyTypeObject *swigpyobject; + SwigPyClientData *cd; + PyObject *public_interface, *public_symbol; + PyObject *this_descr; + PyObject *thisown_descr; + PyObject *self = 0; + int i; + + (void)builtin_pytype; + (void)builtin_base_count; + (void)builtin_basetype; + (void)tuple; + (void)static_getset; + (void)self; + + /* Metaclass is used to implement static member variables */ + metatype = SwigPyObjectType(); + assert(metatype); +#endif + + /* Fix SwigMethods to carry the callback ptrs when needed */ + SWIG_Python_FixMethods(SwigMethods, swig_const_table, swig_types, swig_type_initial); + +#if PY_VERSION_HEX >= 0x03000000 + m = PyModule_Create(&SWIG_module); +#else + m = Py_InitModule((char *) SWIG_name, SwigMethods); +#endif + + md = d = PyModule_GetDict(m); + (void)md; + + SWIG_InitializeModule(0); + +#ifdef SWIGPYTHON_BUILTIN + swigpyobject = SwigPyObject_TypeOnce(); + + SwigPyObject_stype = SWIG_MangledTypeQuery("_p_SwigPyObject"); + assert(SwigPyObject_stype); + cd = (SwigPyClientData*) SwigPyObject_stype->clientdata; + if (!cd) { + SwigPyObject_stype->clientdata = &SwigPyObject_clientdata; + SwigPyObject_clientdata.pytype = swigpyobject; + } else if (swigpyobject->tp_basicsize != cd->pytype->tp_basicsize) { + PyErr_SetString(PyExc_RuntimeError, "Import error: attempted to load two incompatible swig-generated modules."); +# if PY_VERSION_HEX >= 0x03000000 + return NULL; +# else + return; +# endif + } + + /* All objects have a 'this' attribute */ + this_descr = PyDescr_NewGetSet(SwigPyObject_type(), &this_getset_def); + (void)this_descr; + + /* All objects have a 'thisown' attribute */ + thisown_descr = PyDescr_NewGetSet(SwigPyObject_type(), &thisown_getset_def); + (void)thisown_descr; + + public_interface = PyList_New(0); + public_symbol = 0; + (void)public_symbol; + + PyDict_SetItemString(md, "__all__", public_interface); + Py_DECREF(public_interface); + for (i = 0; SwigMethods[i].ml_name != NULL; ++i) + SwigPyBuiltin_AddPublicSymbol(public_interface, SwigMethods[i].ml_name); + for (i = 0; swig_const_table[i].name != 0; ++i) + SwigPyBuiltin_AddPublicSymbol(public_interface, swig_const_table[i].name); +#endif + + SWIG_InstallConstants(d,swig_const_table); + +#if PY_VERSION_HEX >= 0x03000000 + return m; +#else + return; +#endif +} + diff --git a/third-party/webp/libwebp/swig/setup.py b/third-party/webp/libwebp/swig/setup.py new file mode 100644 index 0000000000..3a3bfe190f --- /dev/null +++ b/third-party/webp/libwebp/swig/setup.py @@ -0,0 +1,40 @@ +#!/usr/bin/python + +"""distutils script for libwebp python module.""" + +from distutils.core import setup +from distutils.extension import Extension +import os +import shutil +import tempfile + +tmpdir = tempfile.mkdtemp() +package = "com.google.webp" +package_path = os.path.join(tmpdir, *package.split(".")) +os.makedirs(package_path) + +# Create __init_.py files along the package path. +initpy_path = tmpdir +for d in package.split("."): + initpy_path = os.path.join(initpy_path, d) + open(os.path.join(initpy_path, "__init__.py"), "w").close() + +shutil.copy2("libwebp.py", package_path) +setup(name="libwebp", + version="0.0", + description="libwebp python wrapper", + long_description="Provides access to 'simple' libwebp decode interface", + license="BSD", + url="http://developers.google.com/speed/webp", + ext_package=package, + ext_modules=[Extension("_libwebp", + ["libwebp_python_wrap.c"], + libraries=["webp"], + ), + ], + package_dir={"": tmpdir}, + packages=["com", "com.google", "com.google.webp"], + py_modules=[package + ".libwebp"], + ) + +shutil.rmtree(tmpdir) diff --git a/third-party/webp/libwebp/tests/README.md b/third-party/webp/libwebp/tests/README.md new file mode 100644 index 0000000000..91daba26d6 --- /dev/null +++ b/third-party/webp/libwebp/tests/README.md @@ -0,0 +1,18 @@ +# Tests + +This is a collection of tests for the libwebp libraries, currently covering +fuzzing through the APIs. Additional test vector coverage can be found at: +https://chromium.googlesource.com/webm/libwebp-test-data + +## Building + +### Fuzzers + +Follow the [build instructions](../doc/building.md) for libwebp, optionally +adding build flags for various sanitizers (e.g., -fsanitize=address). + +`fuzzer/makefile.unix` can then be used to compile the fuzzer targets: + +```shell +$ make -C fuzzer -f makefile.unix +``` diff --git a/third-party/webp/libwebp/tests/fuzzer/advanced_api_fuzzer.c b/third-party/webp/libwebp/tests/fuzzer/advanced_api_fuzzer.c new file mode 100644 index 0000000000..c8fb176e11 --- /dev/null +++ b/third-party/webp/libwebp/tests/fuzzer/advanced_api_fuzzer.c @@ -0,0 +1,139 @@ +// Copyright 2018 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include "./fuzz_utils.h" +#include "src/utils/rescaler_utils.h" +#include "src/webp/decode.h" + +int LLVMFuzzerTestOneInput(const uint8_t* const data, size_t size) { + WebPDecoderConfig config; + if (!WebPInitDecoderConfig(&config)) return 0; + if (WebPGetFeatures(data, size, &config.input) != VP8_STATUS_OK) return 0; + if ((size_t)config.input.width * config.input.height > kFuzzPxLimit) return 0; + + // Using two independent criteria ensures that all combinations of options + // can reach each path at the decoding stage, with meaningful differences. + + const uint8_t value = FuzzHash(data, size); + const float factor = value / 255.f; // 0-1 + + config.options.flip = value & 1; + config.options.bypass_filtering = value & 2; + config.options.no_fancy_upsampling = value & 4; + config.options.use_threads = value & 8; + if (size & 1) { + config.options.use_cropping = 1; + config.options.crop_width = (int)(config.input.width * (1 - factor)); + config.options.crop_height = (int)(config.input.height * (1 - factor)); + config.options.crop_left = config.input.width - config.options.crop_width; + config.options.crop_top = config.input.height - config.options.crop_height; + } + if (size & 2) { + int strength = (int)(factor * 100); + config.options.dithering_strength = strength; + config.options.alpha_dithering_strength = 100 - strength; + } + if (size & 4) { + config.options.use_scaling = 1; + config.options.scaled_width = (int)(config.input.width * factor * 2); + config.options.scaled_height = (int)(config.input.height * factor * 2); + } + +#if defined(WEBP_REDUCE_CSP) + config.output.colorspace = (value & 1) + ? ((value & 2) ? MODE_RGBA : MODE_BGRA) + : ((value & 2) ? MODE_rgbA : MODE_bgrA); +#else + config.output.colorspace = (WEBP_CSP_MODE)(value % MODE_LAST); +#endif // WEBP_REDUCE_CSP + + for (int i = 0; i < 2; ++i) { + if (i == 1) { + // Use the bitstream data to generate extreme ranges for the options. An + // alternative approach would be to use a custom corpus containing webp + // files prepended with sizeof(config.options) zeroes to allow the fuzzer + // to modify these independently. + const int data_offset = 50; + if (data_offset + sizeof(config.options) >= size) break; + memcpy(&config.options, data + data_offset, sizeof(config.options)); + + // Skip easily avoidable out-of-memory fuzzing errors. + if (config.options.use_scaling) { + int scaled_width = config.options.scaled_width; + int scaled_height = config.options.scaled_height; + if (WebPRescalerGetScaledDimensions(config.input.width, + config.input.height, &scaled_width, + &scaled_height)) { + size_t fuzz_px_limit = kFuzzPxLimit; + if (scaled_width != config.input.width || + scaled_height != config.input.height) { + // Using the WebPRescalerImport internally can significantly slow + // down the execution. Avoid timeouts due to that. + fuzz_px_limit /= 2; + } + // A big output canvas can lead to out-of-memory and timeout issues, + // but a big internal working buffer can too. Also, rescaling from a + // very wide input image to a very tall canvas can be as slow as + // decoding a huge number of pixels. Avoid timeouts due to these. + const uint64_t max_num_operations = + (uint64_t)Max(scaled_width, config.input.width) * + Max(scaled_height, config.input.height); + if (max_num_operations > fuzz_px_limit) { + break; + } + } + } + } + if (size % 3) { + // Decodes incrementally in chunks of increasing size. + WebPIDecoder* idec = WebPIDecode(NULL, 0, &config); + if (!idec) return 0; + VP8StatusCode status; + if (size & 8) { + size_t available_size = value + 1; + while (1) { + if (available_size > size) available_size = size; + status = WebPIUpdate(idec, data, available_size); + if (status != VP8_STATUS_SUSPENDED || available_size == size) break; + available_size *= 2; + } + } else { + // WebPIAppend expects new data and its size with each call. + // Implemented here by simply advancing the pointer into data. + const uint8_t* new_data = data; + size_t new_size = value + 1; + while (1) { + if (new_data + new_size > data + size) { + new_size = data + size - new_data; + } + status = WebPIAppend(idec, new_data, new_size); + if (status != VP8_STATUS_SUSPENDED || new_size == 0) break; + new_data += new_size; + new_size *= 2; + } + } + WebPIDelete(idec); + } else { + WebPDecode(data, size, &config); + } + + WebPFreeDecBuffer(&config.output); + } + return 0; +} diff --git a/third-party/webp/libwebp/tests/fuzzer/animation_api_fuzzer.c b/third-party/webp/libwebp/tests/fuzzer/animation_api_fuzzer.c new file mode 100644 index 0000000000..187ed24e7c --- /dev/null +++ b/third-party/webp/libwebp/tests/fuzzer/animation_api_fuzzer.c @@ -0,0 +1,78 @@ +// Copyright 2018 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + +#include "./fuzz_utils.h" +#include "src/webp/decode.h" +#include "src/webp/demux.h" +#include "src/webp/mux_types.h" + +int LLVMFuzzerTestOneInput(const uint8_t* const data, size_t size) { + WebPData webp_data; + WebPDataInit(&webp_data); + webp_data.size = size; + webp_data.bytes = data; + + // WebPAnimDecoderNew uses WebPDemux internally to calloc canvas size. + WebPDemuxer* const demux = WebPDemux(&webp_data); + if (!demux) return 0; + const uint32_t cw = WebPDemuxGetI(demux, WEBP_FF_CANVAS_WIDTH); + const uint32_t ch = WebPDemuxGetI(demux, WEBP_FF_CANVAS_HEIGHT); + if ((size_t)cw * ch > kFuzzPxLimit) { + WebPDemuxDelete(demux); + return 0; + } + + // In addition to canvas size, check each frame separately. + WebPIterator iter; + for (int i = 0; i < kFuzzFrameLimit; i++) { + if (!WebPDemuxGetFrame(demux, i + 1, &iter)) break; + int w, h; + if (WebPGetInfo(iter.fragment.bytes, iter.fragment.size, &w, &h)) { + if ((size_t)w * h > kFuzzPxLimit) { // image size of the frame payload + WebPDemuxReleaseIterator(&iter); + WebPDemuxDelete(demux); + return 0; + } + } + } + + WebPDemuxReleaseIterator(&iter); + WebPDemuxDelete(demux); + + WebPAnimDecoderOptions dec_options; + if (!WebPAnimDecoderOptionsInit(&dec_options)) return 0; + + dec_options.use_threads = size & 1; + // Animations only support 4 (of 12) modes. + dec_options.color_mode = (WEBP_CSP_MODE)(size % MODE_LAST); + if (dec_options.color_mode != MODE_BGRA && + dec_options.color_mode != MODE_rgbA && + dec_options.color_mode != MODE_bgrA) { + dec_options.color_mode = MODE_RGBA; + } + + WebPAnimDecoder* dec = WebPAnimDecoderNew(&webp_data, &dec_options); + if (!dec) return 0; + + for (int i = 0; i < kFuzzFrameLimit; i++) { + uint8_t* buf; + int timestamp; + if (!WebPAnimDecoderGetNext(dec, &buf, ×tamp)) break; + } + + WebPAnimDecoderDelete(dec); + return 0; +} diff --git a/third-party/webp/libwebp/tests/fuzzer/animdecoder_fuzzer.cc b/third-party/webp/libwebp/tests/fuzzer/animdecoder_fuzzer.cc new file mode 100644 index 0000000000..a79712dc26 --- /dev/null +++ b/third-party/webp/libwebp/tests/fuzzer/animdecoder_fuzzer.cc @@ -0,0 +1,52 @@ +// Copyright 2020 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + +#include "examples/anim_util.h" +#include "imageio/imageio_util.h" +#include "src/webp/demux.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + // WebPAnimDecoderGetInfo() is too late to check the canvas size as + // WebPAnimDecoderNew() will handle the allocations. + WebPBitstreamFeatures features; + if (WebPGetFeatures(data, size, &features) == VP8_STATUS_OK) { + if (!ImgIoUtilCheckSizeArgumentsOverflow(features.width * 4, + features.height)) { + return 0; + } + } + + // decode everything as an animation + WebPData webp_data = { data, size }; + WebPAnimDecoder* const dec = WebPAnimDecoderNew(&webp_data, NULL); + if (dec == NULL) return 0; + + WebPAnimInfo info; + if (!WebPAnimDecoderGetInfo(dec, &info)) goto End; + if (!ImgIoUtilCheckSizeArgumentsOverflow(info.canvas_width * 4, + info.canvas_height)) { + goto End; + } + + while (WebPAnimDecoderHasMoreFrames(dec)) { + uint8_t* buf; + int timestamp; + if (!WebPAnimDecoderGetNext(dec, &buf, ×tamp)) break; + } + End: + WebPAnimDecoderDelete(dec); + return 0; +} diff --git a/third-party/webp/libwebp/tests/fuzzer/animencoder_fuzzer.cc b/third-party/webp/libwebp/tests/fuzzer/animencoder_fuzzer.cc new file mode 100644 index 0000000000..ef6ec1e494 --- /dev/null +++ b/third-party/webp/libwebp/tests/fuzzer/animencoder_fuzzer.cc @@ -0,0 +1,188 @@ +// Copyright 2018 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include "./fuzz_utils.h" +#include "src/webp/encode.h" +#include "src/webp/mux.h" + +namespace { + +const VP8CPUInfo default_VP8GetCPUInfo = VP8GetCPUInfo; + +int AddFrame(WebPAnimEncoder** const enc, + const WebPAnimEncoderOptions& anim_config, int* const width, + int* const height, int timestamp_ms, const uint8_t data[], + size_t size, uint32_t* const bit_pos) { + if (enc == nullptr || width == nullptr || height == nullptr) { + fprintf(stderr, "NULL parameters.\n"); + if (enc != nullptr) WebPAnimEncoderDelete(*enc); + abort(); + } + + // Init the source picture. + WebPPicture pic; + if (!WebPPictureInit(&pic)) { + fprintf(stderr, "WebPPictureInit failed.\n"); + WebPAnimEncoderDelete(*enc); + abort(); + } + pic.use_argb = Extract(1, data, size, bit_pos); + + // Read the source picture. + if (!ExtractSourcePicture(&pic, data, size, bit_pos)) { + const WebPEncodingError error_code = pic.error_code; + WebPAnimEncoderDelete(*enc); + WebPPictureFree(&pic); + if (error_code == VP8_ENC_ERROR_OUT_OF_MEMORY) return 0; + fprintf(stderr, "Can't read input image. Error code: %d\n", error_code); + abort(); + } + + // Crop and scale. + if (*enc == nullptr) { // First frame will set canvas width and height. + if (!ExtractAndCropOrScale(&pic, data, size, bit_pos)) { + const WebPEncodingError error_code = pic.error_code; + WebPPictureFree(&pic); + if (error_code == VP8_ENC_ERROR_OUT_OF_MEMORY) return 0; + fprintf(stderr, "ExtractAndCropOrScale failed. Error code: %d\n", + error_code); + abort(); + } + } else { // Other frames will be resized to the first frame's dimensions. + if (!WebPPictureRescale(&pic, *width, *height)) { + const WebPEncodingError error_code = pic.error_code; + WebPAnimEncoderDelete(*enc); + WebPPictureFree(&pic); + if (error_code == VP8_ENC_ERROR_OUT_OF_MEMORY) return 0; + fprintf(stderr, + "WebPPictureRescale failed. Size: %d,%d. Error code: %d\n", + *width, *height, error_code); + abort(); + } + } + + // Create encoder if it doesn't exist. + if (*enc == nullptr) { + *width = pic.width; + *height = pic.height; + *enc = WebPAnimEncoderNew(*width, *height, &anim_config); + if (*enc == nullptr) { + WebPPictureFree(&pic); + return 0; + } + } + + // Create frame encoding config. + WebPConfig config; + if (!ExtractWebPConfig(&config, data, size, bit_pos)) { + fprintf(stderr, "ExtractWebPConfig failed.\n"); + WebPAnimEncoderDelete(*enc); + WebPPictureFree(&pic); + abort(); + } + // Skip slow settings on big images, it's likely to timeout. + if (pic.width * pic.height > 32 * 32) { + config.method = (config.method > 4) ? 4 : config.method; + config.quality = (config.quality > 99.0f) ? 99.0f : config.quality; + config.alpha_quality = + (config.alpha_quality > 99) ? 99 : config.alpha_quality; + } + + // Encode. + if (!WebPAnimEncoderAdd(*enc, &pic, timestamp_ms, &config)) { + const WebPEncodingError error_code = pic.error_code; + WebPAnimEncoderDelete(*enc); + WebPPictureFree(&pic); + // Tolerate failures when running under the nallocfuzz engine as + // WebPAnimEncoderAdd() may fail due to memory allocation errors outside of + // the encoder; in muxer functions that return booleans for instance. + if (error_code == VP8_ENC_ERROR_OUT_OF_MEMORY || + error_code == VP8_ENC_ERROR_BAD_WRITE || + getenv("NALLOC_FUZZ_VERSION") != nullptr) { + return 0; + } + fprintf(stderr, "WebPEncode failed. Error code: %d\n", error_code); + abort(); + } + + WebPPictureFree(&pic); + return 1; +} + +} // namespace + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* const data, size_t size) { + WebPAnimEncoder* enc = nullptr; + int width = 0, height = 0, timestamp_ms = 0; + uint32_t bit_pos = 0; + + ExtractAndDisableOptimizations(default_VP8GetCPUInfo, data, size, &bit_pos); + + // Extract a configuration from the packed bits. + WebPAnimEncoderOptions anim_config; + if (!WebPAnimEncoderOptionsInit(&anim_config)) { + fprintf(stderr, "WebPAnimEncoderOptionsInit failed.\n"); + abort(); + } + anim_config.minimize_size = Extract(1, data, size, &bit_pos); + anim_config.kmax = Extract(15, data, size, &bit_pos); + const int min_kmin = (anim_config.kmax > 1) ? (anim_config.kmax / 2) : 0; + const int max_kmin = (anim_config.kmax > 1) ? (anim_config.kmax - 1) : 0; + anim_config.kmin = + min_kmin + Extract((uint32_t)(max_kmin - min_kmin), data, size, &bit_pos); + anim_config.allow_mixed = Extract(1, data, size, &bit_pos); + anim_config.verbose = 0; + + const int nb_frames = 1 + Extract(15, data, size, &bit_pos); + + // For each frame. + for (int i = 0; i < nb_frames; ++i) { + if (!AddFrame(&enc, anim_config, &width, &height, timestamp_ms, data, size, + &bit_pos)) { + return 0; + } + + timestamp_ms += (1 << (2 + Extract(15, data, size, &bit_pos))) + + Extract(1, data, size, &bit_pos); // [1..131073], arbitrary + } + + // Assemble. + if (!WebPAnimEncoderAdd(enc, nullptr, timestamp_ms, nullptr)) { + fprintf(stderr, "Last WebPAnimEncoderAdd failed: %s.\n", + WebPAnimEncoderGetError(enc)); + WebPAnimEncoderDelete(enc); + abort(); + } + WebPData webp_data; + WebPDataInit(&webp_data); + // Tolerate failures when running under the nallocfuzz engine as allocations + // during assembly may fail. + if (!WebPAnimEncoderAssemble(enc, &webp_data) && + getenv("NALLOC_FUZZ_VERSION") == nullptr) { + fprintf(stderr, "WebPAnimEncoderAssemble failed: %s.\n", + WebPAnimEncoderGetError(enc)); + WebPAnimEncoderDelete(enc); + WebPDataClear(&webp_data); + abort(); + } + + WebPAnimEncoderDelete(enc); + WebPDataClear(&webp_data); + return 0; +} diff --git a/third-party/webp/libwebp/tests/fuzzer/enc_dec_fuzzer.cc b/third-party/webp/libwebp/tests/fuzzer/enc_dec_fuzzer.cc new file mode 100644 index 0000000000..c5d46ae0ed --- /dev/null +++ b/third-party/webp/libwebp/tests/fuzzer/enc_dec_fuzzer.cc @@ -0,0 +1,161 @@ +// Copyright 2018 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include "./fuzz_utils.h" +#include "src/webp/decode.h" +#include "src/webp/encode.h" + +namespace { + +const VP8CPUInfo default_VP8GetCPUInfo = VP8GetCPUInfo; + +} // namespace + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* const data, size_t size) { + uint32_t bit_pos = 0; + + ExtractAndDisableOptimizations(default_VP8GetCPUInfo, data, size, &bit_pos); + + // Init the source picture. + WebPPicture pic; + if (!WebPPictureInit(&pic)) { + fprintf(stderr, "WebPPictureInit failed.\n"); + abort(); + } + pic.use_argb = Extract(1, data, size, &bit_pos); + + // Read the source picture. + if (!ExtractSourcePicture(&pic, data, size, &bit_pos)) { + const WebPEncodingError error_code = pic.error_code; + WebPPictureFree(&pic); + if (error_code == VP8_ENC_ERROR_OUT_OF_MEMORY) return 0; + fprintf(stderr, "Can't read input image. Error code: %d\n", error_code); + abort(); + } + + // Crop and scale. + if (!ExtractAndCropOrScale(&pic, data, size, &bit_pos)) { + const WebPEncodingError error_code = pic.error_code; + WebPPictureFree(&pic); + if (error_code == VP8_ENC_ERROR_OUT_OF_MEMORY) return 0; + fprintf(stderr, "ExtractAndCropOrScale failed. Error code: %d\n", + error_code); + abort(); + } + + // Extract a configuration from the packed bits. + WebPConfig config; + if (!ExtractWebPConfig(&config, data, size, &bit_pos)) { + fprintf(stderr, "ExtractWebPConfig failed.\n"); + abort(); + } + // Skip slow settings on big images, it's likely to timeout. + if (pic.width * pic.height > 32 * 32) { + if (config.lossless) { + if (config.quality > 99.0f && config.method >= 5) { + config.quality = 99.0f; + config.method = 5; + } + } else { + if (config.quality > 99.0f && config.method == 6) { + config.quality = 99.0f; + } + } + if (config.alpha_quality == 100 && config.method == 6) { + config.alpha_quality = 99; + } + } + + // Encode. + WebPMemoryWriter memory_writer; + WebPMemoryWriterInit(&memory_writer); + pic.writer = WebPMemoryWrite; + pic.custom_ptr = &memory_writer; + if (!WebPEncode(&config, &pic)) { + const WebPEncodingError error_code = pic.error_code; + WebPMemoryWriterClear(&memory_writer); + WebPPictureFree(&pic); + if (error_code == VP8_ENC_ERROR_OUT_OF_MEMORY || + error_code == VP8_ENC_ERROR_BAD_WRITE) { + return 0; + } + fprintf(stderr, "WebPEncode failed. Error code: %d\n", error_code); + abort(); + } + + // Try decoding the result. + const uint8_t* const out_data = memory_writer.mem; + const size_t out_size = memory_writer.size; + WebPDecoderConfig dec_config; + if (!WebPInitDecoderConfig(&dec_config)) { + fprintf(stderr, "WebPInitDecoderConfig failed.\n"); + WebPMemoryWriterClear(&memory_writer); + WebPPictureFree(&pic); + abort(); + } + + dec_config.output.colorspace = MODE_BGRA; + const VP8StatusCode status = WebPDecode(out_data, out_size, &dec_config); + if ((status != VP8_STATUS_OK && status != VP8_STATUS_OUT_OF_MEMORY && + status != VP8_STATUS_USER_ABORT) || + (status == VP8_STATUS_OK && (dec_config.output.width != pic.width || + dec_config.output.height != pic.height))) { + fprintf(stderr, "WebPDecode failed. status: %d.\n", status); + WebPFreeDecBuffer(&dec_config.output); + WebPMemoryWriterClear(&memory_writer); + WebPPictureFree(&pic); + abort(); + } + + if (status == VP8_STATUS_OK) { + const uint8_t* const rgba = dec_config.output.u.RGBA.rgba; + const int w = dec_config.output.width; + const int h = dec_config.output.height; + + // Compare the results if exact encoding. + if (pic.use_argb && config.lossless && config.near_lossless == 100) { + const uint32_t* src1 = (const uint32_t*)rgba; + const uint32_t* src2 = pic.argb; + for (int y = 0; y < h; ++y, src1 += w, src2 += pic.argb_stride) { + for (int x = 0; x < w; ++x) { + uint32_t v1 = src1[x], v2 = src2[x]; + if (!config.exact) { + if ((v1 & 0xff000000u) == 0 || (v2 & 0xff000000u) == 0) { + // Only keep alpha for comparison of fully transparent area. + v1 &= 0xff000000u; + v2 &= 0xff000000u; + } + } + if (v1 != v2) { + fprintf(stderr, "Lossless compression failed pixel-exactness.\n"); + WebPFreeDecBuffer(&dec_config.output); + WebPMemoryWriterClear(&memory_writer); + WebPPictureFree(&pic); + abort(); + } + } + } + } + } + + WebPFreeDecBuffer(&dec_config.output); + WebPMemoryWriterClear(&memory_writer); + WebPPictureFree(&pic); + return 0; +} diff --git a/third-party/webp/libwebp/tests/fuzzer/fuzz.dict b/third-party/webp/libwebp/tests/fuzzer/fuzz.dict new file mode 100644 index 0000000000..627c72e75c --- /dev/null +++ b/third-party/webp/libwebp/tests/fuzzer/fuzz.dict @@ -0,0 +1,17 @@ +# https://developers.google.com/speed/webp/docs/riff_container + +# FourCC +"ALPH" +"ANIM" +"ANMF" +"EXIF" +"ICCP" +"RIFF" +"VP8 " +"VP8L" +"VP8X" +"WEBP" +"XMP " + +# VP8 signature +"\x9D\x01\x2A" diff --git a/third-party/webp/libwebp/tests/fuzzer/fuzz_utils.h b/third-party/webp/libwebp/tests/fuzzer/fuzz_utils.h new file mode 100644 index 0000000000..c3fc366da4 --- /dev/null +++ b/third-party/webp/libwebp/tests/fuzzer/fuzz_utils.h @@ -0,0 +1,223 @@ +// Copyright 2018 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + +#ifndef WEBP_TESTS_FUZZER_FUZZ_UTILS_H_ +#define WEBP_TESTS_FUZZER_FUZZ_UTILS_H_ + +#include +#include + +#include "./img_alpha.h" +#include "./img_grid.h" +#include "./img_peak.h" +#include "src/dsp/dsp.h" +#include "src/webp/encode.h" + +//------------------------------------------------------------------------------ +// Arbitrary limits to prevent OOM, timeout, or slow execution. + +// The decoded image size, and for animations additionally the canvas size. +// Enabling some sanitizers slow down runtime significantly. +// Use a very low threshold in this case to avoid timeouts. +#if defined(__SANITIZE_ADDRESS__) // GCC +static const size_t kFuzzPxLimit = 1024 * 1024 / 10; +#elif !defined(__has_feature) // Clang +static const size_t kFuzzPxLimit = 1024 * 1024; +#elif __has_feature(address_sanitizer) || __has_feature(memory_sanitizer) +static const size_t kFuzzPxLimit = 1024 * 1024 / 18; +#else +static const size_t kFuzzPxLimit = 1024 * 1024; +#endif + +// Demuxed or decoded animation frames. +static const int kFuzzFrameLimit = 3; + +// Reads and sums (up to) 128 spread-out bytes. +static WEBP_INLINE uint8_t FuzzHash(const uint8_t* const data, size_t size) { + uint8_t value = 0; + size_t incr = size / 128; + if (!incr) incr = 1; + for (size_t i = 0; i < size; i += incr) value += data[i]; + return value; +} + +//------------------------------------------------------------------------------ +// Extract an integer in [0, max_value]. + +static WEBP_INLINE uint32_t Extract(uint32_t max_value, + const uint8_t data[], size_t size, + uint32_t* const bit_pos) { + uint32_t v = 0; + uint32_t range = 1; + while (*bit_pos < 8 * size && range <= max_value) { + const uint8_t mask = 1u << (*bit_pos & 7); + v = (v << 1) | !!(data[*bit_pos >> 3] & mask); + range <<= 1; + ++*bit_pos; + } + return v % (max_value + 1); +} + +//------------------------------------------------------------------------------ +// Some functions to override VP8GetCPUInfo and disable some optimizations. + +#ifdef __cplusplus +extern "C" VP8CPUInfo VP8GetCPUInfo; +#else +extern VP8CPUInfo VP8GetCPUInfo; +#endif +static VP8CPUInfo GetCPUInfo; + +static WEBP_INLINE int GetCPUInfoNoSSE41(CPUFeature feature) { + if (feature == kSSE4_1 || feature == kAVX) return 0; + return GetCPUInfo(feature); +} + +static WEBP_INLINE int GetCPUInfoNoAVX(CPUFeature feature) { + if (feature == kAVX) return 0; + return GetCPUInfo(feature); +} + +static WEBP_INLINE int GetCPUInfoForceSlowSSSE3(CPUFeature feature) { + if (feature == kSlowSSSE3 && GetCPUInfo(kSSE3)) { + return 1; // we have SSE3 -> force SlowSSSE3 + } + return GetCPUInfo(feature); +} + +static WEBP_INLINE int GetCPUInfoOnlyC(CPUFeature feature) { + (void)feature; + return 0; +} + +static WEBP_INLINE void ExtractAndDisableOptimizations( + VP8CPUInfo default_VP8GetCPUInfo, const uint8_t data[], size_t size, + uint32_t* const bit_pos) { + GetCPUInfo = default_VP8GetCPUInfo; + const VP8CPUInfo kVP8CPUInfos[5] = {GetCPUInfoOnlyC, GetCPUInfoForceSlowSSSE3, + GetCPUInfoNoSSE41, GetCPUInfoNoAVX, + GetCPUInfo}; + int VP8GetCPUInfo_index = Extract(4, data, size, bit_pos); + VP8GetCPUInfo = kVP8CPUInfos[VP8GetCPUInfo_index]; +} + +//------------------------------------------------------------------------------ + +static WEBP_INLINE int ExtractWebPConfig(WebPConfig* const config, + const uint8_t data[], size_t size, + uint32_t* const bit_pos) { + if (config == NULL || !WebPConfigInit(config)) return 0; + config->lossless = Extract(1, data, size, bit_pos); + config->quality = Extract(100, data, size, bit_pos); + config->method = Extract(6, data, size, bit_pos); + config->image_hint = + (WebPImageHint)Extract(WEBP_HINT_LAST - 1, data, size, bit_pos); + config->segments = 1 + Extract(3, data, size, bit_pos); + config->sns_strength = Extract(100, data, size, bit_pos); + config->filter_strength = Extract(100, data, size, bit_pos); + config->filter_sharpness = Extract(7, data, size, bit_pos); + config->filter_type = Extract(1, data, size, bit_pos); + config->autofilter = Extract(1, data, size, bit_pos); + config->alpha_compression = Extract(1, data, size, bit_pos); + config->alpha_filtering = Extract(2, data, size, bit_pos); + config->alpha_quality = Extract(100, data, size, bit_pos); + config->pass = 1 + Extract(9, data, size, bit_pos); + config->show_compressed = 1; + config->preprocessing = Extract(2, data, size, bit_pos); + config->partitions = Extract(3, data, size, bit_pos); + config->partition_limit = 10 * Extract(10, data, size, bit_pos); + config->emulate_jpeg_size = Extract(1, data, size, bit_pos); + config->thread_level = Extract(1, data, size, bit_pos); + config->low_memory = Extract(1, data, size, bit_pos); + config->near_lossless = 20 * Extract(5, data, size, bit_pos); + config->exact = Extract(1, data, size, bit_pos); + config->use_delta_palette = Extract(1, data, size, bit_pos); + config->use_sharp_yuv = Extract(1, data, size, bit_pos); + return WebPValidateConfig(config); +} + +//------------------------------------------------------------------------------ + +static WEBP_INLINE int ExtractSourcePicture(WebPPicture* const pic, + const uint8_t data[], size_t size, + uint32_t* const bit_pos) { + if (pic == NULL) return 0; + + // Pick a source picture. + const uint8_t* kImagesData[] = { + kImgAlphaData, + kImgGridData, + kImgPeakData + }; + const int kImagesWidth[] = { + kImgAlphaWidth, + kImgGridWidth, + kImgPeakWidth + }; + const int kImagesHeight[] = { + kImgAlphaHeight, + kImgGridHeight, + kImgPeakHeight + }; + const size_t kNbImages = sizeof(kImagesData) / sizeof(kImagesData[0]); + const size_t image_index = Extract(kNbImages - 1, data, size, bit_pos); + const uint8_t* const image_data = kImagesData[image_index]; + pic->width = kImagesWidth[image_index]; + pic->height = kImagesHeight[image_index]; + pic->argb_stride = pic->width * 4 * sizeof(uint8_t); + + // Read the bytes. + return WebPPictureImportRGBA(pic, image_data, pic->argb_stride); +} + +//------------------------------------------------------------------------------ + +static WEBP_INLINE int Max(int a, int b) { return ((a < b) ? b : a); } + +static WEBP_INLINE int ExtractAndCropOrScale(WebPPicture* const pic, + const uint8_t data[], size_t size, + uint32_t* const bit_pos) { + if (pic == NULL) return 0; +#if !defined(WEBP_REDUCE_SIZE) + const int alter_input = Extract(1, data, size, bit_pos); + const int crop_or_scale = Extract(1, data, size, bit_pos); + const int width_ratio = 1 + Extract(7, data, size, bit_pos); + const int height_ratio = 1 + Extract(7, data, size, bit_pos); + if (alter_input) { + if (crop_or_scale) { + const uint32_t left_ratio = 1 + Extract(7, data, size, bit_pos); + const uint32_t top_ratio = 1 + Extract(7, data, size, bit_pos); + const int cropped_width = Max(1, pic->width / width_ratio); + const int cropped_height = Max(1, pic->height / height_ratio); + const int cropped_left = (pic->width - cropped_width) / left_ratio; + const int cropped_top = (pic->height - cropped_height) / top_ratio; + return WebPPictureCrop(pic, cropped_left, cropped_top, cropped_width, + cropped_height); + } else { + const int scaled_width = 1 + (pic->width * width_ratio) / 8; + const int scaled_height = 1 + (pic->height * height_ratio) / 8; + return WebPPictureRescale(pic, scaled_width, scaled_height); + } + } +#else // defined(WEBP_REDUCE_SIZE) + (void)data; + (void)size; + (void)bit_pos; +#endif // !defined(WEBP_REDUCE_SIZE) + return 1; +} + +#endif // WEBP_TESTS_FUZZER_FUZZ_UTILS_H_ diff --git a/third-party/webp/libwebp/tests/fuzzer/huffman_fuzzer.c b/third-party/webp/libwebp/tests/fuzzer/huffman_fuzzer.c new file mode 100644 index 0000000000..28fda720e3 --- /dev/null +++ b/third-party/webp/libwebp/tests/fuzzer/huffman_fuzzer.c @@ -0,0 +1,65 @@ +// Copyright 2023 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include "src/dec/vp8li_dec.h" +#include "src/utils/bit_reader_utils.h" +#include "src/utils/huffman_utils.h" +#include "src/utils/utils.h" +#include "src/webp/format_constants.h" + +int LLVMFuzzerTestOneInput(const uint8_t* const data, size_t size) { + // Number of bits to initialize data. + static const int kColorCacheBitsBits = 4; + // 'num_htree_groups' is contained in the RG channel, hence 16 bits. + static const int kNumHtreeGroupsBits = 16; + if (size * sizeof(*data) < kColorCacheBitsBits + kNumHtreeGroupsBits) { + return 0; + } + + // A non-NULL mapping brings minor changes that are tested by the normal + // fuzzer. + int* const mapping = NULL; + HuffmanTables huffman_tables; + memset(&huffman_tables, 0, sizeof(huffman_tables)); + HTreeGroup* htree_groups = NULL; + + VP8LDecoder* dec = VP8LNew(); + if (dec == NULL) goto Error; + VP8LBitReader* const br = &dec->br_; + VP8LInitBitReader(br, data, size); + + const int color_cache_bits = VP8LReadBits(br, kColorCacheBitsBits); + if (color_cache_bits < 1 || color_cache_bits > MAX_CACHE_BITS) goto Error; + + const int num_htree_groups = VP8LReadBits(br, kNumHtreeGroupsBits); + // 'num_htree_groups' cannot be 0 as it is built from a non-empty image. + if (num_htree_groups == 0) goto Error; + // This variable is only useful when mapping is not NULL. + const int num_htree_groups_max = num_htree_groups; + ReadHuffmanCodesHelper(color_cache_bits, num_htree_groups, + num_htree_groups_max, mapping, dec, &huffman_tables, + &htree_groups); + + Error: + WebPSafeFree(mapping); + VP8LHtreeGroupsFree(htree_groups); + VP8LHuffmanTablesDeallocate(&huffman_tables); + VP8LDelete(dec); + return 0; +} diff --git a/third-party/webp/libwebp/tests/fuzzer/img_alpha.h b/third-party/webp/libwebp/tests/fuzzer/img_alpha.h new file mode 100644 index 0000000000..fac63feb53 --- /dev/null +++ b/third-party/webp/libwebp/tests/fuzzer/img_alpha.h @@ -0,0 +1,381 @@ +// Copyright 2018 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + +#ifndef WEBP_TESTS_FUZZER_IMG_ALPHA_H_ +#define WEBP_TESTS_FUZZER_IMG_ALPHA_H_ + +#include + +static const int kImgAlphaWidth = 32; +static const int kImgAlphaHeight = 32; + +/*Pixel format: Red: 8 bit, Green: 8 bit, Blue: 8 bit, Fix 0xFF: 8 bit*/ +static const uint8_t kImgAlphaData[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfe, 0xfe, 0xfe, 0xff, 0xfe, 0xfe, 0xfd, 0xff, 0xfe, 0xfd, 0xfc, 0xff, + 0xfe, 0xfd, 0xfb, 0xff, 0xfe, 0xfc, 0xfb, 0xff, 0xfe, 0xfc, 0xfa, 0xff, + 0xfe, 0xfc, 0xf9, 0xff, 0xfe, 0xfb, 0xf8, 0xff, 0xfe, 0xfb, 0xf7, 0xff, + 0xfe, 0xfb, 0xf7, 0xff, 0xfe, 0xfa, 0xf6, 0xff, 0xfe, 0xf9, 0xf5, 0xff, + 0xfd, 0xf9, 0xf3, 0xff, 0xfd, 0xf8, 0xf2, 0xff, 0xfd, 0xf7, 0xf1, 0xff, + 0xfc, 0xf7, 0xf0, 0xff, 0xfc, 0xf6, 0xef, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, + 0xfe, 0xfe, 0xfd, 0xff, 0xfe, 0xfd, 0xfc, 0xff, 0xfe, 0xfd, 0xfb, 0xff, + 0xfe, 0xfc, 0xfa, 0xff, 0xfe, 0xfc, 0xfa, 0xff, 0xfe, 0xfb, 0xf9, 0xff, + 0xfe, 0xfb, 0xf8, 0xff, 0xfe, 0xfb, 0xf7, 0xff, 0xfe, 0xfa, 0xf7, 0xff, + 0xfe, 0xfa, 0xf5, 0xff, 0xfe, 0xfa, 0xf5, 0xff, 0xfd, 0xf9, 0xf4, 0xff, + 0xfd, 0xf8, 0xf2, 0xff, 0xfc, 0xf7, 0xf1, 0xff, 0xfc, 0xf7, 0xf0, 0xff, + 0xfc, 0xf7, 0xef, 0xff, 0xfc, 0xf6, 0xee, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfe, 0xfe, 0xfe, 0xff, 0xfe, 0xfe, 0xfd, 0xff, 0xfe, 0xfd, 0xfd, 0xff, + 0xfe, 0xfd, 0xfc, 0xff, 0xfe, 0xfd, 0xfb, 0xff, 0xfe, 0xfc, 0xfa, 0xff, + 0xfe, 0xfc, 0xfa, 0xff, 0xfe, 0xfc, 0xf9, 0xff, 0xfe, 0xfb, 0xf8, 0xff, + 0xfe, 0xfb, 0xf7, 0xff, 0xfe, 0xfb, 0xf6, 0xff, 0xfe, 0xfa, 0xf5, 0xff, + 0xfe, 0xfa, 0xf5, 0xff, 0xfe, 0xf9, 0xf4, 0xff, 0xfe, 0xf8, 0xf3, 0xff, + 0xfd, 0xf8, 0xf2, 0xff, 0xfc, 0xf7, 0xf1, 0xff, 0xfc, 0xf5, 0xf0, 0xff, + 0xfc, 0xf6, 0xee, 0xff, 0xfc, 0xf5, 0xed, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, + 0xfc, 0xfb, 0xfb, 0xff, 0xfd, 0xfc, 0xfc, 0xff, 0xfe, 0xfd, 0xfb, 0xff, + 0xfe, 0xfc, 0xfa, 0xff, 0xfe, 0xfc, 0xfa, 0xff, 0xfe, 0xfc, 0xf9, 0xff, + 0xfe, 0xfb, 0xf8, 0xff, 0xfe, 0xfb, 0xf8, 0xff, 0xfe, 0xfb, 0xf7, 0xff, + 0xfe, 0xfb, 0xf6, 0xff, 0xfe, 0xfa, 0xf5, 0xff, 0xfe, 0xfa, 0xf5, 0xff, + 0xfe, 0xf9, 0xf4, 0xff, 0xfe, 0xf9, 0xf3, 0xff, 0xfe, 0xf8, 0xf2, 0xff, + 0xfd, 0xf7, 0xf1, 0xff, 0xfc, 0xf6, 0xf0, 0xff, 0xfc, 0xf6, 0xee, 0xff, + 0xfc, 0xf5, 0xec, 0xff, 0xfb, 0xf5, 0xec, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xfb, 0xfb, 0xfb, 0xff, + 0xfa, 0xf9, 0xf9, 0xff, 0xf7, 0xf6, 0xf6, 0xff, 0xfd, 0xfc, 0xfa, 0xff, + 0xfe, 0xfc, 0xfa, 0xff, 0xfe, 0xfc, 0xf9, 0xff, 0xfe, 0xfb, 0xf9, 0xff, + 0xfe, 0xfb, 0xf7, 0xff, 0xfe, 0xfb, 0xf7, 0xff, 0xfe, 0xfb, 0xf6, 0xff, + 0xfe, 0xfa, 0xf5, 0xff, 0xfe, 0xfa, 0xf5, 0xff, 0xfe, 0xfa, 0xf3, 0xff, + 0xfe, 0xfa, 0xf4, 0xfb, 0xfe, 0xf9, 0xf4, 0xeb, 0xfe, 0xfb, 0xf6, 0xdc, + 0xfd, 0xfa, 0xf6, 0xcf, 0xfd, 0xfa, 0xf5, 0xcc, 0xfc, 0xf9, 0xf4, 0xcb, + 0xfd, 0xf8, 0xf3, 0xc7, 0xfc, 0xf8, 0xf2, 0xc7, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, + 0xfb, 0xfa, 0xfa, 0xff, 0xf8, 0xf7, 0xf7, 0xff, 0xf6, 0xf4, 0xf4, 0xff, + 0xf7, 0xf5, 0xf5, 0xff, 0xf5, 0xf5, 0xf4, 0xff, 0xf8, 0xf7, 0xf7, 0xff, + 0xfd, 0xfb, 0xf8, 0xff, 0xfe, 0xfb, 0xf8, 0xff, 0xfe, 0xfb, 0xf7, 0xff, + 0xfe, 0xfb, 0xf7, 0xff, 0xfe, 0xfa, 0xf6, 0xff, 0xfe, 0xfa, 0xf5, 0xff, + 0xfe, 0xfa, 0xf4, 0xff, 0xfd, 0xfa, 0xf4, 0xfc, 0xfe, 0xfc, 0xf9, 0xcf, + 0xff, 0xff, 0xff, 0xaf, 0xff, 0xff, 0xff, 0xa8, 0xff, 0xff, 0xff, 0xa4, + 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0x9b, 0xff, 0xff, 0xff, 0x94, + 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x8b, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfc, 0xfc, 0xff, 0xfa, 0xf9, 0xf9, 0xff, + 0xf6, 0xf5, 0xf4, 0xff, 0xf5, 0xf3, 0xf3, 0xff, 0xf4, 0xf2, 0xf1, 0xff, + 0xf2, 0xf1, 0xf0, 0xff, 0xf2, 0xf0, 0xf0, 0xff, 0xf0, 0xee, 0xee, 0xff, + 0xf1, 0xf0, 0xef, 0xff, 0xfe, 0xfb, 0xf8, 0xff, 0xfe, 0xfb, 0xf6, 0xff, + 0xfe, 0xfa, 0xf6, 0xff, 0xfe, 0xfa, 0xf5, 0xff, 0xfe, 0xfb, 0xf4, 0xff, + 0xfe, 0xfb, 0xf5, 0xf3, 0xff, 0xfe, 0xfe, 0xb4, 0xff, 0xff, 0xff, 0xac, + 0xff, 0xff, 0xff, 0xa7, 0xff, 0xff, 0xff, 0xa3, 0xff, 0xff, 0xff, 0x9c, + 0xff, 0xff, 0xff, 0x98, 0xff, 0xff, 0xff, 0x93, 0xff, 0xff, 0xff, 0x8f, + 0xff, 0xff, 0xff, 0x88, 0xff, 0xff, 0xff, 0x84, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, + 0xfc, 0xfb, 0xfb, 0xff, 0xf9, 0xf8, 0xf8, 0xff, 0xf6, 0xf5, 0xf4, 0xff, + 0xf3, 0xf1, 0xf1, 0xff, 0xf0, 0xed, 0xed, 0xff, 0xef, 0xec, 0xeb, 0xff, + 0xee, 0xeb, 0xeb, 0xff, 0xf0, 0xee, 0xee, 0xff, 0xea, 0xe7, 0xe7, 0xff, + 0xec, 0xe9, 0xe9, 0xff, 0xf5, 0xf2, 0xf0, 0xff, 0xfe, 0xfb, 0xf6, 0xff, + 0xfe, 0xfb, 0xf5, 0xff, 0xfe, 0xfa, 0xf4, 0xff, 0xfe, 0xfb, 0xf6, 0xeb, + 0xff, 0xff, 0xff, 0xaf, 0xff, 0xff, 0xff, 0xab, 0xff, 0xff, 0xff, 0xa4, + 0xff, 0xff, 0xff, 0xa0, 0xff, 0xff, 0xff, 0x9b, 0xff, 0xff, 0xff, 0x97, + 0xff, 0xff, 0xff, 0x90, 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x87, + 0xff, 0xff, 0xff, 0x83, 0xff, 0xff, 0xff, 0x7c, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfc, 0xfc, 0xff, 0xfb, 0xfb, 0xfa, 0xff, + 0xf8, 0xf6, 0xf6, 0xff, 0xf4, 0xf3, 0xf2, 0xff, 0xf2, 0xf0, 0xf0, 0xff, + 0xef, 0xec, 0xeb, 0xff, 0xef, 0xec, 0xeb, 0xff, 0xeb, 0xe7, 0xe6, 0xff, + 0xea, 0xe6, 0xe5, 0xff, 0xeb, 0xe8, 0xe8, 0xff, 0xe9, 0xe6, 0xe7, 0xff, + 0xe5, 0xe2, 0xe2, 0xff, 0xed, 0xeb, 0xeb, 0xff, 0xf7, 0xf5, 0xf2, 0xff, + 0xfe, 0xfa, 0xf5, 0xff, 0xfe, 0xfb, 0xf5, 0xf8, 0xff, 0xff, 0xff, 0xac, + 0xff, 0xff, 0xff, 0xa8, 0xff, 0xff, 0xff, 0xa3, 0xff, 0xff, 0xff, 0x9f, + 0xff, 0xff, 0xff, 0x98, 0xff, 0xff, 0xff, 0x94, 0xff, 0xff, 0xff, 0x8f, + 0xff, 0xff, 0xff, 0x8b, 0xff, 0xff, 0xff, 0x84, 0xff, 0xff, 0xff, 0x80, + 0xff, 0xff, 0xff, 0x7c, 0xff, 0xff, 0xff, 0x77, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfc, 0xfc, 0xfc, 0xff, 0xf8, 0xf7, 0xf7, 0xff, 0xf6, 0xf5, 0xf4, 0xff, + 0xf3, 0xf1, 0xf0, 0xff, 0xf1, 0xef, 0xef, 0xff, 0xef, 0xed, 0xec, 0xff, + 0xec, 0xe8, 0xe7, 0xff, 0xe9, 0xe6, 0xe6, 0xff, 0xec, 0xe9, 0xe9, 0xff, + 0xe4, 0xe0, 0xdf, 0xff, 0xec, 0xe9, 0xe9, 0xff, 0xea, 0xe6, 0xe6, 0xff, + 0xe6, 0xe2, 0xe2, 0xff, 0xea, 0xe8, 0xe8, 0xff, 0xec, 0xe8, 0xe7, 0xff, + 0xfc, 0xf9, 0xf4, 0xff, 0xfe, 0xfd, 0xfa, 0xc3, 0xff, 0xff, 0xff, 0xa7, + 0xff, 0xff, 0xff, 0xa0, 0xff, 0xff, 0xff, 0x9c, 0xff, 0xff, 0xff, 0x97, + 0xff, 0xff, 0xff, 0x93, 0xff, 0xff, 0xff, 0x8c, 0xfe, 0xfc, 0xf9, 0xa3, + 0xfc, 0xfb, 0xf5, 0xb0, 0xfc, 0xf9, 0xf1, 0xbb, 0xfb, 0xf8, 0xf1, 0xb8, + 0xfb, 0xf8, 0xef, 0xb4, 0xfb, 0xf9, 0xf2, 0xa4, + 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfc, 0xfc, 0xfc, 0xff, + 0xf8, 0xf7, 0xf7, 0xff, 0xf5, 0xf3, 0xf3, 0xff, 0xf1, 0xef, 0xef, 0xff, + 0xef, 0xec, 0xeb, 0xff, 0xeb, 0xe7, 0xe7, 0xff, 0xea, 0xe7, 0xe6, 0xff, + 0xe7, 0xe3, 0xe2, 0xff, 0xe4, 0xdf, 0xde, 0xff, 0xe6, 0xe2, 0xe2, 0xff, + 0xe4, 0xe1, 0xe0, 0xff, 0xe6, 0xe3, 0xe2, 0xff, 0xe0, 0xdc, 0xdc, 0xff, + 0xe3, 0xdf, 0xdf, 0xff, 0xe8, 0xe5, 0xe5, 0xff, 0xe4, 0xe1, 0xe2, 0xff, + 0xec, 0xe8, 0xe5, 0xf8, 0xff, 0xff, 0xff, 0xa4, 0xff, 0xff, 0xff, 0xa0, + 0xff, 0xff, 0xff, 0x9b, 0xff, 0xff, 0xff, 0x97, 0xff, 0xff, 0xff, 0x90, + 0xfe, 0xfe, 0xfb, 0x9c, 0xfc, 0xf9, 0xef, 0xf7, 0xfc, 0xf8, 0xed, 0xff, + 0xfc, 0xf7, 0xeb, 0xff, 0xfb, 0xf7, 0xeb, 0xff, 0xfa, 0xf6, 0xe9, 0xff, + 0xfa, 0xf5, 0xe7, 0xff, 0xf8, 0xf4, 0xe5, 0xff, + 0xfd, 0xfd, 0xfd, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xfc, 0xfc, 0xfc, 0xff, + 0xf8, 0xf7, 0xf7, 0xff, 0xf1, 0xef, 0xee, 0xff, 0xed, 0xea, 0xe9, 0xff, + 0xea, 0xe6, 0xe5, 0xff, 0xe7, 0xe3, 0xe2, 0xff, 0xe4, 0xe0, 0xdf, 0xff, + 0xe3, 0xde, 0xdd, 0xff, 0xe2, 0xde, 0xdd, 0xff, 0xe5, 0xe1, 0xe1, 0xff, + 0xde, 0xda, 0xda, 0xff, 0xe0, 0xdd, 0xdc, 0xff, 0xe1, 0xdd, 0xdd, 0xff, + 0xe3, 0xe0, 0xdf, 0xff, 0xe4, 0xe1, 0xe1, 0xff, 0xe3, 0xe0, 0xe0, 0xff, + 0xec, 0xea, 0xea, 0xe8, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0x98, + 0xff, 0xff, 0xff, 0x93, 0xff, 0xff, 0xff, 0x8f, 0xfe, 0xfe, 0xfe, 0x8c, + 0xfd, 0xfb, 0xef, 0xff, 0xfd, 0xfb, 0xed, 0xff, 0xfd, 0xf8, 0xec, 0xff, + 0xfc, 0xf8, 0xeb, 0xff, 0xfc, 0xf7, 0xea, 0xff, 0xfb, 0xf6, 0xe9, 0xff, + 0xfa, 0xf6, 0xe7, 0xff, 0xfa, 0xf5, 0xe5, 0xff, + 0xfa, 0xfa, 0xfa, 0xff, 0xf8, 0xf7, 0xf8, 0xff, 0xf6, 0xf6, 0xf6, 0xff, + 0xf1, 0xf0, 0xf0, 0xff, 0xed, 0xec, 0xec, 0xff, 0xe9, 0xe6, 0xe5, 0xff, + 0xe6, 0xe1, 0xe0, 0xff, 0xe2, 0xde, 0xdc, 0xff, 0xe0, 0xda, 0xd8, 0xff, + 0xdd, 0xd7, 0xd5, 0xff, 0xde, 0xda, 0xd9, 0xff, 0xde, 0xda, 0xda, 0xff, + 0xdc, 0xd7, 0xd8, 0xff, 0xdf, 0xdc, 0xdc, 0xff, 0xe5, 0xe3, 0xe4, 0xff, + 0xe1, 0xde, 0xde, 0xff, 0xde, 0xdc, 0xdc, 0xff, 0xe9, 0xe7, 0xe8, 0xff, + 0xe8, 0xe7, 0xe6, 0xe7, 0xff, 0xff, 0xff, 0x97, 0xff, 0xff, 0xff, 0x93, + 0xff, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0x88, 0xfe, 0xfe, 0xfa, 0x9b, + 0xfc, 0xfb, 0xee, 0xff, 0xfc, 0xfa, 0xed, 0xff, 0xfb, 0xfa, 0xeb, 0xff, + 0xfb, 0xf8, 0xeb, 0xff, 0xfb, 0xf7, 0xea, 0xff, 0xfa, 0xf6, 0xe8, 0xff, + 0xf8, 0xf6, 0xe6, 0xff, 0xf7, 0xf5, 0xe3, 0xff, + 0xf9, 0xf9, 0xf9, 0xff, 0xf7, 0xf6, 0xf7, 0xff, 0xf5, 0xf4, 0xf4, 0xff, + 0xf0, 0xee, 0xef, 0xff, 0xe8, 0xe7, 0xe7, 0xff, 0xe7, 0xe4, 0xe3, 0xff, + 0xe2, 0xdd, 0xdb, 0xff, 0xdf, 0xd9, 0xd7, 0xff, 0xdc, 0xd6, 0xd4, 0xff, + 0xd8, 0xd2, 0xcf, 0xff, 0xd8, 0xd2, 0xd1, 0xff, 0xe0, 0xdc, 0xdc, 0xff, + 0xdb, 0xd7, 0xd7, 0xff, 0xdb, 0xd7, 0xd7, 0xff, 0xe7, 0xe5, 0xe5, 0xff, + 0xde, 0xda, 0xdb, 0xff, 0xdb, 0xd8, 0xd9, 0xff, 0xe0, 0xde, 0xde, 0xff, + 0xed, 0xeb, 0xec, 0xe4, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0x8b, + 0xff, 0xff, 0xff, 0x87, 0xff, 0xff, 0xff, 0x80, 0xfe, 0xfe, 0xfa, 0x94, + 0xfd, 0xfb, 0xee, 0xff, 0xfd, 0xfb, 0xed, 0xff, 0xfc, 0xfb, 0xec, 0xff, + 0xfc, 0xfa, 0xea, 0xff, 0xf8, 0xf7, 0xe9, 0xff, 0xf8, 0xf6, 0xe7, 0xff, + 0xf7, 0xf7, 0xe5, 0xff, 0xf7, 0xf5, 0xe3, 0xff, + 0xf9, 0xf9, 0xf9, 0xff, 0xf5, 0xf4, 0xf4, 0xff, 0xf2, 0xf2, 0xf2, 0xff, + 0xe9, 0xe6, 0xe6, 0xff, 0xe9, 0xe7, 0xe6, 0xff, 0xe9, 0xe7, 0xe7, 0xff, + 0xe0, 0xdb, 0xda, 0xff, 0xda, 0xd3, 0xd2, 0xff, 0xd6, 0xd0, 0xce, 0xff, + 0xd4, 0xcd, 0xcb, 0xff, 0xd0, 0xc8, 0xc7, 0xff, 0xd7, 0xd2, 0xd1, 0xff, + 0xd8, 0xd3, 0xd3, 0xff, 0xd4, 0xd1, 0xd1, 0xff, 0xe6, 0xe3, 0xe2, 0xff, + 0xdd, 0xda, 0xda, 0xff, 0xe3, 0xe1, 0xe1, 0xff, 0xe0, 0xde, 0xde, 0xff, + 0xe7, 0xe5, 0xe5, 0xe3, 0xff, 0xff, 0xff, 0x88, 0xff, 0xff, 0xff, 0x84, + 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7b, 0xfe, 0xfe, 0xfb, 0x88, + 0xfc, 0xfc, 0xef, 0xff, 0xfb, 0xfc, 0xee, 0xff, 0xfb, 0xfa, 0xeb, 0xff, + 0xfa, 0xfa, 0xea, 0xff, 0xf9, 0xf9, 0xe7, 0xff, 0xf7, 0xf7, 0xe6, 0xff, + 0xf6, 0xf5, 0xe5, 0xff, 0xf7, 0xf5, 0xe3, 0xff, + 0xf8, 0xf7, 0xf7, 0xff, 0xf4, 0xf4, 0xf4, 0xff, 0xf2, 0xf2, 0xf1, 0xff, + 0xe8, 0xe6, 0xe6, 0xff, 0xe4, 0xe1, 0xe1, 0xff, 0xdd, 0xda, 0xda, 0xff, + 0xe7, 0xe3, 0xe3, 0xff, 0xd6, 0xcf, 0xcd, 0xff, 0xd4, 0xcc, 0xca, 0xff, + 0xcf, 0xc7, 0xc5, 0xff, 0xcc, 0xc3, 0xc1, 0xff, 0xd3, 0xce, 0xcc, 0xff, + 0xd9, 0xd4, 0xd4, 0xff, 0xda, 0xd6, 0xd6, 0xff, 0xe3, 0xe1, 0xe0, 0xff, + 0xdb, 0xd8, 0xd7, 0xff, 0xe4, 0xe2, 0xe2, 0xff, 0xe1, 0xde, 0xdf, 0xff, + 0xe3, 0xe1, 0xe1, 0xf0, 0xff, 0xff, 0xff, 0x83, 0xff, 0xff, 0xff, 0x7c, + 0xff, 0xff, 0xff, 0x78, 0xff, 0xff, 0xff, 0x73, 0xff, 0xff, 0xff, 0x6f, + 0xfb, 0xfc, 0xed, 0xff, 0xfa, 0xfb, 0xed, 0xff, 0xfb, 0xfa, 0xeb, 0xff, + 0xfa, 0xf9, 0xe9, 0xff, 0xfa, 0xf9, 0xe7, 0xff, 0xf8, 0xf9, 0xe7, 0xff, + 0xf7, 0xf5, 0xe3, 0xff, 0xf7, 0xf4, 0xe1, 0xff, + 0xf2, 0xf2, 0xf2, 0xff, 0xf0, 0xf0, 0xf0, 0xff, 0xf0, 0xf0, 0xef, 0xff, + 0xe5, 0xe3, 0xe3, 0xff, 0xdd, 0xd9, 0xd9, 0xff, 0xdf, 0xdc, 0xdc, 0xff, + 0xe6, 0xe3, 0xe3, 0xff, 0xe1, 0xda, 0xdb, 0xff, 0xd2, 0xca, 0xc7, 0xff, + 0xca, 0xc2, 0xc0, 0xff, 0xc7, 0xbe, 0xbc, 0xff, 0xc8, 0xc2, 0xc0, 0xff, + 0xd2, 0xcf, 0xce, 0xff, 0xd5, 0xcf, 0xd0, 0xff, 0xd5, 0xd1, 0xd1, 0xff, + 0xda, 0xd6, 0xd7, 0xff, 0xde, 0xdc, 0xdd, 0xff, 0xde, 0xdd, 0xdc, 0xff, + 0xe2, 0xe0, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x7c, 0xff, 0xff, 0xff, 0x77, + 0xff, 0xff, 0xff, 0x70, 0xff, 0xff, 0xff, 0x6c, 0xff, 0xff, 0xff, 0x67, + 0xfa, 0xfd, 0xed, 0xf8, 0xf9, 0xfc, 0xeb, 0xff, 0xf9, 0xfb, 0xea, 0xff, + 0xf8, 0xf9, 0xe8, 0xff, 0xf7, 0xf9, 0xe6, 0xff, 0xf7, 0xf8, 0xe6, 0xff, + 0xf6, 0xf5, 0xe4, 0xff, 0xf6, 0xf4, 0xe1, 0xff, + 0xe7, 0xe7, 0xe7, 0xff, 0xe3, 0xe4, 0xe3, 0xff, 0xe1, 0xe2, 0xe2, 0xff, + 0xe4, 0xe4, 0xe4, 0xff, 0xd7, 0xd6, 0xd5, 0xff, 0xd5, 0xd4, 0xd4, 0xff, + 0xdd, 0xdc, 0xdc, 0xff, 0xdc, 0xda, 0xda, 0xff, 0xd0, 0xc9, 0xc9, 0xff, + 0xc9, 0xbf, 0xbe, 0xff, 0xc2, 0xba, 0xb8, 0xff, 0xc0, 0xb8, 0xb6, 0xff, + 0xcc, 0xc7, 0xc7, 0xff, 0xd2, 0xcd, 0xcd, 0xff, 0xd2, 0xce, 0xcf, 0xff, + 0xd1, 0xcc, 0xcd, 0xff, 0xdf, 0xde, 0xde, 0xff, 0xe7, 0xe6, 0xe6, 0xff, + 0xe4, 0xe3, 0xe3, 0xff, 0xfd, 0xfd, 0xfd, 0x78, 0xff, 0xff, 0xff, 0x70, + 0xff, 0xff, 0xff, 0x6b, 0xff, 0xff, 0xff, 0x67, 0xff, 0xff, 0xff, 0x60, + 0xfc, 0xfe, 0xef, 0xcf, 0xf9, 0xfc, 0xec, 0xff, 0xfa, 0xfa, 0xe9, 0xff, + 0xf8, 0xfa, 0xe8, 0xff, 0xf7, 0xf7, 0xe5, 0xff, 0xf6, 0xf7, 0xe5, 0xff, + 0xf5, 0xf5, 0xe3, 0xff, 0xf6, 0xf4, 0xe0, 0xff, + 0xdc, 0xdd, 0xdd, 0xff, 0xdb, 0xdc, 0xdc, 0xff, 0xd3, 0xd4, 0xd4, 0xff, + 0xd8, 0xd8, 0xd8, 0xff, 0xd1, 0xd1, 0xd1, 0xff, 0xd0, 0xd0, 0xd0, 0xff, + 0xca, 0xcb, 0xcb, 0xff, 0xcc, 0xcc, 0xcd, 0xff, 0xcb, 0xcb, 0xcb, 0xff, + 0xc6, 0xc1, 0xc1, 0xff, 0xc0, 0xbc, 0xba, 0xff, 0xba, 0xb1, 0xaf, 0xff, + 0xc5, 0xbf, 0xc0, 0xff, 0xd6, 0xd2, 0xd2, 0xff, 0xc4, 0xbf, 0xbf, 0xff, + 0xd3, 0xce, 0xcd, 0xff, 0xd3, 0xd1, 0xd2, 0xff, 0xe3, 0xe2, 0xe2, 0xff, + 0xe6, 0xe4, 0xe4, 0xff, 0xee, 0xee, 0xed, 0x9b, 0xff, 0xff, 0xff, 0x68, + 0xff, 0xff, 0xff, 0x63, 0xff, 0xff, 0xff, 0x5f, 0xff, 0xff, 0xff, 0x5b, + 0xfd, 0xfe, 0xf6, 0x80, 0xf9, 0xfc, 0xeb, 0xff, 0xf7, 0xfa, 0xeb, 0xff, + 0xf7, 0xf9, 0xe9, 0xff, 0xf6, 0xf8, 0xe8, 0xff, 0xf6, 0xf7, 0xe5, 0xff, + 0xf5, 0xf4, 0xe4, 0xff, 0xf5, 0xf4, 0xe3, 0xff, + 0xd7, 0xd8, 0xd8, 0xff, 0xd4, 0xd5, 0xd4, 0xff, 0xd2, 0xd3, 0xd3, 0xff, + 0xcf, 0xd0, 0xd0, 0xff, 0xcc, 0xce, 0xcd, 0xff, 0xc9, 0xca, 0xca, 0xff, + 0xc5, 0xc6, 0xc6, 0xff, 0xc3, 0xc4, 0xc4, 0xff, 0xbf, 0xbf, 0xbd, 0xff, + 0xbe, 0xbf, 0xbf, 0xff, 0xba, 0xba, 0xba, 0xff, 0xb4, 0xb1, 0xb1, 0xff, + 0xbb, 0xba, 0xb9, 0xff, 0xc9, 0xc8, 0xc7, 0xff, 0xe2, 0xde, 0xde, 0xff, + 0xc1, 0xbd, 0xbd, 0xff, 0xd6, 0xd5, 0xd5, 0xff, 0xde, 0xdd, 0xdc, 0xff, + 0xdc, 0xda, 0xda, 0xff, 0xe6, 0xe5, 0xe5, 0xcf, 0xff, 0xff, 0xff, 0x63, + 0xff, 0xff, 0xff, 0x5c, 0xff, 0xff, 0xff, 0x58, 0xff, 0xff, 0xff, 0x53, + 0xff, 0xff, 0xff, 0x4f, 0xf9, 0xfc, 0xeb, 0xfb, 0xf6, 0xf9, 0xeb, 0xff, + 0xf6, 0xf9, 0xea, 0xff, 0xf6, 0xf9, 0xe8, 0xff, 0xf5, 0xf5, 0xe4, 0xff, + 0xf6, 0xf6, 0xe4, 0xff, 0xf5, 0xf4, 0xe2, 0xff, + 0xd3, 0xd4, 0xd4, 0xff, 0xcc, 0xcd, 0xcd, 0xff, 0xce, 0xcf, 0xcf, 0xff, + 0xc9, 0xcb, 0xcb, 0xff, 0xc6, 0xc7, 0xc7, 0xff, 0xc3, 0xc5, 0xc4, 0xff, + 0xc0, 0xc1, 0xc1, 0xff, 0xbb, 0xbd, 0xbc, 0xff, 0xb7, 0xb9, 0xb8, 0xff, + 0xb6, 0xb7, 0xb7, 0xff, 0xb4, 0xb7, 0xb6, 0xff, 0xaf, 0xaf, 0xaf, 0xff, + 0xb0, 0xb2, 0xb2, 0xff, 0xb5, 0xb5, 0xb5, 0xff, 0xc1, 0xc0, 0xc0, 0xff, + 0xc9, 0xc6, 0xc7, 0xff, 0xb3, 0xad, 0xae, 0xff, 0xcf, 0xcd, 0xce, 0xff, + 0xe3, 0xe2, 0xe2, 0xff, 0xe4, 0xe2, 0xe2, 0xff, 0xfd, 0xfd, 0xfd, 0x60, + 0xff, 0xff, 0xff, 0x57, 0xff, 0xff, 0xff, 0x50, 0xff, 0xff, 0xff, 0x4c, + 0xff, 0xff, 0xff, 0x47, 0xfa, 0xfb, 0xef, 0xa8, 0xf8, 0xfc, 0xed, 0xff, + 0xf7, 0xf9, 0xea, 0xff, 0xf6, 0xf7, 0xe7, 0xff, 0xf6, 0xf4, 0xe7, 0xff, + 0xf5, 0xf4, 0xe5, 0xff, 0xf4, 0xf3, 0xe3, 0xff, + 0xce, 0xcf, 0xcf, 0xff, 0xc8, 0xc9, 0xc9, 0xff, 0xc6, 0xc8, 0xc8, 0xff, + 0xc4, 0xc6, 0xc6, 0xff, 0xc2, 0xc3, 0xc3, 0xff, 0xba, 0xbd, 0xbc, 0xff, + 0xbc, 0xbe, 0xbe, 0xff, 0xb5, 0xb8, 0xb7, 0xff, 0xb4, 0xb6, 0xb5, 0xff, + 0xb0, 0xb2, 0xb2, 0xff, 0xaf, 0xb1, 0xb0, 0xff, 0xaa, 0xad, 0xac, 0xff, + 0xaa, 0xad, 0xac, 0xff, 0xa7, 0xa9, 0xa8, 0xff, 0xa4, 0xa5, 0xa5, 0xff, + 0xa7, 0xa8, 0xa8, 0xff, 0xc4, 0xc3, 0xc3, 0xff, 0xb8, 0xb7, 0xb7, 0xff, + 0xc0, 0xbf, 0xbe, 0xff, 0xd0, 0xce, 0xce, 0xff, 0xe3, 0xe2, 0xe2, 0x94, + 0xff, 0xff, 0xff, 0x4f, 0xff, 0xff, 0xff, 0x4b, 0xff, 0xff, 0xff, 0x44, + 0xff, 0xff, 0xff, 0x40, 0xed, 0xe7, 0xe6, 0x48, 0xba, 0xad, 0xa1, 0xff, + 0xd6, 0xcf, 0xc1, 0xff, 0xf4, 0xf3, 0xe4, 0xff, 0xf5, 0xf4, 0xe5, 0xff, + 0xf5, 0xf3, 0xe5, 0xff, 0xf5, 0xf5, 0xe5, 0xff, + 0xc7, 0xc9, 0xc8, 0xff, 0xc5, 0xc6, 0xc6, 0xff, 0xc1, 0xc2, 0xc2, 0xff, + 0xbd, 0xbe, 0xbe, 0xff, 0xba, 0xbc, 0xbb, 0xff, 0xb3, 0xb4, 0xb4, 0xff, + 0xb2, 0xb5, 0xb4, 0xff, 0xb1, 0xb4, 0xb3, 0xff, 0xac, 0xaf, 0xae, 0xff, + 0xa8, 0xaa, 0xa9, 0xff, 0xa8, 0xab, 0xaa, 0xff, 0xa1, 0xa4, 0xa3, 0xff, + 0xa1, 0xa4, 0xa3, 0xff, 0xa3, 0xa5, 0xa4, 0xff, 0x9f, 0xa1, 0xa0, 0xff, + 0x99, 0x9b, 0x9a, 0xff, 0x98, 0x9a, 0x9a, 0xff, 0x97, 0x9a, 0x99, 0xff, + 0xa0, 0xa0, 0xa0, 0xff, 0x9b, 0x9b, 0x9b, 0xff, 0x9f, 0xa0, 0x9f, 0xe8, + 0xff, 0xff, 0xff, 0x48, 0xff, 0xff, 0xff, 0x44, 0xff, 0xff, 0xff, 0x3f, + 0xff, 0xff, 0xff, 0x3b, 0xff, 0xff, 0xff, 0x34, 0xbb, 0xa7, 0xa5, 0xd8, + 0xb9, 0xa9, 0xa6, 0xff, 0xb9, 0xac, 0xa0, 0xff, 0xf8, 0xfa, 0xe7, 0xff, + 0xf5, 0xf4, 0xe6, 0xff, 0xf4, 0xf3, 0xe4, 0xff, + 0xc0, 0xc0, 0xbf, 0xff, 0xbb, 0xbb, 0xbb, 0xff, 0xbb, 0xbc, 0xbb, 0xff, + 0xb6, 0xb6, 0xb6, 0xff, 0xb0, 0xb1, 0xb1, 0xff, 0xad, 0xad, 0xad, 0xff, + 0xa8, 0xa7, 0xa7, 0xff, 0xa8, 0xa9, 0xa9, 0xff, 0xa5, 0xa6, 0xa6, 0xff, + 0xa4, 0xa6, 0xa5, 0xff, 0xa3, 0xa6, 0xa6, 0xff, 0x9b, 0x9d, 0x9c, 0xff, + 0x96, 0x99, 0x99, 0xff, 0x9b, 0x9d, 0x9d, 0xff, 0x97, 0x99, 0x98, 0xff, + 0x8e, 0x91, 0x91, 0xff, 0x98, 0x9b, 0x9b, 0xff, 0x89, 0x8c, 0x8b, 0xff, + 0x87, 0x8b, 0x89, 0xff, 0x84, 0x7f, 0x81, 0xff, 0x82, 0x82, 0x83, 0xff, + 0xc0, 0xbe, 0xbf, 0x67, 0xff, 0xff, 0xff, 0x3c, 0xff, 0xff, 0xff, 0x37, + 0xff, 0xff, 0xff, 0x33, 0xff, 0xff, 0xff, 0x2f, 0xc6, 0xbb, 0xb9, 0x50, + 0xac, 0x9c, 0x99, 0xff, 0xa8, 0x98, 0x91, 0xff, 0xbd, 0xb0, 0xa5, 0xff, + 0xf6, 0xf5, 0xe6, 0xff, 0xf4, 0xf3, 0xe4, 0xff, + 0xbb, 0xbb, 0xba, 0xff, 0xb3, 0xb3, 0xb3, 0xff, 0xb3, 0xb4, 0xb4, 0xff, + 0xae, 0xaf, 0xae, 0xff, 0xad, 0xae, 0xae, 0xff, 0xb2, 0xb4, 0xb4, 0xfc, + 0xa8, 0xa8, 0xa9, 0xf3, 0xa7, 0xa7, 0xa7, 0xf3, 0x9e, 0x9f, 0x9d, 0xfc, + 0x9b, 0x9c, 0x9a, 0xff, 0x9c, 0x9e, 0x9e, 0xff, 0x94, 0x96, 0x94, 0xff, + 0x90, 0x90, 0x90, 0xff, 0x96, 0x98, 0x99, 0xff, 0x8d, 0x8f, 0x8e, 0xff, + 0x83, 0x83, 0x84, 0xff, 0x8f, 0x92, 0x91, 0xff, 0x83, 0x85, 0x85, 0xff, + 0x87, 0x87, 0x87, 0xff, 0x7c, 0x7d, 0x7d, 0xff, 0x78, 0x74, 0x72, 0xff, + 0x95, 0x93, 0x92, 0x97, 0xff, 0xff, 0xff, 0x34, 0xff, 0xff, 0xff, 0x30, + 0xff, 0xff, 0xff, 0x2c, 0xff, 0xff, 0xff, 0x27, 0xff, 0xff, 0xff, 0x23, + 0xa2, 0x93, 0x94, 0xe7, 0x96, 0x83, 0x81, 0xff, 0xa8, 0x91, 0x8b, 0xff, + 0xc4, 0xbc, 0xb2, 0xff, 0xf5, 0xf5, 0xe4, 0xff, + 0xb7, 0xb9, 0xb8, 0xff, 0xaf, 0xaf, 0xae, 0xff, 0xaf, 0xaf, 0xaf, 0xff, + 0xac, 0xad, 0xae, 0xff, 0xa8, 0xaa, 0xa9, 0xff, 0xae, 0xaf, 0xaf, 0xec, + 0xc6, 0xc7, 0xc7, 0xb4, 0xc5, 0xc6, 0xc6, 0xb3, 0x9a, 0x99, 0x99, 0xeb, + 0x91, 0x91, 0x90, 0xff, 0x94, 0x95, 0x95, 0xff, 0x95, 0x96, 0x96, 0xff, + 0x8c, 0x8e, 0x8e, 0xff, 0x86, 0x88, 0x87, 0xff, 0x83, 0x82, 0x82, 0xff, + 0x80, 0x81, 0x81, 0xff, 0x82, 0x84, 0x84, 0xff, 0x7b, 0x79, 0x7a, 0xff, + 0x73, 0x74, 0x73, 0xff, 0x79, 0x7a, 0x7b, 0xff, 0x75, 0x73, 0x72, 0xff, + 0x6f, 0x70, 0x6e, 0xfc, 0xe8, 0xe7, 0xe7, 0x37, 0xff, 0xff, 0xff, 0x2b, + 0xff, 0xff, 0xff, 0x24, 0xff, 0xff, 0xff, 0x20, 0xff, 0xff, 0xff, 0x1c, + 0x70, 0x6e, 0x6d, 0xeb, 0x6c, 0x69, 0x66, 0xff, 0x83, 0x78, 0x7b, 0xff, + 0x83, 0x7f, 0x78, 0xff, 0xdc, 0xd5, 0xcd, 0xff, + 0xb3, 0xb5, 0xb4, 0xff, 0xa9, 0xa9, 0xaa, 0xff, 0xa7, 0xa8, 0xa7, 0xff, + 0xa7, 0xa8, 0xa7, 0xff, 0xa6, 0xa8, 0xa8, 0xff, 0xab, 0xac, 0xab, 0xe3, + 0xdb, 0xdc, 0xdc, 0x97, 0xd9, 0xda, 0xda, 0x93, 0x99, 0x99, 0x98, 0xe0, + 0x94, 0x95, 0x95, 0xff, 0x8e, 0x8f, 0x8e, 0xff, 0x8f, 0x93, 0x92, 0xff, + 0x88, 0x8a, 0x89, 0xff, 0x79, 0x78, 0x78, 0xff, 0x80, 0x82, 0x82, 0xff, + 0x7f, 0x81, 0x81, 0xff, 0x7f, 0x7d, 0x7e, 0xff, 0x76, 0x72, 0x72, 0xff, + 0x70, 0x70, 0x70, 0xff, 0x73, 0x73, 0x73, 0xff, 0x67, 0x66, 0x64, 0xff, + 0x6b, 0x6b, 0x6a, 0xff, 0x70, 0x73, 0x72, 0xd4, 0xff, 0xff, 0xff, 0x23, + 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0x1b, 0x79, 0x74, 0x72, 0x67, + 0x63, 0x61, 0x61, 0xff, 0x63, 0x62, 0x60, 0xff, 0x5e, 0x5c, 0x5a, 0xff, + 0x61, 0x5f, 0x5c, 0xff, 0x6b, 0x63, 0x5e, 0xff, + 0xae, 0xaf, 0xaf, 0xff, 0xa9, 0xa9, 0xa9, 0xff, 0x9c, 0x9b, 0x99, 0xff, + 0x9d, 0x9c, 0x9b, 0xff, 0x9c, 0x9c, 0x9c, 0xff, 0x9c, 0x9c, 0x9d, 0xf7, + 0xaa, 0xac, 0xac, 0xd4, 0xa5, 0xa7, 0xa6, 0xd3, 0x98, 0x9a, 0x9a, 0xf4, + 0x8d, 0x8e, 0x8e, 0xff, 0x85, 0x85, 0x85, 0xff, 0x85, 0x86, 0x86, 0xff, + 0x82, 0x84, 0x84, 0xff, 0x7b, 0x7b, 0x7b, 0xff, 0x7e, 0x82, 0x81, 0xff, + 0x79, 0x7b, 0x7b, 0xff, 0x79, 0x7b, 0x7b, 0xff, 0x72, 0x73, 0x73, 0xff, + 0x70, 0x6e, 0x6e, 0xff, 0x6d, 0x6d, 0x6d, 0xff, 0x61, 0x5f, 0x5d, 0xff, + 0x5d, 0x5d, 0x5b, 0xff, 0x64, 0x60, 0x61, 0xff, 0x5e, 0x5d, 0x5d, 0xec, + 0x6a, 0x69, 0x67, 0xa0, 0x67, 0x66, 0x64, 0xbc, 0x59, 0x56, 0x55, 0xff, + 0x54, 0x51, 0x4e, 0xff, 0x56, 0x52, 0x51, 0xff, 0x55, 0x52, 0x4f, 0xff, + 0x52, 0x4e, 0x49, 0xff, 0x54, 0x54, 0x52, 0xff, + 0xa9, 0xac, 0xab, 0xff, 0xa1, 0xa0, 0xa0, 0xff, 0x9a, 0x99, 0x98, 0xff, + 0x97, 0x97, 0x96, 0xff, 0x95, 0x94, 0x94, 0xff, 0x8e, 0x8c, 0x8c, 0xff, + 0x95, 0x98, 0x97, 0xfc, 0x90, 0x91, 0x91, 0xfc, 0x95, 0x96, 0x96, 0xff, + 0x86, 0x86, 0x86, 0xff, 0x81, 0x82, 0x80, 0xff, 0x7d, 0x7e, 0x7b, 0xff, + 0x78, 0x79, 0x78, 0xff, 0x71, 0x70, 0x6e, 0xff, 0x72, 0x71, 0x70, 0xff, + 0x72, 0x73, 0x72, 0xff, 0x70, 0x70, 0x6e, 0xff, 0x6d, 0x6a, 0x6a, 0xff, + 0x64, 0x64, 0x63, 0xff, 0x69, 0x68, 0x67, 0xff, 0x61, 0x5f, 0x5e, 0xff, + 0x59, 0x57, 0x57, 0xff, 0x5f, 0x5f, 0x5e, 0xff, 0x55, 0x55, 0x53, 0xff, + 0x57, 0x58, 0x57, 0xff, 0x51, 0x53, 0x50, 0xff, 0x54, 0x51, 0x51, 0xff, + 0x4c, 0x4b, 0x4a, 0xff, 0x49, 0x4a, 0x47, 0xff, 0x4f, 0x51, 0x4e, 0xff, + 0x4f, 0x4d, 0x49, 0xff, 0x4c, 0x4b, 0x46, 0xff, + 0xa7, 0xaa, 0xaa, 0xff, 0x99, 0x98, 0x98, 0xff, 0x95, 0x92, 0x92, 0xff, + 0x94, 0x93, 0x92, 0xff, 0x8a, 0x87, 0x84, 0xff, 0x85, 0x80, 0x7f, 0xff, + 0x8d, 0x90, 0x8f, 0xff, 0x85, 0x85, 0x85, 0xff, 0x8e, 0x8e, 0x8e, 0xff, + 0x80, 0x80, 0x81, 0xff, 0x7c, 0x7d, 0x7b, 0xff, 0x79, 0x79, 0x78, 0xff, + 0x78, 0x79, 0x78, 0xff, 0x6e, 0x6c, 0x6b, 0xff, 0x68, 0x66, 0x66, 0xff, + 0x69, 0x6a, 0x67, 0xff, 0x60, 0x5e, 0x5d, 0xff, 0x5b, 0x58, 0x57, 0xff, + 0x58, 0x56, 0x55, 0xff, 0x61, 0x5e, 0x5d, 0xff, 0x54, 0x53, 0x52, 0xff, + 0x60, 0x5d, 0x5c, 0xff, 0x5b, 0x5b, 0x5a, 0xff, 0x59, 0x5a, 0x58, 0xff, + 0x48, 0x43, 0x42, 0xff, 0x44, 0x40, 0x40, 0xff, 0x48, 0x46, 0x44, 0xff, + 0x4a, 0x46, 0x46, 0xff, 0x4c, 0x4f, 0x4c, 0xff, 0x49, 0x4a, 0x48, 0xff, + 0x47, 0x46, 0x41, 0xff, 0x44, 0x43, 0x3f, 0xff, + 0xa2, 0xa4, 0xa4, 0xff, 0x96, 0x95, 0x96, 0xff, 0x8e, 0x8c, 0x8a, 0xff, + 0x89, 0x86, 0x86, 0xff, 0x82, 0x7c, 0x7c, 0xff, 0x83, 0x80, 0x7f, 0xff, + 0x82, 0x82, 0x80, 0xff, 0x82, 0x83, 0x81, 0xff, 0x82, 0x85, 0x85, 0xff, + 0x7c, 0x7c, 0x7c, 0xff, 0x77, 0x78, 0x75, 0xff, 0x75, 0x77, 0x76, 0xff, + 0x71, 0x72, 0x70, 0xff, 0x68, 0x66, 0x65, 0xff, 0x62, 0x60, 0x5f, 0xff, + 0x5f, 0x5e, 0x5c, 0xff, 0x5a, 0x52, 0x4f, 0xff, 0x5b, 0x53, 0x4f, 0xff, + 0x50, 0x49, 0x49, 0xff, 0x5c, 0x58, 0x57, 0xff, 0x50, 0x4b, 0x49, 0xff, + 0x57, 0x54, 0x53, 0xff, 0x4f, 0x4f, 0x4e, 0xff, 0x53, 0x57, 0x55, 0xff, + 0x48, 0x45, 0x44, 0xff, 0x3c, 0x33, 0x33, 0xff, 0x49, 0x45, 0x43, 0xff, + 0x41, 0x3f, 0x3d, 0xff, 0x49, 0x46, 0x44, 0xff, 0x4a, 0x48, 0x47, 0xff, + 0x3f, 0x3c, 0x3a, 0xff, 0x43, 0x41, 0x3e, 0xff, + 0x99, 0x9c, 0x9a, 0xff, 0x90, 0x8e, 0x8f, 0xff, 0x8c, 0x8b, 0x89, 0xff, + 0x81, 0x7c, 0x7c, 0xff, 0x7d, 0x78, 0x78, 0xff, 0x82, 0x82, 0x80, 0xff, + 0x77, 0x74, 0x73, 0xff, 0x75, 0x73, 0x73, 0xff, 0x78, 0x76, 0x76, 0xff, + 0x70, 0x6f, 0x6f, 0xff, 0x6d, 0x6c, 0x6b, 0xff, 0x6e, 0x6f, 0x6d, 0xff, + 0x68, 0x68, 0x66, 0xff, 0x5f, 0x5b, 0x5b, 0xff, 0x5b, 0x56, 0x56, 0xff, + 0x5a, 0x58, 0x57, 0xff, 0x53, 0x49, 0x47, 0xff, 0x4e, 0x45, 0x43, 0xff, + 0x49, 0x43, 0x41, 0xff, 0x5f, 0x5b, 0x5a, 0xff, 0x46, 0x3f, 0x3e, 0xff, + 0x4b, 0x48, 0x47, 0xff, 0x42, 0x3f, 0x3f, 0xff, 0x4d, 0x50, 0x50, 0xff, + 0x52, 0x52, 0x51, 0xff, 0x37, 0x31, 0x30, 0xff, 0x3d, 0x38, 0x37, 0xff, + 0x3f, 0x39, 0x38, 0xff, 0x40, 0x3c, 0x3b, 0xff, 0x4a, 0x48, 0x47, 0xff, + 0x3f, 0x3d, 0x3b, 0xff, 0x46, 0x45, 0x43, 0xff, +}; + +#endif // WEBP_TESTS_FUZZER_IMG_ALPHA_H_ diff --git a/third-party/webp/libwebp/tests/fuzzer/img_grid.h b/third-party/webp/libwebp/tests/fuzzer/img_grid.h new file mode 100644 index 0000000000..f269bbd609 --- /dev/null +++ b/third-party/webp/libwebp/tests/fuzzer/img_grid.h @@ -0,0 +1,125 @@ +// Copyright 2018 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + +#ifndef WEBP_TESTS_FUZZER_IMG_GRID_H_ +#define WEBP_TESTS_FUZZER_IMG_GRID_H_ + +#include + +static const int kImgGridWidth = 16; +static const int kImgGridHeight = 16; + +/*Pixel format: Red: 8 bit, Green: 8 bit, Blue: 8 bit, Fix 0xFF: 8 bit*/ +static const uint8_t kImgGridData[] = { + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, +}; + +#endif // WEBP_TESTS_FUZZER_IMG_GRID_H_ diff --git a/third-party/webp/libwebp/tests/fuzzer/img_peak.h b/third-party/webp/libwebp/tests/fuzzer/img_peak.h new file mode 100644 index 0000000000..d17ba1edb2 --- /dev/null +++ b/third-party/webp/libwebp/tests/fuzzer/img_peak.h @@ -0,0 +1,5533 @@ +// Copyright 2018 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + +#ifndef WEBP_TESTS_FUZZER_IMG_PEAK_H_ +#define WEBP_TESTS_FUZZER_IMG_PEAK_H_ + +#include + +static const int kImgPeakWidth = 128; +static const int kImgPeakHeight = 128; + +/*Pixel format: Red: 8 bit, Green: 8 bit, Blue: 8 bit, Fix 0xFF: 8 bit*/ +static const uint8_t kImgPeakData[] = { + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf7, 0xdd, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf7, 0xdd, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf7, 0xdd, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf7, 0xdd, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf7, 0xdd, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf7, 0xdd, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf7, 0xdd, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf7, 0xdd, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf7, 0xdd, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xe4, 0xe2, 0xd8, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xe4, 0xe2, 0xd8, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf7, 0xdd, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf7, 0xdd, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xec, 0xdb, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf7, 0xdd, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xf7, 0xdd, 0xcc, 0xff, 0xec, 0xd6, 0xc4, 0xff, 0xd9, 0xc6, 0xb4, 0xff, + 0xa7, 0x94, 0x84, 0xff, 0xa9, 0x9b, 0x8c, 0xff, 0xa9, 0x9b, 0x8c, 0xff, + 0xc5, 0xb7, 0xb4, 0xff, 0xc0, 0xaa, 0x9c, 0xff, 0xc4, 0xb2, 0xac, 0xff, + 0xe6, 0xd6, 0xcc, 0xff, 0xee, 0xdd, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xde, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xf7, 0xdd, 0xcc, 0xff, 0xf7, 0xdd, 0xcc, 0xff, 0xc0, 0xaa, 0x9c, 0xff, + 0x9c, 0x7e, 0x6c, 0xff, 0x8c, 0x6e, 0x64, 0xff, 0x94, 0x79, 0x6c, 0xff, + 0x94, 0x79, 0x6c, 0xff, 0x8e, 0x79, 0x74, 0xff, 0x9e, 0x8b, 0x84, 0xff, + 0x9c, 0x80, 0x7c, 0xff, 0x9e, 0x8b, 0x84, 0xff, 0xa6, 0x95, 0x94, 0xff, + 0xbf, 0xaa, 0xa4, 0xff, 0xc5, 0xb7, 0xb4, 0xff, 0xd6, 0xc5, 0xbc, 0xff, + 0xec, 0xdb, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xde, 0xd4, 0xff, + 0xd4, 0xb8, 0xac, 0xff, 0x94, 0x79, 0x6c, 0xff, 0x84, 0x6e, 0x5c, 0xff, + 0x94, 0x79, 0x6c, 0xff, 0x8d, 0x72, 0x6b, 0xff, 0x8a, 0x76, 0x6c, 0xff, + 0x9e, 0x8b, 0x84, 0xff, 0x9e, 0x8b, 0x84, 0xff, 0xa8, 0x93, 0x8c, 0xff, + 0x9c, 0x80, 0x7c, 0xff, 0x94, 0x8c, 0x8c, 0xff, 0x8f, 0x86, 0x7c, 0xff, + 0xc4, 0xb2, 0xac, 0xff, 0xcc, 0xbd, 0xbc, 0xff, 0xa8, 0x9b, 0x94, 0xff, + 0xd9, 0xcc, 0xbc, 0xff, 0xe4, 0xe2, 0xd8, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xdc, 0xbe, 0xb4, 0xff, 0xac, 0x8e, 0x7c, 0xff, 0x9c, 0x81, 0x74, 0xff, + 0x7c, 0x62, 0x54, 0xff, 0x80, 0x67, 0x5c, 0xff, 0xa4, 0x89, 0x7c, 0xff, + 0xbc, 0xa4, 0x9c, 0xff, 0x8d, 0x72, 0x6b, 0xff, 0xac, 0x8d, 0x84, 0xff, + 0x9c, 0x80, 0x7c, 0xff, 0x96, 0x85, 0x84, 0xff, 0xad, 0x9a, 0x9c, 0xff, + 0x96, 0x85, 0x84, 0xff, 0x96, 0x85, 0x84, 0xff, 0x96, 0x85, 0x84, 0xff, + 0xa8, 0x9b, 0x94, 0xff, 0xbc, 0xb1, 0xb4, 0xff, 0xc7, 0xb8, 0xac, 0xff, + 0xa8, 0x9b, 0x94, 0xff, 0xc9, 0xc0, 0xb4, 0xff, 0xe4, 0xd2, 0xc4, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xf2, 0xe9, 0xdc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf2, 0xe9, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xe4, 0xe2, 0xd8, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf7, 0xdd, 0xcc, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xec, 0xd6, 0xc4, 0xff, 0xa4, 0x89, 0x7c, 0xff, + 0x7c, 0x5c, 0x4c, 0xff, 0x7e, 0x67, 0x54, 0xff, 0x7c, 0x62, 0x54, 0xff, + 0x80, 0x67, 0x5c, 0xff, 0x8c, 0x6e, 0x64, 0xff, 0x8c, 0x6d, 0x6c, 0xff, + 0xac, 0x8d, 0x84, 0xff, 0x8c, 0x6e, 0x64, 0xff, 0xac, 0x8d, 0x8c, 0xff, + 0x8e, 0x79, 0x74, 0xff, 0x9c, 0x80, 0x7c, 0xff, 0x9c, 0x7a, 0x7c, 0xff, + 0x8e, 0x72, 0x74, 0xff, 0x9d, 0x8d, 0x8c, 0xff, 0xad, 0x9a, 0x9c, 0xff, + 0x96, 0x86, 0x8c, 0xff, 0xa8, 0x9b, 0x94, 0xff, 0xad, 0x9e, 0x9e, 0xff, + 0xd7, 0xcc, 0xc4, 0xff, 0xd6, 0xc5, 0xbc, 0xff, 0xb0, 0xa3, 0x9c, 0xff, + 0xc7, 0xb8, 0xac, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xf2, 0xe9, 0xdc, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xec, 0xd6, 0xc4, 0xff, 0x94, 0x76, 0x64, 0xff, 0x7c, 0x5c, 0x4c, 0xff, + 0x74, 0x5b, 0x4c, 0xff, 0x74, 0x5b, 0x4c, 0xff, 0x75, 0x56, 0x54, 0xff, + 0x80, 0x67, 0x5c, 0xff, 0x8d, 0x72, 0x6b, 0xff, 0x9c, 0x80, 0x7c, 0xff, + 0x8e, 0x79, 0x74, 0xff, 0x8e, 0x72, 0x74, 0xff, 0xa4, 0x85, 0x84, 0xff, + 0xa4, 0x85, 0x84, 0xff, 0x8e, 0x72, 0x74, 0xff, 0x8e, 0x72, 0x74, 0xff, + 0x9c, 0x80, 0x7c, 0xff, 0xad, 0x9e, 0x9e, 0xff, 0xad, 0x9a, 0x9c, 0xff, + 0x9c, 0x80, 0x7c, 0xff, 0xa1, 0x99, 0x9c, 0xff, 0xb1, 0xaa, 0xa4, 0xff, + 0xc4, 0xba, 0xbc, 0xff, 0x9c, 0x93, 0x8c, 0xff, 0xa8, 0x93, 0x8c, 0xff, + 0xa8, 0x93, 0x8c, 0xff, 0xc4, 0xb2, 0xac, 0xff, 0xee, 0xdd, 0xd4, 0xff, + 0xef, 0xe2, 0xdc, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xe7, 0xce, 0xbc, 0xff, + 0x84, 0x6e, 0x5c, 0xff, 0x74, 0x5b, 0x4c, 0xff, 0x74, 0x5b, 0x4c, 0xff, + 0x7c, 0x5d, 0x54, 0xff, 0x74, 0x5b, 0x4c, 0xff, 0x7f, 0x6a, 0x64, 0xff, + 0x8e, 0x79, 0x74, 0xff, 0xa8, 0x93, 0x8c, 0xff, 0xa4, 0x85, 0x84, 0xff, + 0x9c, 0x80, 0x7c, 0xff, 0xa4, 0x85, 0x84, 0xff, 0xcc, 0xaa, 0xac, 0xff, + 0x9c, 0x80, 0x7c, 0xff, 0x9c, 0x80, 0x7c, 0xff, 0x8e, 0x72, 0x74, 0xff, + 0x8c, 0x81, 0x84, 0xff, 0xad, 0x9a, 0x9c, 0xff, 0xad, 0x9e, 0x9e, 0xff, + 0x96, 0x85, 0x84, 0xff, 0xbc, 0xb6, 0xac, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0x8f, 0x86, 0x7c, 0xff, 0xbc, 0xb0, 0xac, 0xff, 0x8f, 0x7f, 0x7c, 0xff, + 0x9d, 0x8d, 0x8c, 0xff, 0xa8, 0x9b, 0x94, 0xff, 0xdc, 0xbe, 0xb4, 0xff, + 0xee, 0xdd, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf7, 0xdd, 0xcc, 0xff, 0x84, 0x6e, 0x5c, 0xff, + 0x6f, 0x56, 0x44, 0xff, 0x74, 0x5b, 0x4c, 0xff, 0x74, 0x5b, 0x4c, 0xff, + 0x69, 0x4e, 0x44, 0xff, 0x94, 0x79, 0x6c, 0xff, 0xad, 0x9e, 0x9e, 0xff, + 0xbd, 0xa6, 0xa4, 0xff, 0xb4, 0x96, 0x94, 0xff, 0x8e, 0x79, 0x74, 0xff, + 0x8e, 0x72, 0x74, 0xff, 0xbd, 0xa6, 0xa4, 0xff, 0xdc, 0xba, 0xbc, 0xff, + 0xc6, 0xb1, 0xb4, 0xff, 0xac, 0x8d, 0x8c, 0xff, 0x7e, 0x6d, 0x6c, 0xff, + 0x9c, 0x7a, 0x7c, 0xff, 0x84, 0x77, 0x74, 0xff, 0xad, 0x9e, 0x9e, 0xff, + 0xbc, 0xb0, 0xac, 0xff, 0xd5, 0xcd, 0xcc, 0xff, 0x9c, 0x93, 0x8c, 0xff, + 0x9d, 0x8d, 0x8c, 0xff, 0xad, 0x9e, 0x9e, 0xff, 0xad, 0x9a, 0x9c, 0xff, + 0x8f, 0x86, 0x7c, 0xff, 0xa8, 0x93, 0x8c, 0xff, 0xbc, 0xb0, 0xac, 0xff, + 0xee, 0xdd, 0xd4, 0xff, 0xee, 0xdd, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xe7, 0xce, 0xbc, 0xff, 0x9c, 0x7e, 0x6c, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x69, 0x4e, 0x44, 0xff, + 0x75, 0x56, 0x54, 0xff, 0x8d, 0x72, 0x6b, 0xff, 0xd4, 0xc6, 0xc4, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0xef, 0xe2, 0xdc, 0xff, 0xc4, 0xba, 0xbc, 0xff, + 0x96, 0x85, 0x84, 0xff, 0xad, 0x9e, 0x9e, 0xff, 0xe4, 0xce, 0xcc, 0xff, + 0xec, 0xde, 0xdc, 0xff, 0xf8, 0xea, 0xec, 0xff, 0xc5, 0xb7, 0xb4, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0x84, 0x77, 0x74, 0xff, 0xa6, 0x95, 0x94, 0xff, + 0xbc, 0xb1, 0xb4, 0xff, 0xc4, 0xba, 0xbc, 0xff, 0x94, 0x8c, 0x8c, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0xa1, 0x9e, 0x9c, 0xff, 0xb3, 0xae, 0xac, 0xff, + 0xa8, 0x9b, 0x94, 0xff, 0x89, 0x86, 0x84, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0xbc, 0xb0, 0xac, 0xff, 0xee, 0xdd, 0xd4, 0xff, 0xf2, 0xe9, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xd4, 0xc2, 0xac, 0xff, + 0x7e, 0x67, 0x54, 0xff, 0x7c, 0x5c, 0x4c, 0xff, 0x7c, 0x5c, 0x4c, 0xff, + 0x74, 0x4e, 0x44, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x74, 0x4e, 0x44, 0xff, + 0x7f, 0x6a, 0x64, 0xff, 0xac, 0x8d, 0x8c, 0xff, 0xa6, 0x95, 0x94, 0xff, + 0xc6, 0xb1, 0xb4, 0xff, 0xdc, 0xdc, 0xdc, 0xff, 0xd6, 0xd2, 0xd4, 0xff, + 0x9c, 0x80, 0x7c, 0xff, 0xa6, 0x95, 0x94, 0xff, 0xdc, 0xba, 0xbc, 0xff, + 0xcf, 0xc6, 0xcc, 0xff, 0xbc, 0xb0, 0xac, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0x9d, 0x8d, 0x8c, 0xff, 0x8e, 0x7a, 0x7c, 0xff, 0xba, 0xb6, 0xb4, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0xad, 0x9e, 0x9e, 0xff, 0x8f, 0x7f, 0x7c, 0xff, + 0xa1, 0x99, 0x9c, 0xff, 0xb3, 0xae, 0xac, 0xff, 0xb4, 0xaa, 0xac, 0xff, + 0xc4, 0xba, 0xbc, 0xff, 0xba, 0xb0, 0xa4, 0xff, 0xad, 0x9e, 0x9e, 0xff, + 0xad, 0x9e, 0x9e, 0xff, 0xbd, 0xa6, 0xa4, 0xff, 0xec, 0xdb, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xe7, 0xce, 0xbc, 0xff, 0x7c, 0x62, 0x54, 0xff, + 0x6f, 0x56, 0x44, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x7c, 0x5d, 0x54, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x6a, 0x53, 0x4c, 0xff, 0x69, 0x4e, 0x4c, 0xff, + 0x8d, 0x72, 0x6b, 0xff, 0xa6, 0x95, 0x94, 0xff, 0x9e, 0x8b, 0x84, 0xff, + 0xb0, 0xa3, 0x9c, 0xff, 0x94, 0x8c, 0x8c, 0xff, 0x9d, 0x8d, 0x8c, 0xff, + 0x7e, 0x6d, 0x6c, 0xff, 0x8c, 0x81, 0x84, 0xff, 0x8e, 0x7a, 0x7c, 0xff, + 0xa6, 0x95, 0x94, 0xff, 0x7e, 0x6d, 0x6c, 0xff, 0x77, 0x66, 0x6c, 0xff, + 0x84, 0x77, 0x74, 0xff, 0x9e, 0x8b, 0x84, 0xff, 0xd5, 0xcd, 0xcc, 0xff, + 0x94, 0x8b, 0x84, 0xff, 0x84, 0x77, 0x74, 0xff, 0x9e, 0x8e, 0x94, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0xb4, 0xaa, 0xac, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0xb4, 0xaa, 0xac, 0xff, 0xc5, 0xb7, 0xb4, 0xff, 0xa6, 0x95, 0x94, 0xff, + 0xba, 0xb0, 0xa4, 0xff, 0x94, 0x8b, 0x84, 0xff, 0xba, 0xb0, 0xa4, 0xff, + 0xec, 0xd6, 0xc4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xc7, 0xb2, 0xa4, 0xff, 0x7e, 0x67, 0x54, 0xff, 0x6f, 0x56, 0x44, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x7c, 0x5c, 0x4c, 0xff, 0x7c, 0x5d, 0x54, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x74, 0x4e, 0x44, 0xff, + 0x78, 0x66, 0x64, 0xff, 0x9c, 0x80, 0x7c, 0xff, 0x7e, 0x6d, 0x6c, 0xff, + 0x84, 0x77, 0x74, 0xff, 0x81, 0x7e, 0x7c, 0xff, 0x81, 0x7e, 0x7c, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0x9c, 0x80, 0x7c, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0x6f, 0x6c, 0x6c, 0xff, 0x7f, 0x6a, 0x64, 0xff, 0x78, 0x66, 0x64, 0xff, + 0x72, 0x62, 0x5c, 0xff, 0x84, 0x77, 0x74, 0xff, 0x9d, 0x8d, 0x8c, 0xff, + 0x8c, 0x81, 0x84, 0xff, 0x9e, 0x8b, 0x84, 0xff, 0x84, 0x77, 0x74, 0xff, + 0x71, 0x6a, 0x64, 0xff, 0xae, 0xa4, 0xa4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0x94, 0x8c, 0x8c, 0xff, 0x8f, 0x7f, 0x7c, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0x94, 0x8b, 0x84, 0xff, 0xa1, 0x9e, 0x9c, 0xff, + 0xe6, 0xd6, 0xcc, 0xff, 0xef, 0xe2, 0xdc, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xec, 0xdb, 0xcc, 0xff, 0x9c, 0x7e, 0x6c, 0xff, + 0x74, 0x5b, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x74, 0x5b, 0x4c, 0xff, + 0x7c, 0x5c, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x74, 0x5b, 0x4c, 0xff, + 0x7c, 0x5d, 0x54, 0xff, 0x69, 0x4e, 0x44, 0xff, 0x7c, 0x5d, 0x54, 0xff, + 0x9c, 0x7a, 0x74, 0xff, 0x8d, 0x72, 0x6b, 0xff, 0x70, 0x5e, 0x5c, 0xff, + 0x8a, 0x76, 0x6c, 0xff, 0x71, 0x6a, 0x64, 0xff, 0x96, 0x85, 0x84, 0xff, + 0x7f, 0x6a, 0x64, 0xff, 0x94, 0x8c, 0x8c, 0xff, 0x94, 0x8b, 0x84, 0xff, + 0x84, 0x77, 0x74, 0xff, 0x9e, 0x8b, 0x84, 0xff, 0x8f, 0x7f, 0x7c, 0xff, + 0x7e, 0x6d, 0x6c, 0xff, 0x78, 0x66, 0x64, 0xff, 0x70, 0x5e, 0x5c, 0xff, + 0x84, 0x77, 0x74, 0xff, 0x9e, 0x8b, 0x84, 0xff, 0x78, 0x66, 0x64, 0xff, + 0x6c, 0x61, 0x64, 0xff, 0x8c, 0x81, 0x84, 0xff, 0xc4, 0xb2, 0xac, 0xff, + 0xcc, 0xbd, 0xbc, 0xff, 0xbc, 0xb6, 0xac, 0xff, 0xd7, 0xcc, 0xc4, 0xff, + 0xc9, 0xc0, 0xb4, 0xff, 0xae, 0xa4, 0xa4, 0xff, 0xc5, 0xb7, 0xb4, 0xff, + 0xc5, 0xb7, 0xb4, 0xff, 0xd9, 0xcc, 0xbc, 0xff, 0xef, 0xe2, 0xdc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xec, 0xd6, 0xc4, 0xff, 0x84, 0x6e, 0x5c, 0xff, 0x74, 0x5b, 0x4c, 0xff, + 0x74, 0x5b, 0x4c, 0xff, 0x69, 0x4e, 0x44, 0xff, 0x7c, 0x5d, 0x54, 0xff, + 0x74, 0x5b, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x69, 0x4e, 0x4c, 0xff, 0x80, 0x67, 0x5c, 0xff, + 0x8d, 0x72, 0x6b, 0xff, 0x72, 0x5b, 0x54, 0xff, 0x72, 0x5b, 0x54, 0xff, + 0x6b, 0x56, 0x5c, 0xff, 0x7f, 0x6a, 0x64, 0xff, 0x84, 0x77, 0x74, 0xff, + 0x8e, 0x79, 0x74, 0xff, 0x7e, 0x6d, 0x6c, 0xff, 0x72, 0x62, 0x5c, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0x7f, 0x72, 0x6c, 0xff, 0x72, 0x62, 0x5c, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0x7f, 0x6a, 0x64, 0xff, 0x7f, 0x6a, 0x64, 0xff, + 0x78, 0x66, 0x64, 0xff, 0x7e, 0x6d, 0x6c, 0xff, 0x78, 0x66, 0x64, 0xff, + 0x8f, 0x7f, 0x7c, 0xff, 0xa6, 0x95, 0x94, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0xb4, 0xaa, 0xac, 0xff, 0xae, 0xa4, 0xa4, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0xbc, 0xb0, 0xac, 0xff, 0xbc, 0xb6, 0xac, 0xff, 0xcc, 0xc5, 0xc4, 0xff, + 0xd9, 0xd4, 0xcc, 0xff, 0xc4, 0xba, 0xbc, 0xff, 0xd6, 0xc5, 0xbc, 0xff, + 0xef, 0xe2, 0xdc, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xd9, 0xc6, 0xb4, 0xff, + 0x7e, 0x67, 0x54, 0xff, 0x6f, 0x56, 0x44, 0xff, 0x74, 0x5b, 0x4c, 0xff, + 0x69, 0x4e, 0x44, 0xff, 0x7e, 0x67, 0x54, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x7c, 0x5d, 0x54, 0xff, 0x74, 0x4e, 0x4c, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x7d, 0x62, 0x5c, 0xff, 0x80, 0x67, 0x5c, 0xff, + 0x75, 0x56, 0x54, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x6a, 0x53, 0x4c, 0xff, + 0x69, 0x4e, 0x4c, 0xff, 0x7c, 0x5d, 0x54, 0xff, 0x7e, 0x6d, 0x6c, 0xff, + 0x7c, 0x5d, 0x54, 0xff, 0x78, 0x66, 0x64, 0xff, 0x72, 0x5b, 0x54, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x72, 0x5b, 0x54, 0xff, 0x72, 0x62, 0x5c, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x7d, 0x62, 0x5c, 0xff, 0x7f, 0x72, 0x6c, 0xff, + 0x7c, 0x72, 0x64, 0xff, 0x72, 0x5b, 0x54, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x81, 0x72, 0x74, 0xff, 0x9a, 0x94, 0x94, 0xff, 0xb4, 0xaa, 0xac, 0xff, + 0xa6, 0x95, 0x94, 0xff, 0x94, 0x8c, 0x8c, 0xff, 0x94, 0x8c, 0x8c, 0xff, + 0x94, 0x8b, 0x84, 0xff, 0xba, 0xb6, 0xb4, 0xff, 0xba, 0xb6, 0xb4, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xe4, 0xde, 0xdc, 0xff, 0xcc, 0xc2, 0xbc, 0xff, + 0xcc, 0xc2, 0xbc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf2, 0xe9, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xd9, 0xc6, 0xb4, 0xff, 0x74, 0x5b, 0x4c, 0xff, + 0x74, 0x5b, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x6f, 0x56, 0x44, 0xff, + 0x7c, 0x62, 0x54, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x7c, 0x5c, 0x4c, 0xff, 0x69, 0x4e, 0x44, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x7c, 0x5d, 0x54, 0xff, 0x7c, 0x5d, 0x54, 0xff, 0x7c, 0x5d, 0x54, 0xff, + 0x7c, 0x5d, 0x54, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x75, 0x56, 0x54, 0xff, + 0x75, 0x56, 0x54, 0xff, 0x8f, 0x7f, 0x7c, 0xff, 0x7d, 0x62, 0x5c, 0xff, + 0x69, 0x55, 0x54, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x6b, 0x56, 0x5c, 0xff, 0x8d, 0x72, 0x6b, 0xff, + 0x75, 0x56, 0x54, 0xff, 0x69, 0x55, 0x54, 0xff, 0x8d, 0x72, 0x6b, 0xff, + 0x8e, 0x79, 0x74, 0xff, 0x75, 0x62, 0x64, 0xff, 0x72, 0x5b, 0x54, 0xff, + 0x8f, 0x7f, 0x7c, 0xff, 0xad, 0x9a, 0x9c, 0xff, 0x9e, 0x8e, 0x94, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0x8f, 0x7f, 0x7c, 0xff, 0x94, 0x8b, 0x84, 0xff, + 0x81, 0x7e, 0x7c, 0xff, 0x7b, 0x7a, 0x7c, 0xff, 0x94, 0x8c, 0x8c, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xd5, 0xcd, 0xcc, 0xff, 0xb1, 0xaa, 0xa4, 0xff, + 0xc7, 0xb8, 0xac, 0xff, 0xda, 0xd4, 0xc4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xd4, 0xb8, 0xac, 0xff, 0x80, 0x67, 0x5c, 0xff, 0x74, 0x5b, 0x4c, 0xff, + 0x74, 0x5b, 0x4c, 0xff, 0x7c, 0x5c, 0x4c, 0xff, 0x7c, 0x5d, 0x54, 0xff, + 0x7c, 0x5c, 0x4c, 0xff, 0x74, 0x5b, 0x4c, 0xff, 0x7c, 0x5c, 0x4c, 0xff, + 0x74, 0x5b, 0x4c, 0xff, 0x74, 0x4e, 0x44, 0xff, 0x7c, 0x5c, 0x4c, 0xff, + 0x7c, 0x5d, 0x54, 0xff, 0x7c, 0x5d, 0x54, 0xff, 0x7c, 0x5e, 0x5c, 0xff, + 0x7c, 0x5d, 0x54, 0xff, 0x75, 0x56, 0x54, 0xff, 0x75, 0x56, 0x54, 0xff, + 0x7c, 0x5e, 0x5c, 0xff, 0x8c, 0x6e, 0x64, 0xff, 0x75, 0x56, 0x54, 0xff, + 0x6a, 0x53, 0x4c, 0xff, 0x69, 0x4e, 0x4c, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x61, 0x48, 0x44, 0xff, 0x61, 0x48, 0x44, 0xff, 0x94, 0x8b, 0x84, 0xff, + 0x8d, 0x72, 0x6b, 0xff, 0x75, 0x56, 0x54, 0xff, 0x9c, 0x80, 0x7c, 0xff, + 0x96, 0x85, 0x84, 0xff, 0x75, 0x56, 0x54, 0xff, 0x78, 0x66, 0x64, 0xff, + 0x84, 0x77, 0x74, 0xff, 0xb1, 0xaa, 0xa4, 0xff, 0x94, 0x8b, 0x84, 0xff, + 0x8f, 0x7f, 0x7c, 0xff, 0x81, 0x72, 0x74, 0xff, 0x96, 0x85, 0x84, 0xff, + 0x9d, 0x8d, 0x8c, 0xff, 0x8c, 0x81, 0x84, 0xff, 0x96, 0x85, 0x84, 0xff, + 0xa4, 0x9e, 0xa4, 0xff, 0xd4, 0xc6, 0xc4, 0xff, 0xc5, 0xb7, 0xb4, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0xae, 0xa4, 0xa4, 0xff, 0xd7, 0xcc, 0xc4, 0xff, + 0xef, 0xe2, 0xdc, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xac, 0x8e, 0x7c, 0xff, + 0x7c, 0x5c, 0x4c, 0xff, 0x74, 0x5b, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x7c, 0x5d, 0x54, 0xff, 0x74, 0x5b, 0x4c, 0xff, + 0x74, 0x5b, 0x4c, 0xff, 0x74, 0x5b, 0x4c, 0xff, 0x6f, 0x56, 0x44, 0xff, + 0x74, 0x5b, 0x4c, 0xff, 0x6f, 0x56, 0x44, 0xff, 0x7c, 0x62, 0x54, 0xff, + 0x7c, 0x5d, 0x54, 0xff, 0x7d, 0x62, 0x5c, 0xff, 0x7d, 0x62, 0x5c, 0xff, + 0x8c, 0x6e, 0x64, 0xff, 0x6b, 0x56, 0x5c, 0xff, 0x7c, 0x5d, 0x54, 0xff, + 0x7c, 0x5d, 0x54, 0xff, 0x70, 0x5e, 0x5c, 0xff, 0x75, 0x56, 0x54, 0xff, + 0x75, 0x56, 0x54, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x6a, 0x53, 0x4c, 0xff, + 0x61, 0x48, 0x44, 0xff, 0x69, 0x4e, 0x4c, 0xff, 0x8f, 0x7f, 0x7c, 0xff, + 0x7d, 0x62, 0x5c, 0xff, 0x7d, 0x62, 0x5c, 0xff, 0xb4, 0x9b, 0x94, 0xff, + 0x96, 0x85, 0x84, 0xff, 0x7c, 0x5d, 0x54, 0xff, 0x75, 0x56, 0x54, 0xff, + 0x7c, 0x72, 0x64, 0xff, 0x9d, 0x8d, 0x8c, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0xbc, 0xb0, 0xac, 0xff, 0x84, 0x77, 0x74, 0xff, 0x9d, 0x8d, 0x8c, 0xff, + 0x96, 0x85, 0x84, 0xff, 0xad, 0x9a, 0x9c, 0xff, 0x96, 0x86, 0x8c, 0xff, + 0x81, 0x72, 0x74, 0xff, 0xa1, 0x99, 0x9c, 0xff, 0xcc, 0xbd, 0xbc, 0xff, + 0x88, 0x8a, 0x84, 0xff, 0xae, 0xa4, 0xa4, 0xff, 0xc2, 0xc2, 0xbc, 0xff, + 0xd5, 0xcd, 0xcc, 0xff, 0xf2, 0xe9, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xa4, 0x86, 0x74, 0xff, 0x74, 0x5b, 0x4c, 0xff, + 0x69, 0x4e, 0x44, 0xff, 0x74, 0x5b, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x7c, 0x5d, 0x54, 0xff, 0x74, 0x5b, 0x4c, 0xff, + 0x7c, 0x5d, 0x54, 0xff, 0x74, 0x5b, 0x4c, 0xff, 0x69, 0x4e, 0x44, 0xff, + 0x74, 0x5b, 0x4c, 0xff, 0x7c, 0x5c, 0x4c, 0xff, 0x7c, 0x62, 0x54, 0xff, + 0x7d, 0x62, 0x5c, 0xff, 0x8d, 0x72, 0x6b, 0xff, 0x7d, 0x62, 0x5c, 0xff, + 0x8e, 0x72, 0x74, 0xff, 0x9c, 0x80, 0x7c, 0xff, 0x7d, 0x62, 0x5c, 0xff, + 0x75, 0x56, 0x54, 0xff, 0x7d, 0x62, 0x5c, 0xff, 0x72, 0x5b, 0x54, 0xff, + 0x6c, 0x4a, 0x44, 0xff, 0x58, 0x49, 0x4c, 0xff, 0x74, 0x4e, 0x4c, 0xff, + 0x61, 0x48, 0x44, 0xff, 0x50, 0x4e, 0x44, 0xff, 0x7c, 0x5e, 0x5c, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0x8f, 0x7f, 0x7c, 0xff, 0xbc, 0xa4, 0x9c, 0xff, + 0x8e, 0x79, 0x74, 0xff, 0x72, 0x5b, 0x54, 0xff, 0x70, 0x5e, 0x5c, 0xff, + 0x84, 0x77, 0x74, 0xff, 0x84, 0x77, 0x74, 0xff, 0x9e, 0x8b, 0x84, 0xff, + 0x9d, 0x8d, 0x8c, 0xff, 0x8c, 0x81, 0x84, 0xff, 0x96, 0x86, 0x8c, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0xbc, 0xaa, 0xac, 0xff, 0xc4, 0xba, 0xbc, 0xff, + 0x84, 0x77, 0x74, 0xff, 0x8f, 0x7f, 0x7c, 0xff, 0xad, 0x9e, 0x9e, 0xff, + 0xb1, 0xaa, 0xa4, 0xff, 0xb3, 0xae, 0xac, 0xff, 0xb1, 0xaa, 0xa4, 0xff, + 0xc9, 0xc0, 0xb4, 0xff, 0xf2, 0xe9, 0xdc, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xac, 0x8e, 0x7c, 0xff, 0x6f, 0x56, 0x44, 0xff, 0x74, 0x5b, 0x4c, 0xff, + 0x74, 0x5b, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x7c, 0x5d, 0x54, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x7c, 0x5d, 0x54, 0xff, 0x7c, 0x5d, 0x54, 0xff, 0x7c, 0x5d, 0x54, 0xff, + 0x80, 0x67, 0x5c, 0xff, 0x7c, 0x5d, 0x54, 0xff, 0x75, 0x62, 0x64, 0xff, + 0x9c, 0x7a, 0x74, 0xff, 0xa4, 0x85, 0x84, 0xff, 0x9c, 0x7a, 0x7c, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x7d, 0x62, 0x5c, 0xff, 0x70, 0x5e, 0x5c, 0xff, + 0x75, 0x56, 0x54, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x6a, 0x53, 0x4c, 0xff, + 0x69, 0x55, 0x54, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x6a, 0x53, 0x4c, 0xff, + 0x69, 0x55, 0x54, 0xff, 0x9c, 0x80, 0x7c, 0xff, 0xbc, 0xa4, 0x9c, 0xff, + 0x7f, 0x72, 0x6c, 0xff, 0x7d, 0x62, 0x5c, 0xff, 0x7c, 0x5e, 0x5c, 0xff, + 0x84, 0x77, 0x74, 0xff, 0x5d, 0x5a, 0x54, 0xff, 0x70, 0x5e, 0x5c, 0xff, + 0x7e, 0x6d, 0x6c, 0xff, 0x8c, 0x81, 0x84, 0xff, 0xa8, 0x9b, 0x94, 0xff, + 0xc6, 0xb1, 0xb4, 0xff, 0xc4, 0xba, 0xbc, 0xff, 0xb4, 0xaa, 0xac, 0xff, + 0x78, 0x66, 0x64, 0xff, 0x84, 0x77, 0x74, 0xff, 0x94, 0x8c, 0x8c, 0xff, + 0x9d, 0x8d, 0x8c, 0xff, 0xa8, 0x9b, 0x94, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0xb0, 0xa3, 0x9c, 0xff, 0xd7, 0xcc, 0xc4, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xf7, 0xdd, 0xcc, 0xff, 0xf7, 0xdd, 0xcc, 0xff, 0x94, 0x79, 0x6c, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x6f, 0x56, 0x44, 0xff, + 0x69, 0x4e, 0x44, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x7c, 0x5d, 0x54, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x6a, 0x53, 0x4c, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x7c, 0x5d, 0x54, 0xff, + 0x64, 0x5a, 0x4c, 0xff, 0x7c, 0x5d, 0x54, 0xff, 0x7c, 0x5d, 0x54, 0xff, + 0x75, 0x62, 0x64, 0xff, 0x8d, 0x72, 0x6b, 0xff, 0x8c, 0x6d, 0x6c, 0xff, + 0x8c, 0x6d, 0x6c, 0xff, 0x9c, 0x80, 0x7c, 0xff, 0x8c, 0x6d, 0x6c, 0xff, + 0x7c, 0x5e, 0x5c, 0xff, 0x69, 0x4e, 0x4c, 0xff, 0x6a, 0x53, 0x4c, 0xff, + 0x75, 0x56, 0x54, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x70, 0x5e, 0x5c, 0xff, + 0x69, 0x4e, 0x4c, 0xff, 0x6a, 0x53, 0x4c, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x7c, 0x5d, 0x54, 0xff, 0x78, 0x66, 0x64, 0xff, 0x72, 0x5b, 0x54, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x7e, 0x6d, 0x6c, 0xff, 0x7c, 0x5d, 0x54, 0xff, + 0x72, 0x62, 0x5c, 0xff, 0x7d, 0x62, 0x5c, 0xff, 0x78, 0x66, 0x64, 0xff, + 0x78, 0x66, 0x64, 0xff, 0x78, 0x66, 0x64, 0xff, 0xa4, 0x9e, 0xa4, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0xad, 0x9e, 0x9e, 0xff, 0x9d, 0x8d, 0x8c, 0xff, + 0x7e, 0x6d, 0x6c, 0xff, 0x78, 0x66, 0x64, 0xff, 0x84, 0x77, 0x74, 0xff, + 0x8f, 0x7f, 0x7c, 0xff, 0x94, 0x8c, 0x8c, 0xff, 0x9d, 0x8d, 0x8c, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0xae, 0xa4, 0xa4, 0xff, 0xec, 0xdb, 0xcc, 0xff, + 0xf2, 0xe9, 0xdc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xfc, 0xe2, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xf7, 0xdd, 0xcc, 0xff, 0x94, 0x76, 0x64, 0xff, 0x69, 0x4e, 0x44, 0xff, + 0x74, 0x5b, 0x4c, 0xff, 0x69, 0x4e, 0x44, 0xff, 0x6f, 0x56, 0x44, 0xff, + 0x74, 0x5b, 0x4c, 0xff, 0x7c, 0x5d, 0x54, 0xff, 0x7c, 0x5d, 0x54, 0xff, + 0x69, 0x4e, 0x4c, 0xff, 0x6a, 0x53, 0x4c, 0xff, 0x74, 0x4e, 0x4c, 0xff, + 0x7c, 0x5d, 0x54, 0xff, 0x7d, 0x62, 0x5c, 0xff, 0x8e, 0x79, 0x74, 0xff, + 0x7c, 0x5e, 0x5c, 0xff, 0x72, 0x62, 0x5c, 0xff, 0x7d, 0x62, 0x5c, 0xff, + 0x8c, 0x6e, 0x64, 0xff, 0x78, 0x66, 0x64, 0xff, 0x7f, 0x6a, 0x64, 0xff, + 0x78, 0x66, 0x64, 0xff, 0x7d, 0x62, 0x5c, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x6a, 0x53, 0x4c, 0xff, 0x72, 0x5b, 0x54, 0xff, 0x7d, 0x62, 0x5c, 0xff, + 0x7c, 0x5e, 0x5c, 0xff, 0x6a, 0x53, 0x4c, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x80, 0x67, 0x5c, 0xff, 0x75, 0x56, 0x54, 0xff, 0x50, 0x4e, 0x44, 0xff, + 0x69, 0x4e, 0x4c, 0xff, 0x69, 0x4e, 0x4c, 0xff, 0x6a, 0x53, 0x4c, 0xff, + 0x7f, 0x6a, 0x64, 0xff, 0x8f, 0x7f, 0x7c, 0xff, 0x7e, 0x6d, 0x6c, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x7e, 0x6d, 0x6c, 0xff, 0x8c, 0x81, 0x84, 0xff, + 0x9d, 0x8d, 0x8c, 0xff, 0x8c, 0x81, 0x84, 0xff, 0x96, 0x85, 0x84, 0xff, + 0xb4, 0xaa, 0xac, 0xff, 0xad, 0x9e, 0x9e, 0xff, 0x8e, 0x7a, 0x7c, 0xff, + 0x96, 0x85, 0x84, 0xff, 0x8c, 0x81, 0x84, 0xff, 0x8f, 0x7f, 0x7c, 0xff, + 0x8e, 0x7a, 0x7c, 0xff, 0x9e, 0x8e, 0x94, 0xff, 0x9a, 0x94, 0x94, 0xff, + 0xbf, 0xaa, 0xa4, 0xff, 0xa8, 0x9b, 0x94, 0xff, 0xd9, 0xcc, 0xbc, 0xff, + 0xef, 0xe2, 0xdc, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xf2, 0xe9, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0x9c, 0x80, 0x7c, 0xff, 0x6f, 0x56, 0x44, 0xff, 0x74, 0x5b, 0x4c, 0xff, + 0x7c, 0x5c, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x74, 0x5b, 0x4c, 0xff, + 0x7c, 0x5d, 0x54, 0xff, 0x7c, 0x5d, 0x54, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x69, 0x4e, 0x44, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x7c, 0x5e, 0x5c, 0xff, 0x8c, 0x6d, 0x6c, 0xff, 0x9c, 0x80, 0x7c, 0xff, + 0x8d, 0x72, 0x6b, 0xff, 0x69, 0x55, 0x54, 0xff, 0x78, 0x66, 0x64, 0xff, + 0x96, 0x85, 0x84, 0xff, 0x7c, 0x5d, 0x54, 0xff, 0x70, 0x5e, 0x5c, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x6a, 0x53, 0x4c, 0xff, 0x70, 0x5e, 0x5c, 0xff, + 0x80, 0x67, 0x5c, 0xff, 0x78, 0x66, 0x64, 0xff, 0x90, 0x7f, 0x74, 0xff, + 0x8e, 0x79, 0x74, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x75, 0x56, 0x54, 0xff, + 0x7f, 0x6a, 0x64, 0xff, 0x61, 0x48, 0x44, 0xff, 0x69, 0x4e, 0x44, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x69, 0x4e, 0x44, 0xff, 0x70, 0x5e, 0x5c, 0xff, + 0x90, 0x7f, 0x74, 0xff, 0x9c, 0x88, 0x7c, 0xff, 0x72, 0x5b, 0x54, 0xff, + 0x69, 0x55, 0x54, 0xff, 0x8e, 0x79, 0x74, 0xff, 0xac, 0x8d, 0x8c, 0xff, + 0xa6, 0x95, 0x94, 0xff, 0xad, 0x9e, 0x9e, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0xb3, 0xae, 0xac, 0xff, 0x94, 0x8c, 0x8c, 0xff, 0x84, 0x77, 0x74, 0xff, + 0x9c, 0x80, 0x7c, 0xff, 0x96, 0x85, 0x84, 0xff, 0x9d, 0x8d, 0x8c, 0xff, + 0x8e, 0x7a, 0x7c, 0xff, 0xa6, 0x95, 0x94, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0xc6, 0xb1, 0xb4, 0xff, 0xa6, 0x95, 0x94, 0xff, 0xba, 0xb0, 0xa4, 0xff, + 0xe6, 0xd6, 0xcc, 0xff, 0xf2, 0xe9, 0xdc, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xea, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe2, 0xcc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xac, 0x8e, 0x7c, 0xff, + 0x69, 0x4e, 0x44, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x74, 0x5b, 0x4c, 0xff, 0x7c, 0x5d, 0x54, 0xff, + 0x7c, 0x5d, 0x54, 0xff, 0x74, 0x5b, 0x4c, 0xff, 0x74, 0x4e, 0x44, 0xff, + 0x69, 0x4e, 0x4c, 0xff, 0x6c, 0x4a, 0x44, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x78, 0x66, 0x64, 0xff, 0xac, 0x8d, 0x8c, 0xff, 0xbf, 0xaa, 0xa4, 0xff, + 0xad, 0x9e, 0x9e, 0xff, 0x70, 0x5e, 0x5c, 0xff, 0x9c, 0x80, 0x7c, 0xff, + 0x7e, 0x6d, 0x6c, 0xff, 0x69, 0x55, 0x54, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x6a, 0x53, 0x4c, 0xff, 0x61, 0x48, 0x44, 0xff, 0x6a, 0x53, 0x4c, 0xff, + 0x80, 0x67, 0x5c, 0xff, 0x8a, 0x76, 0x6c, 0xff, 0x7c, 0x5d, 0x54, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x80, 0x67, 0x5c, 0xff, 0x6a, 0x53, 0x4c, 0xff, + 0x69, 0x4e, 0x44, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x69, 0x4e, 0x44, 0xff, 0x69, 0x4e, 0x4c, 0xff, 0x69, 0x4e, 0x44, 0xff, + 0x8e, 0x79, 0x74, 0xff, 0x7c, 0x5d, 0x54, 0xff, 0x69, 0x4e, 0x4c, 0xff, + 0x64, 0x4e, 0x54, 0xff, 0x9c, 0x7a, 0x74, 0xff, 0xad, 0x9a, 0x9c, 0xff, + 0x96, 0x85, 0x84, 0xff, 0x96, 0x85, 0x84, 0xff, 0x9d, 0x8d, 0x8c, 0xff, + 0xc4, 0xba, 0xbc, 0xff, 0x9a, 0x94, 0x94, 0xff, 0x8c, 0x81, 0x84, 0xff, + 0x94, 0x8b, 0x84, 0xff, 0x96, 0x85, 0x84, 0xff, 0x84, 0x79, 0x7c, 0xff, + 0x81, 0x72, 0x74, 0xff, 0x9d, 0x8d, 0x8c, 0xff, 0xad, 0x9e, 0x9e, 0xff, + 0xbc, 0xb1, 0xb4, 0xff, 0xbc, 0xb0, 0xac, 0xff, 0xa8, 0x9b, 0x94, 0xff, + 0xbc, 0xb0, 0xac, 0xff, 0xe2, 0xdc, 0xcc, 0xff, 0xf2, 0xe9, 0xdc, 0xff, + 0xf2, 0xe9, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe6, 0xcc, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0x94, 0x79, 0x6c, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x6a, 0x53, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x7c, 0x5d, 0x54, 0xff, 0x7d, 0x62, 0x5c, 0xff, 0x7c, 0x62, 0x54, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x69, 0x4e, 0x4c, 0xff, 0x74, 0x4e, 0x44, 0xff, + 0x69, 0x4e, 0x44, 0xff, 0x6a, 0x53, 0x4c, 0xff, 0x75, 0x56, 0x54, 0xff, + 0x7f, 0x6a, 0x64, 0xff, 0xbc, 0xa4, 0x9c, 0xff, 0xc5, 0xb7, 0xb4, 0xff, + 0xac, 0x8d, 0x8c, 0xff, 0x7f, 0x6a, 0x64, 0xff, 0x7e, 0x6d, 0x6c, 0xff, + 0x7d, 0x62, 0x5c, 0xff, 0x6a, 0x53, 0x4c, 0xff, 0x69, 0x4e, 0x4c, 0xff, + 0x69, 0x55, 0x54, 0xff, 0x6a, 0x53, 0x4c, 0xff, 0x72, 0x5b, 0x54, 0xff, + 0x75, 0x62, 0x64, 0xff, 0x78, 0x66, 0x64, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x69, 0x4e, 0x4c, 0xff, 0x69, 0x4e, 0x44, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x7d, 0x62, 0x5c, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x75, 0x56, 0x54, 0xff, 0x69, 0x4e, 0x4c, 0xff, 0x75, 0x56, 0x54, 0xff, + 0x7f, 0x6a, 0x64, 0xff, 0x6a, 0x53, 0x4c, 0xff, 0x6a, 0x53, 0x4c, 0xff, + 0x7c, 0x5d, 0x54, 0xff, 0x9c, 0x80, 0x7c, 0xff, 0x8e, 0x7a, 0x7c, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0x75, 0x62, 0x64, 0xff, 0x78, 0x66, 0x64, 0xff, + 0xa6, 0x95, 0x94, 0xff, 0x9e, 0x8e, 0x94, 0xff, 0x94, 0x8c, 0x8c, 0xff, + 0x9d, 0x8d, 0x8c, 0xff, 0xad, 0x9a, 0x9c, 0xff, 0x70, 0x5e, 0x5c, 0xff, + 0x75, 0x62, 0x64, 0xff, 0x96, 0x86, 0x8c, 0xff, 0xad, 0x9e, 0x9e, 0xff, + 0xd4, 0xc6, 0xc4, 0xff, 0xc4, 0xba, 0xbc, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0xba, 0xb0, 0xa4, 0xff, 0xd9, 0xd4, 0xcc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0x9c, 0x7e, 0x6c, 0xff, 0x7c, 0x62, 0x54, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x75, 0x56, 0x54, 0xff, + 0x7c, 0x5d, 0x54, 0xff, 0x7c, 0x5d, 0x54, 0xff, 0x75, 0x56, 0x54, 0xff, + 0x69, 0x4e, 0x44, 0xff, 0x6c, 0x4a, 0x44, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x69, 0x4e, 0x44, 0xff, 0x72, 0x62, 0x5c, 0xff, + 0x94, 0x79, 0x6c, 0xff, 0xbc, 0xa4, 0x9c, 0xff, 0xc7, 0xb8, 0xac, 0xff, + 0x70, 0x66, 0x5c, 0xff, 0x7d, 0x62, 0x5c, 0xff, 0x7d, 0x62, 0x5c, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x72, 0x5b, 0x54, 0xff, 0x6a, 0x53, 0x4c, 0xff, + 0x6a, 0x53, 0x4c, 0xff, 0x70, 0x5e, 0x5c, 0xff, 0x7c, 0x72, 0x64, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0x8c, 0x6e, 0x64, 0xff, 0x58, 0x49, 0x4c, 0xff, + 0x69, 0x4e, 0x44, 0xff, 0x74, 0x4e, 0x4c, 0xff, 0x69, 0x4e, 0x44, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x7e, 0x6d, 0x6c, 0xff, 0x7d, 0x62, 0x5c, 0xff, + 0x9c, 0x80, 0x7c, 0xff, 0x7c, 0x5e, 0x5c, 0xff, 0x75, 0x56, 0x54, 0xff, + 0x7f, 0x6a, 0x64, 0xff, 0x75, 0x56, 0x54, 0xff, 0x6a, 0x53, 0x4c, 0xff, + 0x75, 0x62, 0x64, 0xff, 0xac, 0x8d, 0x8c, 0xff, 0x7c, 0x5e, 0x5c, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0x8e, 0x7a, 0x7c, 0xff, 0x8e, 0x7a, 0x7c, 0xff, + 0xa1, 0x99, 0x9c, 0xff, 0x9d, 0x8d, 0x8c, 0xff, 0x9e, 0x8e, 0x94, 0xff, + 0xa6, 0x95, 0x94, 0xff, 0xad, 0x9e, 0x9e, 0xff, 0x6b, 0x56, 0x5c, 0xff, + 0x6b, 0x56, 0x5c, 0xff, 0x7e, 0x6d, 0x6c, 0xff, 0xad, 0x9e, 0x9e, 0xff, + 0xbc, 0xb1, 0xb4, 0xff, 0xc4, 0xba, 0xbc, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0xb4, 0xaa, 0xac, 0xff, 0xba, 0xb0, 0xa4, 0xff, 0xc5, 0xb7, 0xb4, 0xff, + 0xe2, 0xdc, 0xcc, 0xff, 0xfc, 0xf2, 0xe4, 0xff, 0xf2, 0xe9, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf9, 0xe2, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xac, 0x8d, 0x84, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x7c, 0x5d, 0x54, 0xff, 0x72, 0x5b, 0x54, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x7c, 0x5c, 0x4c, 0xff, + 0x7c, 0x5d, 0x54, 0xff, 0x75, 0x56, 0x54, 0xff, 0x74, 0x4e, 0x44, 0xff, + 0x74, 0x4e, 0x44, 0xff, 0x75, 0x56, 0x54, 0xff, 0x74, 0x4e, 0x4c, 0xff, + 0x61, 0x48, 0x44, 0xff, 0x69, 0x4e, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x8a, 0x76, 0x6c, 0xff, 0xc5, 0xb7, 0xb4, 0xff, 0x8a, 0x76, 0x6c, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0x78, 0x66, 0x64, 0xff, 0x7c, 0x5e, 0x5c, 0xff, + 0x6a, 0x53, 0x4c, 0xff, 0x69, 0x55, 0x54, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x78, 0x66, 0x64, 0xff, 0x72, 0x62, 0x5c, 0xff, + 0x7e, 0x6d, 0x6c, 0xff, 0x7d, 0x62, 0x5c, 0xff, 0x6c, 0x4a, 0x44, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x6a, 0x53, 0x4c, 0xff, 0x69, 0x4e, 0x44, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x72, 0x5b, 0x54, 0xff, 0x84, 0x77, 0x74, 0xff, + 0xbd, 0xa6, 0xa4, 0xff, 0x84, 0x77, 0x74, 0xff, 0x7c, 0x5d, 0x54, 0xff, + 0x7e, 0x6d, 0x6c, 0xff, 0x69, 0x4e, 0x4c, 0xff, 0x75, 0x56, 0x54, 0xff, + 0x8d, 0x72, 0x6b, 0xff, 0x96, 0x85, 0x84, 0xff, 0x69, 0x4e, 0x4c, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0x84, 0x77, 0x74, 0xff, 0x96, 0x86, 0x8c, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0x9d, 0x8d, 0x8c, 0xff, 0xad, 0x9a, 0x9c, 0xff, + 0x96, 0x86, 0x8c, 0xff, 0x81, 0x72, 0x74, 0xff, 0x81, 0x72, 0x74, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0x70, 0x5e, 0x5c, 0xff, 0x9e, 0x8b, 0x84, 0xff, + 0xbc, 0xb0, 0xac, 0xff, 0xbc, 0xb1, 0xb4, 0xff, 0xba, 0xb6, 0xb4, 0xff, + 0xcc, 0xbe, 0xc4, 0xff, 0xa1, 0xa2, 0x9c, 0xff, 0xc7, 0xb8, 0xac, 0xff, + 0xd7, 0xcc, 0xc4, 0xff, 0xf2, 0xe9, 0xdc, 0xff, 0xf2, 0xe9, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf2, 0xe9, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf9, 0xe2, 0xd4, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xb4, 0x9a, 0x8c, 0xff, 0x72, 0x5b, 0x54, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x7c, 0x5d, 0x54, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x7c, 0x5d, 0x54, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x69, 0x4e, 0x44, 0xff, + 0x74, 0x4e, 0x44, 0xff, 0x75, 0x56, 0x54, 0xff, 0x7c, 0x5d, 0x54, 0xff, + 0x6a, 0x53, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x69, 0x4e, 0x44, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x9c, 0x80, 0x7c, 0xff, 0x7d, 0x62, 0x5c, 0xff, + 0x7c, 0x5d, 0x54, 0xff, 0x72, 0x5b, 0x54, 0xff, 0x69, 0x4e, 0x4c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x69, 0x4e, 0x4c, 0xff, 0x78, 0x66, 0x64, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x84, 0x77, 0x74, 0xff, 0x7e, 0x6d, 0x6c, 0xff, + 0x7f, 0x6a, 0x64, 0xff, 0x69, 0x55, 0x54, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x69, 0x4e, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x69, 0x4e, 0x44, 0xff, 0x58, 0x49, 0x4c, 0xff, 0x7c, 0x5d, 0x54, 0xff, + 0x7e, 0x6d, 0x6c, 0xff, 0x7f, 0x6a, 0x64, 0xff, 0x9c, 0x80, 0x7c, 0xff, + 0x9c, 0x80, 0x7c, 0xff, 0x74, 0x4e, 0x4c, 0xff, 0x7e, 0x6d, 0x6c, 0xff, + 0x8e, 0x79, 0x74, 0xff, 0x8c, 0x6d, 0x6c, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x7d, 0x62, 0x5c, 0xff, 0x8e, 0x7a, 0x7c, 0xff, 0x9d, 0x8d, 0x8c, 0xff, + 0xad, 0x9a, 0x9c, 0xff, 0x9e, 0x8e, 0x94, 0xff, 0xa4, 0x9e, 0xa4, 0xff, + 0x9e, 0x8e, 0x94, 0xff, 0x9d, 0x8d, 0x8c, 0xff, 0x9e, 0x8e, 0x94, 0xff, + 0x81, 0x72, 0x74, 0xff, 0x6b, 0x56, 0x5c, 0xff, 0x7e, 0x6d, 0x6c, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0x9a, 0x94, 0x94, 0xff, 0xc4, 0xba, 0xbc, 0xff, + 0xd5, 0xcd, 0xcc, 0xff, 0xa1, 0x9e, 0x9c, 0xff, 0xb0, 0xa3, 0x9c, 0xff, + 0xbc, 0xb6, 0xac, 0xff, 0xd9, 0xd4, 0xcc, 0xff, 0xf2, 0xe9, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf2, 0xe9, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xb1, 0xa3, 0x94, 0xff, 0xc9, 0xc0, 0xb4, 0xff, 0xd9, 0xcc, 0xbc, 0xff, + 0x9c, 0x80, 0x7c, 0xff, 0x72, 0x5b, 0x54, 0xff, 0x7c, 0x5d, 0x54, 0xff, + 0x74, 0x5b, 0x4c, 0xff, 0x7c, 0x5d, 0x54, 0xff, 0x7c, 0x5d, 0x54, 0xff, + 0x7c, 0x5d, 0x54, 0xff, 0x75, 0x56, 0x54, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x6c, 0x4a, 0x44, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x7c, 0x5d, 0x54, 0xff, 0x7c, 0x5d, 0x54, 0xff, 0x75, 0x56, 0x54, 0xff, + 0x6a, 0x53, 0x4c, 0xff, 0x61, 0x48, 0x44, 0xff, 0x69, 0x4e, 0x44, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x72, 0x5b, 0x54, 0xff, 0x69, 0x4e, 0x44, 0xff, + 0x69, 0x4e, 0x4c, 0xff, 0x6a, 0x53, 0x4c, 0xff, 0x6a, 0x53, 0x4c, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x69, 0x4e, 0x4c, 0xff, 0x84, 0x77, 0x74, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0x8f, 0x7f, 0x7c, 0xff, 0x7c, 0x72, 0x64, 0xff, + 0x8f, 0x86, 0x7c, 0xff, 0x7c, 0x5d, 0x54, 0xff, 0x69, 0x4e, 0x4c, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x7c, 0x5d, 0x54, 0xff, 0x75, 0x56, 0x54, 0xff, 0x58, 0x49, 0x4c, 0xff, + 0x75, 0x56, 0x54, 0xff, 0x8e, 0x72, 0x74, 0xff, 0x8c, 0x81, 0x84, 0xff, + 0x8e, 0x79, 0x74, 0xff, 0x7e, 0x6d, 0x6c, 0xff, 0x8e, 0x72, 0x74, 0xff, + 0x69, 0x55, 0x54, 0xff, 0x6a, 0x53, 0x4c, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x84, 0x77, 0x74, 0xff, 0x9d, 0x8d, 0x8c, 0xff, 0xad, 0x9a, 0x9c, 0xff, + 0xbc, 0xaa, 0xac, 0xff, 0x9a, 0x94, 0x94, 0xff, 0xad, 0x9a, 0x9c, 0xff, + 0xbd, 0xa6, 0xa4, 0xff, 0xbd, 0xa6, 0xa4, 0xff, 0xad, 0x9a, 0x9c, 0xff, + 0xad, 0x9e, 0x9e, 0xff, 0x8e, 0x72, 0x74, 0xff, 0x7f, 0x72, 0x6c, 0xff, + 0xa1, 0x99, 0x9c, 0xff, 0xa4, 0x9e, 0xa4, 0xff, 0xb4, 0xaa, 0xac, 0xff, + 0xbc, 0xb1, 0xb4, 0xff, 0xc5, 0xb7, 0xb4, 0xff, 0xb0, 0xa3, 0x9c, 0xff, + 0xbc, 0xb0, 0xac, 0xff, 0xbc, 0xb0, 0xac, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf4, 0xea, 0xe4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xf2, 0xe4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf2, 0xe9, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xf2, 0xe9, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0x7c, 0x72, 0x64, 0xff, 0x7f, 0x72, 0x6c, 0xff, 0x64, 0x5a, 0x4c, 0xff, + 0x6a, 0x53, 0x4c, 0xff, 0x72, 0x5b, 0x54, 0xff, 0x72, 0x5b, 0x54, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0x7c, 0x5e, 0x5c, 0xff, 0x75, 0x56, 0x54, 0xff, + 0x75, 0x56, 0x54, 0xff, 0x7c, 0x5d, 0x54, 0xff, 0x7c, 0x5c, 0x4c, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x75, 0x56, 0x54, 0xff, 0x7c, 0x5d, 0x54, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x61, 0x48, 0x44, 0xff, 0x61, 0x48, 0x44, 0xff, 0x6a, 0x53, 0x4c, 0xff, + 0x50, 0x4e, 0x44, 0xff, 0x61, 0x48, 0x44, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x69, 0x4e, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x8c, 0x6d, 0x6c, 0xff, 0x84, 0x77, 0x74, 0xff, 0x7f, 0x6a, 0x64, 0xff, + 0x7f, 0x6a, 0x64, 0xff, 0x6a, 0x53, 0x4c, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x71, 0x6a, 0x64, 0xff, 0x55, 0x52, 0x4c, 0xff, 0x72, 0x5b, 0x54, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x72, 0x5b, 0x54, 0xff, 0x75, 0x56, 0x54, 0xff, + 0x7c, 0x5d, 0x54, 0xff, 0x72, 0x5b, 0x54, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x7f, 0x6a, 0x64, 0xff, 0x81, 0x72, 0x74, 0xff, 0x7d, 0x62, 0x5c, 0xff, + 0x81, 0x72, 0x74, 0xff, 0x9d, 0x8d, 0x8c, 0xff, 0x8e, 0x79, 0x74, 0xff, + 0x69, 0x55, 0x54, 0xff, 0x69, 0x55, 0x54, 0xff, 0x72, 0x5b, 0x54, 0xff, + 0x7e, 0x6d, 0x6c, 0xff, 0x9e, 0x8e, 0x94, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0xad, 0x9a, 0x9c, 0xff, 0xa4, 0x9e, 0xa4, 0xff, 0xc6, 0xb1, 0xb4, 0xff, + 0xa4, 0x9e, 0xa4, 0xff, 0x9e, 0x8e, 0x94, 0xff, 0x96, 0x86, 0x8c, 0xff, + 0x9e, 0x8e, 0x94, 0xff, 0xad, 0x9a, 0x9c, 0xff, 0xa6, 0x95, 0x94, 0xff, + 0x9d, 0x8d, 0x8c, 0xff, 0xa1, 0x99, 0x9c, 0xff, 0x94, 0x8c, 0x8c, 0xff, + 0xc5, 0xb7, 0xb4, 0xff, 0xcc, 0xc5, 0xc4, 0xff, 0xb4, 0xaa, 0xac, 0xff, + 0xbc, 0xb6, 0xac, 0xff, 0xbf, 0xaa, 0xa4, 0xff, 0xc9, 0xc0, 0xb4, 0xff, + 0xfc, 0xf2, 0xe4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf2, 0xe4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf2, 0xe9, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0x94, 0x8b, 0x84, 0xff, 0x90, 0x7f, 0x74, 0xff, 0x71, 0x6a, 0x64, 0xff, + 0x6a, 0x53, 0x4c, 0xff, 0x72, 0x5b, 0x54, 0xff, 0x70, 0x5e, 0x5c, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x7c, 0x5e, 0x5c, 0xff, 0x72, 0x5b, 0x54, 0xff, + 0x7c, 0x5d, 0x54, 0xff, 0x7c, 0x5d, 0x54, 0xff, 0x72, 0x5b, 0x54, 0xff, + 0x7c, 0x5d, 0x54, 0xff, 0x7c, 0x5d, 0x54, 0xff, 0x7c, 0x5d, 0x54, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x69, 0x4e, 0x4c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x50, 0x4e, 0x44, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x69, 0x4e, 0x44, 0xff, + 0x74, 0x4e, 0x4c, 0xff, 0x5c, 0x3e, 0x34, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x7c, 0x5d, 0x54, 0xff, 0x69, 0x4e, 0x4c, 0xff, 0x7f, 0x6a, 0x64, 0xff, + 0x9d, 0x8d, 0x8c, 0xff, 0x50, 0x4e, 0x44, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x6a, 0x53, 0x4c, 0xff, 0x78, 0x66, 0x64, 0xff, 0x80, 0x67, 0x5c, 0xff, + 0x6a, 0x53, 0x4c, 0xff, 0x6a, 0x53, 0x4c, 0xff, 0x7c, 0x5d, 0x54, 0xff, + 0x7f, 0x6a, 0x64, 0xff, 0x70, 0x5e, 0x5c, 0xff, 0x77, 0x66, 0x6c, 0xff, + 0x81, 0x72, 0x74, 0xff, 0x78, 0x66, 0x64, 0xff, 0x77, 0x66, 0x6c, 0xff, + 0x7e, 0x6d, 0x6c, 0xff, 0xad, 0x9a, 0x9c, 0xff, 0xad, 0x9e, 0x9e, 0xff, + 0x84, 0x77, 0x74, 0xff, 0x7d, 0x62, 0x5c, 0xff, 0x78, 0x66, 0x64, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0x8f, 0x7f, 0x7c, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0xad, 0x9a, 0x9c, 0xff, 0xad, 0x9a, 0x9c, 0xff, 0xbc, 0xaa, 0xac, 0xff, + 0x9e, 0x8e, 0x94, 0xff, 0x9c, 0x7a, 0x7c, 0xff, 0x84, 0x79, 0x7c, 0xff, + 0x8e, 0x7a, 0x7c, 0xff, 0x96, 0x85, 0x84, 0xff, 0xa6, 0x95, 0x94, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0x9d, 0x8d, 0x8c, 0xff, 0x8b, 0x8b, 0x8c, 0xff, + 0xb4, 0xaa, 0xac, 0xff, 0xcc, 0xc2, 0xbc, 0xff, 0xba, 0xb6, 0xb4, 0xff, + 0xc5, 0xb7, 0xb4, 0xff, 0xc5, 0xb7, 0xb4, 0xff, 0xb0, 0xa3, 0x9c, 0xff, + 0xd7, 0xcc, 0xc4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xf2, 0xe4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xe8, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0x94, 0x8b, 0x84, 0xff, 0x90, 0x7f, 0x74, 0xff, 0x78, 0x77, 0x74, 0xff, + 0x7f, 0x72, 0x6c, 0xff, 0x6f, 0x6c, 0x6c, 0xff, 0x7f, 0x6a, 0x64, 0xff, + 0x69, 0x55, 0x54, 0xff, 0x72, 0x62, 0x5c, 0xff, 0x70, 0x5e, 0x5c, 0xff, + 0x72, 0x62, 0x5c, 0xff, 0x7c, 0x5d, 0x54, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x75, 0x56, 0x54, 0xff, 0x72, 0x5b, 0x54, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x69, 0x4e, 0x44, 0xff, 0x61, 0x48, 0x44, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x61, 0x48, 0x44, 0xff, 0x69, 0x4e, 0x44, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x5c, 0x42, 0x44, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x69, 0x4e, 0x4c, 0xff, + 0x69, 0x4e, 0x44, 0xff, 0x61, 0x48, 0x44, 0xff, 0x6a, 0x53, 0x4c, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x70, 0x5e, 0x5c, 0xff, + 0x84, 0x77, 0x74, 0xff, 0x7f, 0x6a, 0x64, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x69, 0x4e, 0x44, 0xff, 0x6a, 0x53, 0x4c, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x72, 0x5b, 0x54, 0xff, 0x70, 0x5e, 0x5c, 0xff, + 0x72, 0x62, 0x5c, 0xff, 0x77, 0x66, 0x6c, 0xff, 0x75, 0x62, 0x64, 0xff, + 0x7e, 0x6d, 0x6c, 0xff, 0x96, 0x86, 0x8c, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0x8e, 0x72, 0x74, 0xff, 0x8f, 0x7f, 0x7c, 0xff, 0x9c, 0x80, 0x7c, 0xff, + 0x84, 0x77, 0x74, 0xff, 0x8e, 0x7a, 0x7c, 0xff, 0x8c, 0x81, 0x84, 0xff, + 0xa1, 0x99, 0x9c, 0xff, 0x96, 0x86, 0x8c, 0xff, 0x8e, 0x7a, 0x7c, 0xff, + 0x96, 0x86, 0x8c, 0xff, 0x96, 0x86, 0x8c, 0xff, 0x96, 0x86, 0x8c, 0xff, + 0x96, 0x85, 0x84, 0xff, 0x9d, 0x8d, 0x8c, 0xff, 0xa6, 0x95, 0x94, 0xff, + 0x94, 0x8c, 0x8c, 0xff, 0xa1, 0x99, 0x9c, 0xff, 0xbc, 0xb9, 0xbc, 0xff, + 0xc4, 0xba, 0xbc, 0xff, 0xc2, 0xbe, 0xbc, 0xff, 0xcc, 0xc2, 0xbc, 0xff, + 0xc4, 0xbe, 0xc4, 0xff, 0xc5, 0xb7, 0xb4, 0xff, 0xbc, 0xb0, 0xac, 0xff, + 0xa9, 0x9b, 0x8c, 0xff, 0xf9, 0xe2, 0xd4, 0xff, 0xfc, 0xf2, 0xe4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xea, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0x9c, 0x93, 0x8c, 0xff, 0xa6, 0x95, 0x94, 0xff, 0x94, 0x8b, 0x84, 0xff, + 0x9d, 0x8d, 0x8c, 0xff, 0xd7, 0xcc, 0xc4, 0xff, 0xbc, 0xb1, 0xb4, 0xff, + 0xa1, 0x99, 0x9c, 0xff, 0xad, 0x9a, 0x9c, 0xff, 0x84, 0x77, 0x74, 0xff, + 0x71, 0x6a, 0x64, 0xff, 0x81, 0x72, 0x74, 0xff, 0x72, 0x5b, 0x54, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x69, 0x55, 0x54, 0xff, 0x69, 0x4e, 0x4c, 0xff, + 0x61, 0x48, 0x44, 0xff, 0x61, 0x48, 0x44, 0xff, 0x69, 0x4e, 0x4c, 0xff, + 0x5c, 0x42, 0x44, 0xff, 0x6c, 0x4a, 0x44, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x5c, 0x42, 0x44, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x6c, 0x4a, 0x44, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x69, 0x4e, 0x4c, 0xff, + 0x6c, 0x4a, 0x44, 0xff, 0x61, 0x48, 0x44, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x61, 0x48, 0x44, 0xff, 0x6a, 0x53, 0x4c, 0xff, 0x72, 0x62, 0x5c, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x70, 0x66, 0x5c, 0xff, 0x7f, 0x6a, 0x64, 0xff, + 0x7c, 0x5d, 0x54, 0xff, 0x6a, 0x53, 0x4c, 0xff, 0x6a, 0x53, 0x4c, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x69, 0x55, 0x54, 0xff, 0x69, 0x4e, 0x4c, 0xff, + 0x69, 0x4e, 0x4c, 0xff, 0x70, 0x5e, 0x5c, 0xff, 0x75, 0x62, 0x64, 0xff, + 0x8e, 0x79, 0x74, 0xff, 0xbc, 0xb1, 0xb4, 0xff, 0x96, 0x85, 0x84, 0xff, + 0x7f, 0x72, 0x6c, 0xff, 0x8f, 0x7f, 0x7c, 0xff, 0xa6, 0x95, 0x94, 0xff, + 0xb0, 0xa3, 0x9c, 0xff, 0xa6, 0x95, 0x94, 0xff, 0x96, 0x85, 0x84, 0xff, + 0x8f, 0x7f, 0x7c, 0xff, 0x78, 0x77, 0x74, 0xff, 0x8c, 0x81, 0x84, 0xff, + 0x81, 0x72, 0x74, 0xff, 0x9d, 0x8d, 0x8c, 0xff, 0x9d, 0x8d, 0x8c, 0xff, + 0x8c, 0x81, 0x84, 0xff, 0x8c, 0x81, 0x84, 0xff, 0xa6, 0x95, 0x94, 0xff, + 0xad, 0x9a, 0x9c, 0xff, 0xa1, 0x99, 0x9c, 0xff, 0xbc, 0xaa, 0xac, 0xff, + 0xc4, 0xba, 0xbc, 0xff, 0xc2, 0xbe, 0xbc, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0xc4, 0xba, 0xbc, 0xff, 0xc4, 0xba, 0xbc, 0xff, 0xba, 0xb6, 0xb4, 0xff, + 0xa8, 0x9b, 0x94, 0xff, 0xb0, 0xaa, 0x9c, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf2, 0xe4, 0xff, 0xfc, 0xea, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf2, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0x92, 0x92, 0x8c, 0xff, 0x8b, 0x8b, 0x8c, 0xff, 0xa1, 0x9e, 0x9c, 0xff, + 0xa3, 0xa3, 0xa4, 0xff, 0xbc, 0xb1, 0xb4, 0xff, 0xdc, 0xdc, 0xdc, 0xff, + 0xc8, 0xca, 0xc4, 0xff, 0xb3, 0xae, 0xac, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0xc5, 0xb7, 0xb4, 0xff, 0xb1, 0xaa, 0xa4, 0xff, 0x70, 0x5e, 0x5c, 0xff, + 0x75, 0x62, 0x64, 0xff, 0x78, 0x66, 0x64, 0xff, 0x69, 0x4e, 0x4c, 0xff, + 0x69, 0x4e, 0x4c, 0xff, 0x69, 0x4e, 0x4c, 0xff, 0x74, 0x4e, 0x4c, 0xff, + 0x6c, 0x4a, 0x44, 0xff, 0x6c, 0x4a, 0x44, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x6c, 0x4a, 0x44, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x6c, 0x4a, 0x44, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x69, 0x4e, 0x44, 0xff, + 0x61, 0x48, 0x44, 0xff, 0x61, 0x48, 0x44, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x69, 0x4e, 0x44, 0xff, 0x50, 0x4e, 0x44, 0xff, + 0x61, 0x48, 0x44, 0xff, 0x69, 0x4e, 0x44, 0xff, 0x7f, 0x6a, 0x64, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x6a, 0x53, 0x4c, 0xff, 0x69, 0x4e, 0x44, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x74, 0x4e, 0x4c, 0xff, 0x69, 0x4e, 0x4c, 0xff, + 0x75, 0x56, 0x54, 0xff, 0x7c, 0x5e, 0x5c, 0xff, 0x70, 0x5e, 0x5c, 0xff, + 0x7f, 0x72, 0x6c, 0xff, 0x96, 0x85, 0x84, 0xff, 0x8e, 0x7a, 0x7c, 0xff, + 0x96, 0x85, 0x84, 0xff, 0x8f, 0x7f, 0x7c, 0xff, 0x84, 0x77, 0x74, 0xff, + 0x94, 0x8b, 0x84, 0xff, 0xae, 0xa4, 0xa4, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0x81, 0x72, 0x74, 0xff, 0x84, 0x77, 0x74, 0xff, 0x9c, 0x80, 0x7c, 0xff, + 0x8c, 0x81, 0x84, 0xff, 0x81, 0x72, 0x74, 0xff, 0x9e, 0x8e, 0x94, 0xff, + 0x9d, 0x8d, 0x8c, 0xff, 0x8f, 0x7f, 0x7c, 0xff, 0x94, 0x8c, 0x8c, 0xff, + 0xad, 0x9e, 0x9e, 0xff, 0xa1, 0x99, 0x9c, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0xd6, 0xd2, 0xd4, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0xb4, 0xaa, 0xac, 0xff, 0xbc, 0xb1, 0xb4, 0xff, 0xbc, 0xb0, 0xac, 0xff, + 0xc5, 0xb7, 0xb4, 0xff, 0x94, 0x8b, 0x84, 0xff, 0xe4, 0xde, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf2, 0xe4, 0xff, 0xfc, 0xf2, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xae, 0xa4, 0xa4, 0xff, 0x94, 0x8c, 0x8c, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0x9c, 0x9a, 0x94, 0xff, 0xe4, 0xde, 0xdc, 0xff, + 0xd5, 0xcd, 0xcc, 0xff, 0xcc, 0xc5, 0xc4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0xba, 0xb6, 0xb4, 0xff, 0xc4, 0xba, 0xbc, 0xff, 0x8e, 0x7a, 0x7c, 0xff, + 0x75, 0x62, 0x64, 0xff, 0x8c, 0x6e, 0x64, 0xff, 0x75, 0x56, 0x54, 0xff, + 0x74, 0x4e, 0x4c, 0xff, 0x69, 0x4e, 0x4c, 0xff, 0x69, 0x4e, 0x4c, 0xff, + 0x6c, 0x4a, 0x44, 0xff, 0x5c, 0x42, 0x44, 0xff, 0x5c, 0x42, 0x44, 0xff, + 0x5c, 0x42, 0x44, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x6c, 0x4a, 0x44, 0xff, 0x6c, 0x4a, 0x44, 0xff, + 0x61, 0x48, 0x44, 0xff, 0x6c, 0x4a, 0x44, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x61, 0x48, 0x44, 0xff, 0x69, 0x4e, 0x44, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x69, 0x4e, 0x44, 0xff, 0x70, 0x66, 0x5c, 0xff, + 0x6a, 0x53, 0x4c, 0xff, 0x50, 0x4e, 0x44, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x6a, 0x53, 0x4c, 0xff, + 0x69, 0x4e, 0x4c, 0xff, 0x70, 0x5e, 0x5c, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x75, 0x62, 0x64, 0xff, 0x7e, 0x6d, 0x6c, 0xff, 0x8e, 0x7a, 0x7c, 0xff, + 0x8e, 0x7a, 0x7c, 0xff, 0x7e, 0x6d, 0x6c, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0x96, 0x85, 0x84, 0xff, 0x9d, 0x8d, 0x8c, 0xff, + 0x94, 0x8b, 0x84, 0xff, 0x9d, 0x8d, 0x8c, 0xff, 0x96, 0x86, 0x8c, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x75, 0x62, 0x64, 0xff, 0x8e, 0x79, 0x74, 0xff, + 0x94, 0x8c, 0x8c, 0xff, 0x9d, 0x8d, 0x8c, 0xff, 0x9d, 0x8d, 0x8c, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0xad, 0x9a, 0x9c, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0xad, 0x9e, 0x9e, 0xff, 0xbc, 0xb1, 0xb4, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0xae, 0xa4, 0xa4, 0xff, 0x94, 0x8e, 0x94, 0xff, + 0xc5, 0xb7, 0xb4, 0xff, 0xa8, 0x9b, 0x94, 0xff, 0xc7, 0xb8, 0xac, 0xff, + 0xf4, 0xea, 0xe4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf2, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf2, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xe8, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xba, 0xb6, 0xb4, 0xff, 0xb1, 0xaa, 0xa4, 0xff, + 0x9c, 0x93, 0x8c, 0xff, 0x8b, 0x8b, 0x8c, 0xff, 0xbc, 0xb9, 0xbc, 0xff, + 0xe4, 0xde, 0xdc, 0xff, 0xdc, 0xdc, 0xdc, 0xff, 0xba, 0xb6, 0xb4, 0xff, + 0xbc, 0xb1, 0xb4, 0xff, 0xcc, 0xc5, 0xc4, 0xff, 0xbd, 0xa6, 0xa4, 0xff, + 0x9c, 0x7a, 0x7c, 0xff, 0x75, 0x62, 0x64, 0xff, 0x7c, 0x5e, 0x5c, 0xff, + 0x74, 0x4e, 0x4c, 0xff, 0x61, 0x48, 0x44, 0xff, 0x5c, 0x42, 0x44, 0xff, + 0x5c, 0x42, 0x44, 0xff, 0x5c, 0x42, 0x44, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x5c, 0x42, 0x44, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x6c, 0x4a, 0x44, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x61, 0x48, 0x44, 0xff, 0x69, 0x4e, 0x44, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x6a, 0x53, 0x4c, 0xff, 0x72, 0x62, 0x5c, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x6a, 0x53, 0x4c, 0xff, 0x72, 0x62, 0x5c, 0xff, + 0x6a, 0x53, 0x4c, 0xff, 0x69, 0x4e, 0x4c, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0x6a, 0x53, 0x4c, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0x8e, 0x72, 0x74, 0xff, 0x84, 0x77, 0x74, 0xff, + 0x9c, 0x80, 0x7c, 0xff, 0x7e, 0x6d, 0x6c, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x71, 0x6a, 0x64, 0xff, 0x84, 0x79, 0x7c, 0xff, 0x94, 0x8b, 0x84, 0xff, + 0x96, 0x85, 0x84, 0xff, 0xa6, 0x95, 0x94, 0xff, 0x9c, 0x93, 0x8c, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0x84, 0x77, 0x74, 0xff, 0x8c, 0x81, 0x84, 0xff, + 0x96, 0x86, 0x8c, 0xff, 0x96, 0x85, 0x84, 0xff, 0x9e, 0x8e, 0x94, 0xff, + 0xa6, 0x95, 0x94, 0xff, 0x9a, 0x94, 0x94, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0xad, 0x9e, 0x9e, 0xff, 0xb4, 0xb2, 0xb4, 0xff, 0x96, 0x85, 0x84, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0xa4, 0x9e, 0xa4, 0xff, 0xa1, 0xa2, 0x9c, 0xff, + 0xc5, 0xb7, 0xb4, 0xff, 0xbc, 0xb0, 0xac, 0xff, 0x9c, 0x93, 0x8c, 0xff, + 0xef, 0xe2, 0xdc, 0xff, 0xfc, 0xf2, 0xe4, 0xff, 0xfc, 0xf2, 0xe4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf2, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf2, 0xe4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xe8, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xac, 0xa9, 0xac, 0xff, 0xc2, 0xc2, 0xbc, 0xff, 0x94, 0x8e, 0x94, 0xff, + 0x8b, 0x8b, 0x8c, 0xff, 0x71, 0x72, 0x6c, 0xff, 0x81, 0x7e, 0x7c, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xe4, 0xe2, 0xd8, 0xff, 0xdc, 0xd6, 0xdc, 0xff, + 0xd6, 0xd2, 0xd4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xcc, 0xbe, 0xc4, 0xff, + 0xc6, 0xb1, 0xb4, 0xff, 0xb4, 0x96, 0x94, 0xff, 0x75, 0x62, 0x64, 0xff, + 0x64, 0x4e, 0x54, 0xff, 0x6c, 0x4a, 0x44, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x69, 0x4e, 0x4c, 0xff, 0x6c, 0x4a, 0x44, 0xff, 0x5c, 0x42, 0x44, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x6c, 0x4a, 0x44, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x6c, 0x4a, 0x44, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x69, 0x4e, 0x4c, 0xff, 0x69, 0x4e, 0x44, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x72, 0x5b, 0x54, 0xff, + 0x6a, 0x53, 0x4c, 0xff, 0x6a, 0x53, 0x4c, 0xff, 0x7d, 0x62, 0x5c, 0xff, + 0x69, 0x4e, 0x4c, 0xff, 0x78, 0x66, 0x64, 0xff, 0x70, 0x5e, 0x5c, 0xff, + 0x7e, 0x6d, 0x6c, 0xff, 0x6f, 0x6c, 0x6c, 0xff, 0x8c, 0x81, 0x84, 0xff, + 0x8e, 0x7a, 0x7c, 0xff, 0x72, 0x5b, 0x54, 0xff, 0x5d, 0x5a, 0x54, 0xff, + 0x84, 0x77, 0x74, 0xff, 0x7f, 0x72, 0x6c, 0xff, 0x8f, 0x7f, 0x7c, 0xff, + 0xa6, 0x95, 0x94, 0xff, 0xae, 0xa4, 0xa4, 0xff, 0xa6, 0x95, 0x94, 0xff, + 0x84, 0x79, 0x7c, 0xff, 0x8f, 0x7f, 0x7c, 0xff, 0x94, 0x8c, 0x8c, 0xff, + 0x96, 0x85, 0x84, 0xff, 0x9a, 0x94, 0x94, 0xff, 0xb0, 0xa3, 0x9c, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0xa1, 0x99, 0x9c, 0xff, 0x9a, 0x94, 0x94, 0xff, + 0xa1, 0x99, 0x9c, 0xff, 0xcc, 0xc5, 0xc4, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0xa1, 0x99, 0x9c, 0xff, 0xb4, 0xaa, 0xac, 0xff, 0xbc, 0xb0, 0xac, 0xff, + 0xec, 0xde, 0xdc, 0xff, 0xc2, 0xbe, 0xbc, 0xff, 0xa6, 0x95, 0x94, 0xff, + 0xd6, 0xc5, 0xbc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xf2, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf2, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0x81, 0x7e, 0x7c, 0xff, 0xbc, 0xb6, 0xac, 0xff, 0x8b, 0x8b, 0x8c, 0xff, + 0x81, 0x7e, 0x7c, 0xff, 0x63, 0x66, 0x64, 0xff, 0x92, 0x92, 0x8c, 0xff, + 0xb3, 0xae, 0xac, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xbc, 0xb9, 0xbc, 0xff, + 0xd5, 0xcd, 0xcc, 0xff, 0xdc, 0xdc, 0xdc, 0xff, 0xd6, 0xd2, 0xd4, 0xff, + 0xbc, 0xaa, 0xac, 0xff, 0xbc, 0xaa, 0xac, 0xff, 0x8e, 0x7a, 0x7c, 0xff, + 0x69, 0x55, 0x54, 0xff, 0x69, 0x55, 0x54, 0xff, 0x6a, 0x53, 0x4c, 0xff, + 0x69, 0x4e, 0x4c, 0xff, 0x69, 0x4e, 0x4c, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x6c, 0x4a, 0x44, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x6c, 0x4a, 0x44, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x61, 0x48, 0x44, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x69, 0x4e, 0x44, 0xff, 0x50, 0x4e, 0x44, 0xff, 0x6a, 0x53, 0x4c, 0xff, + 0x7c, 0x5d, 0x54, 0xff, 0x5d, 0x5a, 0x54, 0xff, 0x72, 0x5b, 0x54, 0xff, + 0x7c, 0x5d, 0x54, 0xff, 0x72, 0x5b, 0x54, 0xff, 0x7f, 0x6a, 0x64, 0xff, + 0x69, 0x55, 0x54, 0xff, 0x72, 0x5b, 0x54, 0xff, 0x78, 0x66, 0x64, 0xff, + 0x6f, 0x6c, 0x6c, 0xff, 0x8e, 0x7a, 0x7c, 0xff, 0x9d, 0x8d, 0x8c, 0xff, + 0x8e, 0x7a, 0x7c, 0xff, 0x70, 0x5e, 0x5c, 0xff, 0x7e, 0x6d, 0x6c, 0xff, + 0x8e, 0x7a, 0x7c, 0xff, 0x94, 0x8c, 0x8c, 0xff, 0xa6, 0x95, 0x94, 0xff, + 0x84, 0x79, 0x7c, 0xff, 0x8f, 0x7f, 0x7c, 0xff, 0xa6, 0x95, 0x94, 0xff, + 0x9d, 0x8d, 0x8c, 0xff, 0x8c, 0x81, 0x84, 0xff, 0x9a, 0x94, 0x94, 0xff, + 0xa6, 0x95, 0x94, 0xff, 0x94, 0x8b, 0x84, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0xa6, 0x95, 0x94, 0xff, 0xad, 0x9a, 0x9c, 0xff, 0xa4, 0x9e, 0xa4, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0xad, 0x9e, 0x9e, 0xff, 0xb4, 0xb2, 0xb4, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0xb4, 0xaa, 0xac, 0xff, 0xb4, 0xaa, 0xac, 0xff, + 0xbc, 0xb1, 0xb4, 0xff, 0xbc, 0xb1, 0xb4, 0xff, 0xb3, 0xae, 0xac, 0xff, + 0x9c, 0x93, 0x8c, 0xff, 0xf2, 0xe9, 0xdc, 0xff, 0xf2, 0xe9, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf2, 0xe4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf2, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf2, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xa3, 0xa3, 0xa4, 0xff, 0x9a, 0x94, 0x94, 0xff, 0x89, 0x86, 0x84, 0xff, + 0x81, 0x7e, 0x7c, 0xff, 0x63, 0x66, 0x64, 0xff, 0x89, 0x86, 0x84, 0xff, + 0xa1, 0x99, 0x9c, 0xff, 0xa1, 0x99, 0x9c, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xdc, 0xd6, 0xdc, 0xff, 0xd6, 0xd2, 0xd4, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xbc, 0xb0, 0xac, 0xff, + 0x71, 0x6a, 0x64, 0xff, 0x5d, 0x5a, 0x54, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x69, 0x55, 0x54, 0xff, 0x6a, 0x53, 0x4c, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x5c, 0x42, 0x44, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x69, 0x4e, 0x44, 0xff, 0x61, 0x48, 0x44, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x69, 0x4e, 0x44, 0xff, 0x6a, 0x53, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x7f, 0x6a, 0x64, 0xff, 0x9c, 0x80, 0x7c, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x71, 0x6a, 0x64, 0xff, 0x84, 0x77, 0x74, 0xff, + 0x8e, 0x79, 0x74, 0xff, 0xae, 0xa4, 0xa4, 0xff, 0x7e, 0x6d, 0x6c, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x8e, 0x7a, 0x7c, 0xff, 0x84, 0x77, 0x74, 0xff, + 0x84, 0x77, 0x74, 0xff, 0x8f, 0x86, 0x7c, 0xff, 0xa6, 0x95, 0x94, 0xff, + 0x71, 0x6a, 0x64, 0xff, 0x78, 0x66, 0x64, 0xff, 0x9d, 0x8d, 0x8c, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0x84, 0x77, 0x74, 0xff, 0x96, 0x85, 0x84, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0xcc, 0xbe, 0xc4, 0xff, 0xa6, 0x95, 0x94, 0xff, + 0xad, 0x9a, 0x9c, 0xff, 0xa1, 0x99, 0x9c, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0xbc, 0xb0, 0xac, 0xff, 0xc4, 0xbe, 0xc4, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0xbc, 0xb1, 0xb4, 0xff, 0xb4, 0xaa, 0xac, 0xff, 0xb3, 0xae, 0xac, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0xd5, 0xcd, 0xcc, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0xb0, 0xa3, 0x9c, 0xff, 0xbc, 0xb6, 0xac, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xee, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xee, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xbc, 0xb0, 0xac, 0xff, 0xb4, 0xb2, 0xb4, 0xff, 0xa3, 0xa3, 0xa4, 0xff, + 0x94, 0x8c, 0x8c, 0xff, 0x81, 0x7e, 0x7c, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x71, 0x72, 0x6c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0xb3, 0xae, 0xac, 0xff, + 0xd6, 0xd2, 0xd4, 0xff, 0x9a, 0x94, 0x94, 0xff, 0xa3, 0xa3, 0xa4, 0xff, + 0x94, 0x8e, 0x94, 0xff, 0x94, 0x8c, 0x8c, 0xff, 0x9a, 0x94, 0x94, 0xff, + 0x94, 0x8c, 0x8c, 0xff, 0x75, 0x62, 0x64, 0xff, 0x5d, 0x5a, 0x54, 0xff, + 0x5d, 0x5a, 0x54, 0xff, 0x6a, 0x53, 0x4c, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x44, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x69, 0x4e, 0x44, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x53, 0x41, 0x3c, 0xff, 0x6a, 0x53, 0x4c, 0xff, + 0x69, 0x4e, 0x44, 0xff, 0x61, 0x48, 0x44, 0xff, 0x53, 0x41, 0x3c, 0xff, + 0x61, 0x48, 0x44, 0xff, 0x72, 0x5b, 0x54, 0xff, 0x78, 0x66, 0x64, 0xff, + 0x72, 0x62, 0x5c, 0xff, 0x7f, 0x6a, 0x64, 0xff, 0x8f, 0x7f, 0x7c, 0xff, + 0x9c, 0x80, 0x7c, 0xff, 0xad, 0x9a, 0x9c, 0xff, 0x7e, 0x6d, 0x6c, 0xff, + 0x84, 0x79, 0x7c, 0xff, 0x72, 0x62, 0x5c, 0xff, 0x7e, 0x6d, 0x6c, 0xff, + 0x8f, 0x7f, 0x7c, 0xff, 0x6f, 0x6c, 0x6c, 0xff, 0x8f, 0x7f, 0x7c, 0xff, + 0x7f, 0x72, 0x6c, 0xff, 0x84, 0x79, 0x7c, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0x9d, 0x8d, 0x8c, 0xff, 0x9c, 0x93, 0x8c, 0xff, 0x96, 0x86, 0x8c, 0xff, + 0x81, 0x7e, 0x7c, 0xff, 0xa6, 0x95, 0x94, 0xff, 0xb4, 0xaa, 0xac, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0xad, 0x9e, 0x9e, 0xff, 0xa4, 0x9e, 0xa4, 0xff, + 0xa6, 0x95, 0x94, 0xff, 0xae, 0xa4, 0xa4, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0xb1, 0xaa, 0xa4, 0xff, 0xa4, 0x9e, 0xa4, 0xff, 0xba, 0xb6, 0xb4, 0xff, + 0xa4, 0x9e, 0xa4, 0xff, 0xd6, 0xd2, 0xd4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0xbc, 0xb0, 0xac, 0xff, 0xba, 0xb0, 0xa4, 0xff, 0xf2, 0xe9, 0xdc, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xfc, 0xf2, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf2, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xee, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xba, 0xb6, 0xb4, 0xff, 0xac, 0xa9, 0xac, 0xff, 0xa1, 0x9e, 0x9c, 0xff, + 0xa1, 0x99, 0x9c, 0xff, 0x81, 0x7e, 0x7c, 0xff, 0x7b, 0x7a, 0x7c, 0xff, + 0x8b, 0x8b, 0x8c, 0xff, 0x71, 0x72, 0x74, 0xff, 0x71, 0x72, 0x74, 0xff, + 0xac, 0xa9, 0xac, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0x94, 0x8c, 0x8c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x69, 0x55, 0x54, 0xff, 0x6f, 0x6c, 0x6c, 0xff, + 0x84, 0x79, 0x7c, 0xff, 0x7e, 0x6d, 0x6c, 0xff, 0x5d, 0x5a, 0x54, 0xff, + 0x69, 0x55, 0x54, 0xff, 0x69, 0x55, 0x54, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x58, 0x49, 0x4c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x6c, 0x4a, 0x44, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x61, 0x48, 0x44, 0xff, 0x6a, 0x53, 0x4c, 0xff, 0x6a, 0x53, 0x4c, 0xff, + 0x6c, 0x61, 0x64, 0xff, 0x84, 0x77, 0x74, 0xff, 0x94, 0x8b, 0x84, 0xff, + 0x8c, 0x81, 0x84, 0xff, 0x84, 0x77, 0x74, 0xff, 0x81, 0x72, 0x74, 0xff, + 0x84, 0x77, 0x74, 0xff, 0x7e, 0x6d, 0x6c, 0xff, 0x81, 0x72, 0x74, 0xff, + 0x8f, 0x7f, 0x7c, 0xff, 0x84, 0x79, 0x7c, 0xff, 0xa6, 0x95, 0x94, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0xa6, 0x95, 0x94, 0xff, 0xbc, 0xb1, 0xb4, 0xff, + 0xac, 0xa9, 0xac, 0xff, 0xa1, 0x99, 0x9c, 0xff, 0x9a, 0x94, 0x94, 0xff, + 0x8c, 0x81, 0x84, 0xff, 0x9a, 0x94, 0x94, 0xff, 0x9d, 0x8d, 0x8c, 0xff, + 0xa4, 0x9e, 0xa4, 0xff, 0xb0, 0xa3, 0x9c, 0xff, 0x9a, 0x94, 0x94, 0xff, + 0x94, 0x8c, 0x8c, 0xff, 0xa3, 0xa3, 0xa4, 0xff, 0xd6, 0xd2, 0xd4, 0xff, + 0xb4, 0xaa, 0xac, 0xff, 0xae, 0xa4, 0xa4, 0xff, 0xb4, 0xb2, 0xb4, 0xff, + 0xbc, 0xb1, 0xb4, 0xff, 0xb4, 0xaa, 0xac, 0xff, 0xba, 0xb6, 0xb4, 0xff, + 0xba, 0xb6, 0xb4, 0xff, 0xbc, 0xb6, 0xac, 0xff, 0xc5, 0xb7, 0xb4, 0xff, + 0xe4, 0xe2, 0xd8, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xf2, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0x71, 0x72, 0x74, 0xff, 0xa3, 0xa3, 0xa4, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0xa1, 0x99, 0x9c, 0xff, 0x7b, 0x7a, 0x7c, 0xff, 0x94, 0x8e, 0x94, 0xff, + 0x8c, 0x81, 0x84, 0xff, 0x7b, 0x7a, 0x7c, 0xff, 0x81, 0x7e, 0x7c, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0xc4, 0xba, 0xbc, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0x6c, 0x61, 0x64, 0xff, 0x70, 0x5e, 0x5c, 0xff, 0x6c, 0x61, 0x64, 0xff, + 0x75, 0x62, 0x64, 0xff, 0x81, 0x72, 0x74, 0xff, 0x70, 0x5e, 0x5c, 0xff, + 0x55, 0x52, 0x4c, 0xff, 0x64, 0x5d, 0x5c, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x6c, 0x4a, 0x44, 0xff, 0x6c, 0x4a, 0x44, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x5c, 0x42, 0x44, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x69, 0x4e, 0x44, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x61, 0x48, 0x44, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x69, 0x4e, 0x44, 0xff, 0x72, 0x5b, 0x54, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x72, 0x62, 0x5c, 0xff, 0x8f, 0x86, 0x7c, 0xff, 0x8c, 0x81, 0x84, 0xff, + 0x84, 0x77, 0x74, 0xff, 0x84, 0x79, 0x7c, 0xff, 0x77, 0x66, 0x6c, 0xff, + 0x81, 0x72, 0x74, 0xff, 0x75, 0x62, 0x64, 0xff, 0x8f, 0x7f, 0x7c, 0xff, + 0x96, 0x86, 0x8c, 0xff, 0x8f, 0x7f, 0x7c, 0xff, 0x8f, 0x7f, 0x7c, 0xff, + 0xa1, 0x99, 0x9c, 0xff, 0x9a, 0x94, 0x94, 0xff, 0xb3, 0xae, 0xac, 0xff, + 0xac, 0xa9, 0xac, 0xff, 0xb4, 0xaa, 0xac, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0xb4, 0xaa, 0xac, 0xff, 0x9e, 0x8e, 0x94, 0xff, + 0xa6, 0x95, 0x94, 0xff, 0xae, 0xa4, 0xa4, 0xff, 0x9a, 0x94, 0x94, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0xa4, 0x9e, 0xa4, 0xff, 0xbc, 0xb1, 0xb4, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xd6, 0xd2, 0xd4, 0xff, 0xbc, 0xb9, 0xbc, 0xff, + 0xb3, 0xae, 0xac, 0xff, 0xb1, 0xaa, 0xa4, 0xff, 0xbc, 0xb9, 0xbc, 0xff, + 0xc2, 0xc2, 0xbc, 0xff, 0xb1, 0xaa, 0xa4, 0xff, 0xd6, 0xc5, 0xbc, 0xff, + 0xb0, 0xa3, 0x9c, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xfc, 0xf2, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0x84, 0x79, 0x7c, 0xff, 0x78, 0x77, 0x74, 0xff, 0x71, 0x72, 0x74, 0xff, + 0x78, 0x77, 0x74, 0xff, 0x83, 0x82, 0x84, 0xff, 0xb3, 0xae, 0xac, 0xff, + 0xa4, 0x9e, 0xa4, 0xff, 0x94, 0x8c, 0x8c, 0xff, 0x94, 0x8c, 0x8c, 0xff, + 0x8c, 0x86, 0x8c, 0xff, 0x96, 0x85, 0x84, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0x8c, 0x81, 0x84, 0xff, 0x96, 0x86, 0x8c, 0xff, 0x6c, 0x61, 0x64, 0xff, + 0x69, 0x55, 0x54, 0xff, 0x64, 0x5d, 0x5c, 0xff, 0x70, 0x5e, 0x5c, 0xff, + 0x64, 0x5d, 0x5c, 0xff, 0x70, 0x5e, 0x5c, 0xff, 0x6a, 0x53, 0x4c, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x69, 0x4e, 0x4c, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x6c, 0x4a, 0x44, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x6c, 0x4a, 0x44, 0xff, + 0x61, 0x48, 0x44, 0xff, 0x7d, 0x62, 0x5c, 0xff, 0x6a, 0x53, 0x4c, 0xff, + 0x78, 0x66, 0x64, 0xff, 0x96, 0x85, 0x84, 0xff, 0x7c, 0x72, 0x64, 0xff, + 0x6b, 0x56, 0x5c, 0xff, 0x8e, 0x7a, 0x7c, 0xff, 0x70, 0x5e, 0x5c, 0xff, + 0x69, 0x55, 0x54, 0xff, 0x6c, 0x61, 0x64, 0xff, 0x81, 0x72, 0x74, 0xff, + 0x8f, 0x7f, 0x7c, 0xff, 0x84, 0x79, 0x7c, 0xff, 0x81, 0x72, 0x74, 0xff, + 0x9d, 0x8d, 0x8c, 0xff, 0x94, 0x8c, 0x8c, 0xff, 0xb4, 0xaa, 0xac, 0xff, + 0xac, 0xa9, 0xac, 0xff, 0xb3, 0xae, 0xac, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xb4, 0xaa, 0xac, 0xff, + 0x9e, 0x8e, 0x94, 0xff, 0xb4, 0xaa, 0xac, 0xff, 0x9e, 0x8e, 0x94, 0xff, + 0xa1, 0x9e, 0x9c, 0xff, 0xae, 0xa4, 0xa4, 0xff, 0xa1, 0x9e, 0x9c, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xf8, 0xea, 0xec, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xcc, 0xc5, 0xc4, 0xff, 0xb4, 0xb2, 0xb4, 0xff, 0xcc, 0xc5, 0xc4, 0xff, + 0xc2, 0xbe, 0xbc, 0xff, 0xbc, 0xb1, 0xb4, 0xff, 0xc2, 0xc2, 0xbc, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0xd7, 0xcc, 0xc4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf2, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xc2, 0xbe, 0xbc, 0xff, 0x94, 0x8c, 0x8c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x6c, 0x61, 0x64, 0xff, 0x8c, 0x81, 0x84, 0xff, 0xb4, 0xb2, 0xb4, 0xff, + 0xba, 0xb6, 0xb4, 0xff, 0x9a, 0x94, 0x94, 0xff, 0x9a, 0x94, 0x94, 0xff, + 0x8b, 0x8b, 0x8c, 0xff, 0x8c, 0x81, 0x84, 0xff, 0x64, 0x5d, 0x5c, 0xff, + 0x8c, 0x81, 0x84, 0xff, 0xcc, 0xbd, 0xbc, 0xff, 0x9e, 0x8e, 0x94, 0xff, + 0x6c, 0x61, 0x64, 0xff, 0x70, 0x5e, 0x5c, 0xff, 0x5d, 0x5a, 0x54, 0xff, + 0x6f, 0x6c, 0x6c, 0xff, 0x6c, 0x61, 0x64, 0xff, 0x6a, 0x53, 0x4c, 0xff, + 0x69, 0x4e, 0x4c, 0xff, 0x69, 0x4e, 0x4c, 0xff, 0x6c, 0x4a, 0x44, 0xff, + 0x6c, 0x4a, 0x44, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x69, 0x4e, 0x44, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x6c, 0x4a, 0x44, 0xff, 0x58, 0x49, 0x4c, 0xff, 0x7c, 0x5d, 0x54, 0xff, + 0x78, 0x66, 0x64, 0xff, 0x71, 0x6a, 0x64, 0xff, 0x70, 0x5e, 0x5c, 0xff, + 0x71, 0x6a, 0x64, 0xff, 0x8f, 0x7f, 0x7c, 0xff, 0x6c, 0x61, 0x64, 0xff, + 0x6b, 0x56, 0x5c, 0xff, 0x81, 0x72, 0x74, 0xff, 0x84, 0x77, 0x74, 0xff, + 0x8e, 0x7a, 0x7c, 0xff, 0x8c, 0x81, 0x84, 0xff, 0x84, 0x79, 0x7c, 0xff, + 0x94, 0x8c, 0x8c, 0xff, 0x9a, 0x94, 0x94, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0xac, 0xa9, 0xac, 0xff, 0xbc, 0xb1, 0xb4, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0xb4, 0xaa, 0xac, 0xff, 0xad, 0x9a, 0x9c, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0xba, 0xb6, 0xb4, 0xff, 0x94, 0x8c, 0x8c, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0xb4, 0xaa, 0xac, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0xac, 0xa9, 0xac, 0xff, 0xcc, 0xc5, 0xc4, 0xff, 0xc4, 0xbe, 0xc4, 0xff, + 0xc2, 0xbe, 0xbc, 0xff, 0xc2, 0xbe, 0xbc, 0xff, 0xbc, 0xb9, 0xbc, 0xff, + 0xc8, 0xca, 0xc4, 0xff, 0xbc, 0xb9, 0xbc, 0xff, 0xcc, 0xc2, 0xbc, 0xff, + 0xcc, 0xc2, 0xbc, 0xff, 0x9c, 0x93, 0x8c, 0xff, 0xee, 0xdd, 0xd4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xac, 0xa9, 0xac, 0xff, 0xb4, 0xb2, 0xb4, 0xff, 0x6c, 0x61, 0x64, 0xff, + 0x81, 0x7e, 0x7c, 0xff, 0xa4, 0x9e, 0xa4, 0xff, 0x9a, 0x94, 0x94, 0xff, + 0xb4, 0xaa, 0xac, 0xff, 0xac, 0xa9, 0xac, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0xa1, 0x9e, 0x9c, 0xff, 0x8e, 0x7a, 0x7c, 0xff, + 0x6b, 0x56, 0x5c, 0xff, 0xb4, 0xaa, 0xac, 0xff, 0xd5, 0xcd, 0xcc, 0xff, + 0x77, 0x66, 0x6c, 0xff, 0x6c, 0x61, 0x64, 0xff, 0x7f, 0x72, 0x6c, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0x63, 0x66, 0x64, 0xff, 0x72, 0x62, 0x5c, 0xff, + 0x69, 0x4e, 0x4c, 0xff, 0x69, 0x4e, 0x4c, 0xff, 0x69, 0x4e, 0x4c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x3e, 0x34, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x69, 0x4e, 0x44, 0xff, 0x6a, 0x53, 0x4c, 0xff, 0x72, 0x5b, 0x54, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0x7e, 0x6d, 0x6c, 0xff, 0x72, 0x62, 0x5c, 0xff, + 0x81, 0x7e, 0x7c, 0xff, 0x8c, 0x81, 0x84, 0xff, 0x7e, 0x6d, 0x6c, 0xff, + 0x7e, 0x6d, 0x6c, 0xff, 0x81, 0x72, 0x74, 0xff, 0x8e, 0x7a, 0x7c, 0xff, + 0x84, 0x77, 0x74, 0xff, 0x81, 0x72, 0x74, 0xff, 0x84, 0x77, 0x74, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0xad, 0x9a, 0x9c, 0xff, 0xb4, 0xaa, 0xac, 0xff, + 0xac, 0xa9, 0xac, 0xff, 0xb4, 0xaa, 0xac, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0xad, 0x9a, 0x9c, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0xc4, 0xba, 0xbc, 0xff, 0xae, 0xa4, 0xa4, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0x94, 0x8c, 0x8c, 0xff, 0xa1, 0x99, 0x9c, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0xa3, 0xa3, 0xa4, 0xff, 0xc2, 0xbe, 0xbc, 0xff, 0xcc, 0xc5, 0xc4, 0xff, + 0xc4, 0xbe, 0xc4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0xd6, 0xd2, 0xd4, 0xff, 0xbc, 0xb1, 0xb4, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0xcc, 0xc2, 0xbc, 0xff, 0xae, 0xa4, 0xa4, 0xff, 0x9c, 0x92, 0x84, 0xff, + 0xe2, 0xdc, 0xcc, 0xff, 0xfc, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xc4, 0xba, 0xbc, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xa3, 0xa3, 0xa4, 0xff, + 0x94, 0x8c, 0x8c, 0xff, 0xac, 0xa9, 0xac, 0xff, 0xa3, 0xa3, 0xa4, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0x9a, 0x94, 0x94, 0xff, 0xb4, 0xaa, 0xac, 0xff, + 0xa1, 0x99, 0x9c, 0xff, 0xa4, 0x9e, 0xa4, 0xff, 0xb3, 0xae, 0xac, 0xff, + 0x83, 0x82, 0x84, 0xff, 0x64, 0x5d, 0x5c, 0xff, 0x6b, 0x56, 0x5c, 0xff, + 0xc5, 0xb7, 0xb4, 0xff, 0x64, 0x5d, 0x5c, 0xff, 0x64, 0x5d, 0x5c, 0xff, + 0x72, 0x62, 0x5c, 0xff, 0x72, 0x62, 0x5c, 0xff, 0x7f, 0x72, 0x6c, 0xff, + 0x7f, 0x6a, 0x64, 0xff, 0x61, 0x48, 0x44, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x6c, 0x4a, 0x44, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x69, 0x4e, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x69, 0x55, 0x54, 0xff, 0x7f, 0x72, 0x6c, 0xff, 0x84, 0x77, 0x74, 0xff, + 0x8e, 0x7a, 0x7c, 0xff, 0x75, 0x62, 0x64, 0xff, 0x75, 0x62, 0x64, 0xff, + 0x84, 0x77, 0x74, 0xff, 0x84, 0x77, 0x74, 0xff, 0x81, 0x72, 0x74, 0xff, + 0x8c, 0x81, 0x84, 0xff, 0x94, 0x8c, 0x8c, 0xff, 0x81, 0x72, 0x74, 0xff, + 0x96, 0x85, 0x84, 0xff, 0xac, 0xa9, 0xac, 0xff, 0xcc, 0xc5, 0xc4, 0xff, + 0xc2, 0xbe, 0xbc, 0xff, 0xbc, 0xb0, 0xac, 0xff, 0xc4, 0xba, 0xbc, 0xff, + 0xad, 0x9e, 0x9e, 0xff, 0x94, 0x8c, 0x8c, 0xff, 0x9e, 0x8e, 0x94, 0xff, + 0x84, 0x79, 0x7c, 0xff, 0x83, 0x82, 0x84, 0xff, 0x9d, 0x8d, 0x8c, 0xff, + 0xa4, 0x9e, 0xa4, 0xff, 0x9a, 0x94, 0x94, 0xff, 0x94, 0x8e, 0x94, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0xbc, 0xb9, 0xbc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xcc, 0xc5, 0xc4, 0xff, 0xcf, 0xc6, 0xcc, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0xcc, 0xbe, 0xc4, 0xff, 0xc4, 0xba, 0xbc, 0xff, 0xcc, 0xbd, 0xbc, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xbc, 0xb0, 0xac, 0xff, 0x8f, 0x86, 0x7c, 0xff, + 0xa8, 0x9b, 0x94, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf2, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf1, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xd5, 0xcd, 0xcc, 0xff, 0xb3, 0xae, 0xac, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0xa3, 0xa3, 0xa4, 0xff, 0x9a, 0x94, 0x94, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0xa1, 0x9e, 0x9c, 0xff, 0x94, 0x8e, 0x94, 0xff, 0x94, 0x8c, 0x8c, 0xff, + 0x96, 0x86, 0x8c, 0xff, 0x9a, 0x94, 0x94, 0xff, 0xc4, 0xba, 0xbc, 0xff, + 0xd4, 0xc6, 0xc4, 0xff, 0x6b, 0x56, 0x5c, 0xff, 0x6c, 0x61, 0x64, 0xff, + 0x81, 0x72, 0x74, 0xff, 0x55, 0x55, 0x54, 0xff, 0x6b, 0x56, 0x5c, 0xff, + 0x5d, 0x62, 0x5c, 0xff, 0x6c, 0x61, 0x64, 0xff, 0x71, 0x6a, 0x64, 0xff, + 0x8f, 0x7f, 0x7c, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x69, 0x4e, 0x44, 0xff, 0x6c, 0x4a, 0x44, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x6c, 0x4a, 0x44, 0xff, 0x61, 0x48, 0x44, 0xff, 0x6a, 0x53, 0x4c, 0xff, + 0x6a, 0x53, 0x4c, 0xff, 0x72, 0x62, 0x5c, 0xff, 0x89, 0x86, 0x84, 0xff, + 0x9c, 0x93, 0x8c, 0xff, 0x8c, 0x81, 0x84, 0xff, 0x96, 0x86, 0x8c, 0xff, + 0x84, 0x79, 0x7c, 0xff, 0x8c, 0x81, 0x84, 0xff, 0x84, 0x77, 0x74, 0xff, + 0x8c, 0x81, 0x84, 0xff, 0x9d, 0x8d, 0x8c, 0xff, 0x8f, 0x7f, 0x7c, 0xff, + 0x81, 0x72, 0x74, 0xff, 0x94, 0x8c, 0x8c, 0xff, 0xbc, 0xb1, 0xb4, 0xff, + 0xbc, 0xb9, 0xbc, 0xff, 0xae, 0xa4, 0xa4, 0xff, 0xbc, 0xb9, 0xbc, 0xff, + 0xb4, 0xaa, 0xac, 0xff, 0x9a, 0x94, 0x94, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0x9e, 0x8e, 0x94, 0xff, 0xa6, 0x95, 0x94, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0xa1, 0x99, 0x9c, 0xff, 0x8b, 0x8b, 0x8c, 0xff, + 0xac, 0xa9, 0xac, 0xff, 0xbc, 0xb9, 0xbc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xe4, 0xe1, 0xe4, 0xff, 0xd6, 0xd2, 0xd4, 0xff, 0xc4, 0xbe, 0xc4, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xd5, 0xcd, 0xcc, 0xff, 0xd5, 0xcd, 0xcc, 0xff, + 0xc4, 0xba, 0xbc, 0xff, 0xb1, 0xaa, 0xa4, 0xff, 0xb1, 0xaa, 0xa4, 0xff, + 0x8f, 0x7f, 0x7c, 0xff, 0xbc, 0xb6, 0xac, 0xff, 0xfb, 0xf9, 0xec, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xfc, 0xf1, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xcf, 0xc6, 0xcc, 0xff, 0xac, 0xa9, 0xac, 0xff, 0x9a, 0x94, 0x94, 0xff, + 0xb3, 0xae, 0xac, 0xff, 0xac, 0xa9, 0xac, 0xff, 0xa3, 0xa3, 0xa4, 0xff, + 0xb4, 0xb2, 0xb4, 0xff, 0xb3, 0xae, 0xac, 0xff, 0xa3, 0xa3, 0xa4, 0xff, + 0x7b, 0x7a, 0x7c, 0xff, 0x96, 0x85, 0x84, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0xa4, 0x9e, 0xa4, 0xff, 0x7e, 0x6d, 0x6c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x69, 0x55, 0x54, 0xff, 0x55, 0x52, 0x4c, 0xff, 0x70, 0x5e, 0x5c, 0xff, + 0x71, 0x6a, 0x64, 0xff, 0x78, 0x66, 0x64, 0xff, 0x71, 0x6a, 0x64, 0xff, + 0x7e, 0x6d, 0x6c, 0xff, 0x84, 0x77, 0x74, 0xff, 0x50, 0x4e, 0x44, 0xff, + 0x61, 0x48, 0x44, 0xff, 0x6c, 0x4a, 0x44, 0xff, 0x6c, 0x4a, 0x44, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x5c, 0x3e, 0x34, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x5c, 0x3e, 0x34, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x61, 0x48, 0x44, 0xff, 0x81, 0x72, 0x74, 0xff, 0x9d, 0x8d, 0x8c, 0xff, + 0xad, 0x9e, 0x9e, 0xff, 0xa6, 0x95, 0x94, 0xff, 0x8c, 0x81, 0x84, 0xff, + 0x9c, 0x80, 0x7c, 0xff, 0x84, 0x79, 0x7c, 0xff, 0x8f, 0x7f, 0x7c, 0xff, + 0x8c, 0x81, 0x84, 0xff, 0x96, 0x85, 0x84, 0xff, 0x96, 0x85, 0x84, 0xff, + 0x78, 0x77, 0x74, 0xff, 0x96, 0x85, 0x84, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0xb4, 0xb2, 0xb4, 0xff, 0xac, 0xa9, 0xac, 0xff, 0x9a, 0x94, 0x94, 0xff, + 0x94, 0x8c, 0x8c, 0xff, 0xa4, 0x9e, 0xa4, 0xff, 0xc5, 0xb7, 0xb4, 0xff, + 0xb4, 0xaa, 0xac, 0xff, 0xc4, 0xba, 0xbc, 0xff, 0xb4, 0xaa, 0xac, 0xff, + 0xba, 0xb6, 0xb4, 0xff, 0xa3, 0xa3, 0xa4, 0xff, 0x9a, 0x94, 0x94, 0xff, + 0xb4, 0xaa, 0xac, 0xff, 0xc2, 0xbe, 0xbc, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0xcf, 0xc6, 0xcc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xba, 0xb6, 0xb4, 0xff, + 0xbc, 0xb9, 0xbc, 0xff, 0xbc, 0xb1, 0xb4, 0xff, 0xbc, 0xb1, 0xb4, 0xff, + 0xd4, 0xc6, 0xc4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xcc, 0xc2, 0xbc, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0x9c, 0x88, 0x7c, 0xff, 0xe6, 0xd6, 0xcc, 0xff, + 0xfc, 0xf2, 0xe4, 0xff, 0xfb, 0xf9, 0xec, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xcc, 0xc5, 0xc4, 0xff, 0xd6, 0xd2, 0xd4, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0xa3, 0xa3, 0xa4, 0xff, 0x9a, 0x94, 0x94, 0xff, 0xb1, 0xaa, 0xa4, 0xff, + 0xbc, 0xb9, 0xbc, 0xff, 0xb3, 0xae, 0xac, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0xa1, 0x9e, 0x9c, 0xff, 0x83, 0x82, 0x84, 0xff, 0x78, 0x77, 0x74, 0xff, + 0xa6, 0x95, 0x94, 0xff, 0x6f, 0x6c, 0x6c, 0xff, 0x58, 0x49, 0x4c, 0xff, + 0x64, 0x4e, 0x54, 0xff, 0x69, 0x55, 0x54, 0xff, 0x72, 0x62, 0x5c, 0xff, + 0x6f, 0x6c, 0x6c, 0xff, 0x78, 0x66, 0x64, 0xff, 0x6f, 0x6c, 0x6c, 0xff, + 0x81, 0x72, 0x74, 0xff, 0x8f, 0x7f, 0x7c, 0xff, 0x7f, 0x6a, 0x64, 0xff, + 0x61, 0x48, 0x44, 0xff, 0x61, 0x48, 0x44, 0xff, 0x69, 0x4e, 0x4c, 0xff, + 0x6c, 0x4a, 0x44, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x61, 0x48, 0x44, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x69, 0x4e, 0x4c, 0xff, + 0x7f, 0x72, 0x6c, 0xff, 0x9d, 0x8d, 0x8c, 0xff, 0xad, 0x9a, 0x9c, 0xff, + 0x94, 0x8c, 0x8c, 0xff, 0x84, 0x79, 0x7c, 0xff, 0x8f, 0x7f, 0x7c, 0xff, + 0x81, 0x72, 0x74, 0xff, 0x84, 0x77, 0x74, 0xff, 0x78, 0x77, 0x74, 0xff, + 0x8c, 0x81, 0x84, 0xff, 0x8c, 0x81, 0x84, 0xff, 0xba, 0xb6, 0xb4, 0xff, + 0xc4, 0xba, 0xbc, 0xff, 0xbc, 0xb0, 0xac, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0xb3, 0xae, 0xac, 0xff, 0xbc, 0xb1, 0xb4, 0xff, + 0xb4, 0xb2, 0xb4, 0xff, 0xb3, 0xae, 0xac, 0xff, 0xb4, 0xb2, 0xb4, 0xff, + 0xba, 0xb6, 0xb4, 0xff, 0xc4, 0xba, 0xbc, 0xff, 0xa1, 0x9e, 0x9c, 0xff, + 0xa3, 0xa3, 0xa4, 0xff, 0xc4, 0xba, 0xbc, 0xff, 0xcc, 0xc5, 0xc4, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xb4, 0xb2, 0xb4, 0xff, 0xbc, 0xb1, 0xb4, 0xff, + 0xbc, 0xb9, 0xbc, 0xff, 0xb4, 0xb2, 0xb4, 0xff, 0xd5, 0xcd, 0xcc, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xcc, 0xbd, 0xbc, 0xff, + 0xba, 0xb6, 0xb4, 0xff, 0x9c, 0x93, 0x8c, 0xff, 0xa8, 0x9b, 0x94, 0xff, + 0xf2, 0xe9, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xdc, 0xdc, 0xdc, 0xff, 0xcf, 0xc6, 0xcc, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0xba, 0xb6, 0xb4, 0xff, 0x9a, 0x94, 0x94, 0xff, 0x94, 0x8e, 0x94, 0xff, + 0xc4, 0xbe, 0xc4, 0xff, 0xcc, 0xc5, 0xc4, 0xff, 0xb3, 0xae, 0xac, 0xff, + 0xb3, 0xae, 0xac, 0xff, 0xba, 0xb6, 0xb4, 0xff, 0x8b, 0x8b, 0x8c, 0xff, + 0x64, 0x5d, 0x5c, 0xff, 0x69, 0x55, 0x54, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x5d, 0x5a, 0x54, 0xff, 0x78, 0x66, 0x64, 0xff, + 0x7e, 0x6d, 0x6c, 0xff, 0xc6, 0xb1, 0xb4, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0x8f, 0x7f, 0x7c, 0xff, 0x78, 0x66, 0x64, 0xff, 0x7e, 0x6d, 0x6c, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0x61, 0x48, 0x44, 0xff, 0x58, 0x49, 0x4c, 0xff, + 0x74, 0x4e, 0x4c, 0xff, 0x6c, 0x4a, 0x44, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x61, 0x48, 0x44, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x69, 0x55, 0x54, 0xff, 0x69, 0x55, 0x54, 0xff, 0x8f, 0x86, 0x7c, 0xff, + 0xa6, 0x95, 0x94, 0xff, 0x96, 0x85, 0x84, 0xff, 0x96, 0x86, 0x8c, 0xff, + 0x78, 0x66, 0x64, 0xff, 0x77, 0x66, 0x6c, 0xff, 0x7e, 0x6d, 0x6c, 0xff, + 0x8f, 0x7f, 0x7c, 0xff, 0x94, 0x8c, 0x8c, 0xff, 0xbc, 0xb0, 0xac, 0xff, + 0xba, 0xb6, 0xb4, 0xff, 0xba, 0xb6, 0xb4, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0x89, 0x86, 0x84, 0xff, 0xbc, 0xb0, 0xac, 0xff, 0xb1, 0xaa, 0xa4, 0xff, + 0xbc, 0xb1, 0xb4, 0xff, 0xbc, 0xb9, 0xbc, 0xff, 0xbc, 0xb1, 0xb4, 0xff, + 0xba, 0xb6, 0xb4, 0xff, 0xc4, 0xbe, 0xc4, 0xff, 0xbc, 0xb9, 0xbc, 0xff, + 0xa1, 0x99, 0x9c, 0xff, 0xa3, 0xa3, 0xa4, 0xff, 0xbc, 0xb9, 0xbc, 0xff, + 0xcc, 0xc5, 0xc4, 0xff, 0xbc, 0xb9, 0xbc, 0xff, 0xac, 0xa9, 0xac, 0xff, + 0xba, 0xb6, 0xb4, 0xff, 0xbc, 0xb1, 0xb4, 0xff, 0xdc, 0xd6, 0xdc, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xd4, 0xc6, 0xc4, 0xff, 0xcc, 0xbe, 0xc4, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0xbc, 0xb1, 0xb4, 0xff, 0x94, 0x8b, 0x84, 0xff, + 0xba, 0xb0, 0xa4, 0xff, 0xf4, 0xea, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xdc, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xe4, 0xe2, 0xd8, 0xff, 0xd6, 0xd2, 0xd4, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0xa1, 0x9e, 0x9c, 0xff, 0xa3, 0xa3, 0xa4, 0xff, 0x9a, 0x94, 0x94, 0xff, + 0xb3, 0xae, 0xac, 0xff, 0xba, 0xb6, 0xb4, 0xff, 0xb3, 0xae, 0xac, 0xff, + 0xa3, 0xa3, 0xa4, 0xff, 0x9c, 0x9a, 0x94, 0xff, 0xbc, 0xb0, 0xac, 0xff, + 0x81, 0x7e, 0x7c, 0xff, 0x7e, 0x6d, 0x6c, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x69, 0x55, 0x54, 0xff, 0x8e, 0x79, 0x74, 0xff, 0x7e, 0x6d, 0x6c, 0xff, + 0x84, 0x79, 0x7c, 0xff, 0x9a, 0x94, 0x94, 0xff, 0xd7, 0xcc, 0xc4, 0xff, + 0x64, 0x5d, 0x5c, 0xff, 0x7e, 0x6d, 0x6c, 0xff, 0x81, 0x72, 0x74, 0xff, + 0x8e, 0x7a, 0x7c, 0xff, 0x69, 0x55, 0x54, 0xff, 0x5c, 0x42, 0x44, 0xff, + 0x69, 0x4e, 0x4c, 0xff, 0x6c, 0x4a, 0x44, 0xff, 0x5c, 0x42, 0x44, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x6c, 0x4a, 0x44, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x3e, 0x34, 0xff, + 0x5c, 0x42, 0x44, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x72, 0x62, 0x5c, 0xff, 0x63, 0x66, 0x64, 0xff, 0x8e, 0x7a, 0x7c, 0xff, + 0x64, 0x5d, 0x5c, 0xff, 0x7e, 0x6d, 0x6c, 0xff, 0x94, 0x8c, 0x8c, 0xff, + 0x84, 0x79, 0x7c, 0xff, 0x6f, 0x6c, 0x6c, 0xff, 0x84, 0x79, 0x7c, 0xff, + 0x96, 0x85, 0x84, 0xff, 0x9a, 0x94, 0x94, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0xb4, 0xb2, 0xb4, 0xff, 0xba, 0xb6, 0xb4, 0xff, 0xba, 0xb6, 0xb4, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0x9a, 0x94, 0x94, 0xff, 0xba, 0xb6, 0xb4, 0xff, + 0xb1, 0xaa, 0xa4, 0xff, 0xbc, 0xb9, 0xbc, 0xff, 0xb4, 0xb2, 0xb4, 0xff, + 0xb4, 0xaa, 0xac, 0xff, 0xb3, 0xae, 0xac, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0xbc, 0xb9, 0xbc, 0xff, 0xb3, 0xae, 0xac, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0xc4, 0xbe, 0xc4, 0xff, 0xcc, 0xc5, 0xc4, 0xff, 0xbc, 0xb9, 0xbc, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0xc4, 0xba, 0xbc, 0xff, 0xba, 0xb6, 0xb4, 0xff, + 0xc4, 0xbe, 0xc4, 0xff, 0xd5, 0xcd, 0xcc, 0xff, 0xcf, 0xc6, 0xcc, 0xff, + 0xb3, 0xae, 0xac, 0xff, 0xc2, 0xbe, 0xbc, 0xff, 0xad, 0x9e, 0x9e, 0xff, + 0x81, 0x7e, 0x7c, 0xff, 0xcc, 0xbe, 0xac, 0xff, 0xfb, 0xf9, 0xec, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfa, 0xfe, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfa, 0xfe, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xd7, 0xd6, 0xd4, 0xff, 0xba, 0xb6, 0xb4, 0xff, + 0xac, 0xa9, 0xac, 0xff, 0xb3, 0xae, 0xac, 0xff, 0xb3, 0xae, 0xac, 0xff, + 0xa1, 0x9e, 0x9c, 0xff, 0x94, 0x8e, 0x94, 0xff, 0xa3, 0xa3, 0xa4, 0xff, + 0xa3, 0xa3, 0xa4, 0xff, 0xa3, 0xa3, 0xa4, 0xff, 0xa3, 0xa3, 0xa4, 0xff, + 0xa8, 0x9b, 0x94, 0xff, 0x89, 0x86, 0x84, 0xff, 0x72, 0x5b, 0x54, 0xff, + 0x69, 0x55, 0x54, 0xff, 0x81, 0x72, 0x74, 0xff, 0x70, 0x5e, 0x5c, 0xff, + 0x8f, 0x7f, 0x7c, 0xff, 0x78, 0x66, 0x64, 0xff, 0x9a, 0x94, 0x94, 0xff, + 0x6b, 0x56, 0x5c, 0xff, 0x9d, 0x8d, 0x8c, 0xff, 0xa4, 0x9e, 0xa4, 0xff, + 0xbd, 0xa6, 0xa4, 0xff, 0x84, 0x77, 0x74, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x61, 0x48, 0x44, 0xff, 0x69, 0x4e, 0x4c, 0xff, 0x74, 0x4e, 0x4c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x6c, 0x4a, 0x44, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x61, 0x48, 0x44, 0xff, 0x6a, 0x53, 0x4c, 0xff, + 0x78, 0x66, 0x64, 0xff, 0x96, 0x85, 0x84, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0x94, 0x8c, 0x8c, 0xff, 0x8f, 0x7f, 0x7c, 0xff, 0x78, 0x77, 0x74, 0xff, + 0x96, 0x85, 0x84, 0xff, 0x84, 0x79, 0x7c, 0xff, 0x8f, 0x7f, 0x7c, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0x9d, 0x8d, 0x8c, 0xff, 0xa6, 0x95, 0x94, 0xff, + 0xba, 0xb6, 0xb4, 0xff, 0xba, 0xb6, 0xb4, 0xff, 0xba, 0xb6, 0xb4, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0x83, 0x82, 0x84, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0xa3, 0xa3, 0xa4, 0xff, 0xb4, 0xb2, 0xb4, 0xff, 0xb4, 0xb2, 0xb4, 0xff, + 0xb3, 0xae, 0xac, 0xff, 0xbc, 0xb9, 0xbc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xbc, 0xb9, 0xbc, 0xff, 0xc2, 0xbe, 0xbc, 0xff, 0xbc, 0xb9, 0xbc, 0xff, + 0xc2, 0xbe, 0xbc, 0xff, 0xbc, 0xb9, 0xbc, 0xff, 0xcc, 0xc5, 0xc4, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0xf8, 0xea, 0xec, 0xff, 0xec, 0xe2, 0xe4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0xcf, 0xc6, 0xcc, 0xff, 0xc5, 0xb7, 0xb4, 0xff, 0xbc, 0xb1, 0xb4, 0xff, + 0x90, 0x7f, 0x74, 0xff, 0x9c, 0x93, 0x8c, 0xff, 0xfb, 0xf9, 0xec, 0xff, + 0xfc, 0xf2, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfa, 0xfe, 0xdc, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xcc, 0xc5, 0xc4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xd6, 0xd2, 0xd4, 0xff, + 0xba, 0xb6, 0xb4, 0xff, 0xbc, 0xb9, 0xbc, 0xff, 0xba, 0xb6, 0xb4, 0xff, + 0xc2, 0xc2, 0xbc, 0xff, 0xb3, 0xae, 0xac, 0xff, 0x9c, 0x9a, 0x94, 0xff, + 0x94, 0x8e, 0x94, 0xff, 0x9a, 0x94, 0x94, 0xff, 0x9c, 0x9a, 0x94, 0xff, + 0xa1, 0x9e, 0x9c, 0xff, 0x94, 0x8b, 0x84, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x58, 0x49, 0x4c, 0xff, 0x7f, 0x72, 0x6c, 0xff, 0x7e, 0x6d, 0x6c, 0xff, + 0x6f, 0x6c, 0x6c, 0xff, 0x64, 0x4e, 0x54, 0xff, 0x4e, 0x42, 0x44, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x78, 0x66, 0x64, 0xff, 0x8f, 0x7f, 0x7c, 0xff, + 0x84, 0x79, 0x7c, 0xff, 0x96, 0x85, 0x84, 0xff, 0x7d, 0x62, 0x5c, 0xff, + 0x53, 0x41, 0x3c, 0xff, 0x75, 0x56, 0x54, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x6c, 0x4a, 0x44, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x6c, 0x4a, 0x44, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x61, 0x48, 0x44, 0xff, 0x58, 0x49, 0x4c, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0x8f, 0x86, 0x7c, 0xff, 0xbc, 0xb0, 0xac, 0xff, + 0xbc, 0xb1, 0xb4, 0xff, 0x9a, 0x94, 0x94, 0xff, 0x96, 0x85, 0x84, 0xff, + 0x94, 0x8c, 0x8c, 0xff, 0x9d, 0x8d, 0x8c, 0xff, 0x96, 0x85, 0x84, 0xff, + 0xa1, 0x99, 0x9c, 0xff, 0x96, 0x85, 0x84, 0xff, 0xa4, 0x9e, 0xa4, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0xbc, 0xb0, 0xac, 0xff, 0xb4, 0xb2, 0xb4, 0xff, + 0xba, 0xb6, 0xb4, 0xff, 0xa1, 0x9e, 0x9c, 0xff, 0x94, 0x8c, 0x8c, 0xff, + 0xbc, 0xb0, 0xac, 0xff, 0xb4, 0xb2, 0xb4, 0xff, 0xbc, 0xb9, 0xbc, 0xff, + 0xb4, 0xb2, 0xb4, 0xff, 0xbc, 0xb9, 0xbc, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0xcc, 0xc5, 0xc4, 0xff, 0xc4, 0xba, 0xbc, 0xff, 0xbc, 0xb9, 0xbc, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0xac, 0xa9, 0xac, 0xff, 0xd6, 0xd2, 0xd4, 0xff, + 0xe4, 0xe1, 0xe4, 0xff, 0xdc, 0xdc, 0xdc, 0xff, 0xe4, 0xd2, 0xd4, 0xff, + 0xd5, 0xcd, 0xcc, 0xff, 0xc2, 0xbe, 0xbc, 0xff, 0xd9, 0xd4, 0xcc, 0xff, + 0xa8, 0x9b, 0x94, 0xff, 0xa6, 0x95, 0x94, 0xff, 0xd7, 0xcc, 0xc4, 0xff, + 0xfb, 0xf9, 0xec, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfa, 0xfe, 0xdc, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xc4, 0xbe, 0xc4, 0xff, 0xba, 0xb6, 0xb4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xc2, 0xbe, 0xbc, 0xff, 0xac, 0xa9, 0xac, 0xff, 0xb4, 0xb2, 0xb4, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xb4, 0xb2, 0xb4, 0xff, + 0xac, 0xa9, 0xac, 0xff, 0xb3, 0xae, 0xac, 0xff, 0xa1, 0xa2, 0x9c, 0xff, + 0xa1, 0x99, 0x9c, 0xff, 0xad, 0x9e, 0x9e, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x69, 0x55, 0x54, 0xff, 0x78, 0x66, 0x64, 0xff, + 0x8c, 0x81, 0x84, 0xff, 0x6b, 0x56, 0x5c, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0x64, 0x5d, 0x5c, 0xff, 0x81, 0x72, 0x74, 0xff, + 0x9c, 0x93, 0x8c, 0xff, 0xc4, 0xb2, 0xac, 0xff, 0xa6, 0x95, 0x94, 0xff, + 0x58, 0x49, 0x4c, 0xff, 0x6c, 0x4a, 0x44, 0xff, 0x69, 0x4e, 0x4c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x6c, 0x4a, 0x44, 0xff, 0x6c, 0x4a, 0x44, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x6c, 0x4a, 0x44, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x61, 0x48, 0x44, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x72, 0x62, 0x5c, 0xff, 0x84, 0x77, 0x74, 0xff, 0x81, 0x7e, 0x7c, 0xff, + 0x8f, 0x7f, 0x7c, 0xff, 0x96, 0x85, 0x84, 0xff, 0x8c, 0x81, 0x84, 0xff, + 0x89, 0x86, 0x84, 0xff, 0x9d, 0x8d, 0x8c, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0xb0, 0xa3, 0x9c, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0xb3, 0xae, 0xac, 0xff, 0xbc, 0xb9, 0xbc, 0xff, 0xba, 0xb6, 0xb4, 0xff, + 0xbc, 0xb0, 0xac, 0xff, 0xbc, 0xb1, 0xb4, 0xff, 0x89, 0x86, 0x84, 0xff, + 0xb3, 0xae, 0xac, 0xff, 0xbc, 0xb9, 0xbc, 0xff, 0xd5, 0xcd, 0xcc, 0xff, + 0xc2, 0xbe, 0xbc, 0xff, 0xb4, 0xaa, 0xac, 0xff, 0xbc, 0xb9, 0xbc, 0xff, + 0xd5, 0xcd, 0xcc, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xbc, 0xb9, 0xbc, 0xff, + 0xba, 0xb6, 0xb4, 0xff, 0xc4, 0xba, 0xbc, 0xff, 0xc4, 0xba, 0xbc, 0xff, + 0xb4, 0xb2, 0xb4, 0xff, 0xc2, 0xbe, 0xbc, 0xff, 0xe4, 0xde, 0xdc, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xdc, 0xdc, 0xdc, 0xff, 0xf2, 0xf0, 0xec, 0xff, + 0xcc, 0xbe, 0xc4, 0xff, 0xd4, 0xc6, 0xc4, 0xff, 0xd6, 0xd2, 0xd4, 0xff, + 0xd4, 0xc6, 0xc4, 0xff, 0xa8, 0x93, 0x8c, 0xff, 0xbc, 0xb0, 0xac, 0xff, + 0xfb, 0xf9, 0xec, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfa, 0xfe, 0xdc, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xbc, 0xb9, 0xbc, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0xc2, 0xbe, 0xbc, 0xff, 0x92, 0x92, 0x8c, 0xff, 0xa3, 0xa3, 0xa4, 0xff, + 0xbc, 0xb9, 0xbc, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0xc2, 0xbe, 0xbc, 0xff, 0xba, 0xb6, 0xb4, 0xff, 0xb4, 0xb2, 0xb4, 0xff, + 0xbc, 0xb0, 0xac, 0xff, 0xa6, 0x95, 0x94, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x6a, 0x53, 0x4c, 0xff, 0x70, 0x5e, 0x5c, 0xff, 0x75, 0x62, 0x64, 0xff, + 0x96, 0x85, 0x84, 0xff, 0x7e, 0x6d, 0x6c, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x6c, 0x61, 0x64, 0xff, 0x64, 0x5d, 0x5c, 0xff, 0x78, 0x66, 0x64, 0xff, + 0xb4, 0xb2, 0xb4, 0xff, 0xc4, 0xba, 0xbc, 0xff, 0x80, 0x67, 0x5c, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x61, 0x48, 0x44, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x6c, 0x4a, 0x44, 0xff, 0x6c, 0x4a, 0x44, 0xff, 0x6c, 0x4a, 0x44, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x6c, 0x4a, 0x44, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x5c, 0x42, 0x44, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x58, 0x49, 0x4c, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0x8f, 0x7f, 0x7c, 0xff, 0x8f, 0x7f, 0x7c, 0xff, + 0x81, 0x72, 0x74, 0xff, 0x89, 0x86, 0x84, 0xff, 0x96, 0x85, 0x84, 0xff, + 0x8f, 0x7f, 0x7c, 0xff, 0x94, 0x8c, 0x8c, 0xff, 0xa6, 0x95, 0x94, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0x9e, 0x8e, 0x94, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0xd5, 0xcd, 0xcc, 0xff, 0xc2, 0xbe, 0xbc, 0xff, 0xba, 0xb6, 0xb4, 0xff, + 0xa3, 0xa3, 0xa4, 0xff, 0xa1, 0xa2, 0x9c, 0xff, 0xbc, 0xb0, 0xac, 0xff, + 0xa1, 0x9e, 0x9c, 0xff, 0xb4, 0xb2, 0xb4, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0xd6, 0xd2, 0xd4, 0xff, 0xb4, 0xaa, 0xac, 0xff, 0xb3, 0xae, 0xac, 0xff, + 0xa4, 0x9e, 0xa4, 0xff, 0xb4, 0xaa, 0xac, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0xc2, 0xbe, 0xbc, 0xff, 0xb4, 0xb2, 0xb4, 0xff, 0xbc, 0xb9, 0xbc, 0xff, + 0xac, 0xa9, 0xac, 0xff, 0xc4, 0xba, 0xbc, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0xd5, 0xcd, 0xcc, 0xff, 0xfc, 0xf6, 0xf4, 0xff, 0xdc, 0xd6, 0xdc, 0xff, + 0xd4, 0xc6, 0xc4, 0xff, 0xc4, 0xba, 0xbc, 0xff, 0xd4, 0xc6, 0xc4, 0xff, + 0xdc, 0xd6, 0xdc, 0xff, 0xad, 0x9e, 0x9e, 0xff, 0xa8, 0x93, 0x8c, 0xff, + 0xd5, 0xcd, 0xcc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xdc, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfa, 0xfe, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xfa, 0xfe, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xe9, 0xd4, 0xff, + 0xcc, 0xc5, 0xc4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0xc2, 0xbe, 0xbc, 0xff, 0xa3, 0xa3, 0xa4, 0xff, 0xbc, 0xb9, 0xbc, 0xff, + 0xb3, 0xae, 0xac, 0xff, 0xb4, 0xb2, 0xb4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xb4, 0xb2, 0xb4, 0xff, 0xbc, 0xb0, 0xac, 0xff, + 0xac, 0xa9, 0xac, 0xff, 0xae, 0xa4, 0xa4, 0xff, 0x69, 0x4e, 0x4c, 0xff, + 0x58, 0x49, 0x4c, 0xff, 0x69, 0x55, 0x54, 0xff, 0x7e, 0x6d, 0x6c, 0xff, + 0x69, 0x4e, 0x4c, 0xff, 0x81, 0x72, 0x74, 0xff, 0x6c, 0x61, 0x64, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0x70, 0x5e, 0x5c, 0xff, 0x6f, 0x6c, 0x6c, 0xff, + 0xb3, 0xae, 0xac, 0xff, 0xbc, 0xaa, 0xac, 0xff, 0x8f, 0x7f, 0x7c, 0xff, + 0x8e, 0x7a, 0x7c, 0xff, 0x69, 0x55, 0x54, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x69, 0x4e, 0x4c, 0xff, 0x61, 0x48, 0x44, 0xff, 0x6c, 0x4a, 0x44, 0xff, + 0x6c, 0x4a, 0x44, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x5c, 0x3e, 0x34, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x61, 0x48, 0x44, 0xff, 0x5c, 0x3e, 0x34, 0xff, + 0x6c, 0x4a, 0x44, 0xff, 0x61, 0x48, 0x44, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x6a, 0x53, 0x4c, 0xff, 0x8f, 0x7f, 0x7c, 0xff, 0x84, 0x77, 0x74, 0xff, + 0x7e, 0x6d, 0x6c, 0xff, 0x8c, 0x81, 0x84, 0xff, 0xa6, 0x95, 0x94, 0xff, + 0x8c, 0x81, 0x84, 0xff, 0x8c, 0x81, 0x84, 0xff, 0x94, 0x8c, 0x8c, 0xff, + 0xa6, 0x95, 0x94, 0xff, 0x89, 0x86, 0x84, 0xff, 0x9c, 0x9a, 0x94, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0xbc, 0xb1, 0xb4, 0xff, 0xc2, 0xc2, 0xbc, 0xff, + 0x94, 0x8c, 0x8c, 0xff, 0xae, 0xa4, 0xa4, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0xae, 0xa4, 0xa4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xbc, 0xb1, 0xb4, 0xff, 0xac, 0xa9, 0xac, 0xff, + 0xba, 0xb6, 0xb4, 0xff, 0xc4, 0xbe, 0xc4, 0xff, 0xbc, 0xb1, 0xb4, 0xff, + 0xbc, 0xb9, 0xbc, 0xff, 0xcc, 0xc5, 0xc4, 0xff, 0xcc, 0xc5, 0xc4, 0xff, + 0xbc, 0xb1, 0xb4, 0xff, 0xc4, 0xbe, 0xc4, 0xff, 0xd5, 0xcd, 0xcc, 0xff, + 0xdc, 0xdc, 0xdc, 0xff, 0xd6, 0xd2, 0xd4, 0xff, 0xd6, 0xd2, 0xd4, 0xff, + 0xec, 0xe2, 0xe4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xb4, 0xaa, 0xac, 0xff, + 0xcc, 0xc2, 0xbc, 0xff, 0xbc, 0xb1, 0xb4, 0xff, 0x8f, 0x7f, 0x7c, 0xff, + 0xb0, 0xa3, 0x9c, 0xff, 0xfc, 0xf2, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfa, 0xfe, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0x94, 0x8e, 0x94, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xac, 0xa9, 0xac, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xc2, 0xbe, 0xbc, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0xbc, 0xb9, 0xbc, 0xff, 0xbc, 0xb9, 0xbc, 0xff, 0xc8, 0xca, 0xc4, 0xff, + 0xc2, 0xc2, 0xbc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xb3, 0xae, 0xac, 0xff, + 0xb4, 0xaa, 0xac, 0xff, 0xad, 0x9e, 0x9e, 0xff, 0x64, 0x4e, 0x54, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x61, 0x48, 0x44, 0xff, 0x81, 0x72, 0x74, 0xff, + 0x6b, 0x56, 0x5c, 0xff, 0x8e, 0x7a, 0x7c, 0xff, 0x8f, 0x7f, 0x7c, 0xff, + 0x64, 0x5d, 0x5c, 0xff, 0x8c, 0x81, 0x84, 0xff, 0x6f, 0x6c, 0x6c, 0xff, + 0x8f, 0x7f, 0x7c, 0xff, 0x8c, 0x81, 0x84, 0xff, 0xa8, 0x9b, 0x94, 0xff, + 0xbc, 0xaa, 0xac, 0xff, 0xad, 0x9a, 0x9c, 0xff, 0x69, 0x4e, 0x4c, 0xff, + 0x69, 0x4e, 0x4c, 0xff, 0x69, 0x4e, 0x4c, 0xff, 0x6a, 0x53, 0x4c, 0xff, + 0x69, 0x4e, 0x44, 0xff, 0x69, 0x4e, 0x44, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x44, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x53, 0x41, 0x3c, 0xff, 0x6f, 0x6c, 0x6c, 0xff, 0x8f, 0x86, 0x7c, 0xff, + 0x78, 0x77, 0x74, 0xff, 0x78, 0x77, 0x74, 0xff, 0x9e, 0x8e, 0x94, 0xff, + 0x81, 0x7e, 0x7c, 0xff, 0x9d, 0x8d, 0x8c, 0xff, 0x84, 0x77, 0x74, 0xff, + 0xad, 0x9e, 0x9e, 0xff, 0x96, 0x86, 0x8c, 0xff, 0x94, 0x8c, 0x8c, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0x94, 0x8c, 0x8c, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0xa1, 0x99, 0x9c, 0xff, 0xbc, 0xb1, 0xb4, 0xff, + 0xa4, 0x9e, 0xa4, 0xff, 0xa3, 0xa3, 0xa4, 0xff, 0xb4, 0xb2, 0xb4, 0xff, + 0xd5, 0xcd, 0xcc, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xcc, 0xc5, 0xc4, 0xff, + 0xb4, 0xb2, 0xb4, 0xff, 0xa3, 0xa3, 0xa4, 0xff, 0xbc, 0xb0, 0xac, 0xff, + 0xc2, 0xbe, 0xbc, 0xff, 0xcf, 0xc6, 0xcc, 0xff, 0xc8, 0xca, 0xc4, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xcc, 0xc5, 0xc4, 0xff, 0xcc, 0xc5, 0xc4, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xd5, 0xcd, 0xcc, 0xff, 0xf4, 0xf2, 0xf4, 0xff, + 0xf4, 0xf2, 0xf4, 0xff, 0xd4, 0xc6, 0xc4, 0xff, 0xb3, 0xae, 0xac, 0xff, + 0xc4, 0xbe, 0xc4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0x9e, 0x8e, 0x94, 0xff, + 0xa8, 0x9b, 0x94, 0xff, 0xc9, 0xc0, 0xb4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfb, 0xfe, 0xec, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xdc, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0x78, 0x77, 0x74, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xd7, 0xd6, 0xd4, 0xff, + 0xb4, 0xb2, 0xb4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xa1, 0x9e, 0x9c, 0xff, + 0x88, 0x8a, 0x84, 0xff, 0xb4, 0xb2, 0xb4, 0xff, 0xa3, 0xa3, 0xa4, 0xff, + 0xa3, 0xa3, 0xa4, 0xff, 0xbc, 0xb9, 0xbc, 0xff, 0xb4, 0xb2, 0xb4, 0xff, + 0xbc, 0xb1, 0xb4, 0xff, 0xa4, 0x9e, 0xa4, 0xff, 0x58, 0x49, 0x4c, 0xff, + 0x58, 0x49, 0x4c, 0xff, 0x69, 0x55, 0x54, 0xff, 0x75, 0x56, 0x54, 0xff, + 0x58, 0x49, 0x4c, 0xff, 0x78, 0x66, 0x64, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0x75, 0x62, 0x64, 0xff, 0xa1, 0x9e, 0x9c, 0xff, 0x81, 0x72, 0x74, 0xff, + 0x6c, 0x66, 0x6c, 0xff, 0x83, 0x82, 0x84, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0xc6, 0xb1, 0xb4, 0xff, 0xcf, 0xc6, 0xcc, 0xff, 0x96, 0x86, 0x8c, 0xff, + 0x64, 0x4e, 0x54, 0xff, 0x75, 0x56, 0x54, 0xff, 0x69, 0x4e, 0x44, 0xff, + 0x74, 0x5b, 0x4c, 0xff, 0x74, 0x4e, 0x44, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x61, 0x48, 0x44, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x5c, 0x42, 0x44, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x72, 0x62, 0x5c, 0xff, 0x81, 0x7e, 0x7c, 0xff, + 0x84, 0x77, 0x74, 0xff, 0x81, 0x72, 0x74, 0xff, 0x96, 0x85, 0x84, 0xff, + 0x94, 0x8c, 0x8c, 0xff, 0xa6, 0x95, 0x94, 0xff, 0x94, 0x8c, 0x8c, 0xff, + 0x8e, 0x7a, 0x7c, 0xff, 0x9a, 0x94, 0x94, 0xff, 0x92, 0x92, 0x8c, 0xff, + 0xa4, 0x9e, 0xa4, 0xff, 0x9a, 0x94, 0x94, 0xff, 0x94, 0x8c, 0x8c, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0x94, 0x8c, 0x8c, 0xff, 0xc6, 0xb1, 0xb4, 0xff, + 0xc4, 0xba, 0xbc, 0xff, 0x9a, 0x94, 0x94, 0xff, 0xb4, 0xb2, 0xb4, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xbc, 0xb9, 0xbc, 0xff, 0xc2, 0xc2, 0xbc, 0xff, + 0xcc, 0xc5, 0xc4, 0xff, 0xb3, 0xae, 0xac, 0xff, 0xa3, 0xa3, 0xa4, 0xff, + 0xbc, 0xb9, 0xbc, 0xff, 0xcc, 0xc5, 0xc4, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xc2, 0xc2, 0xbc, 0xff, 0xcf, 0xc6, 0xcc, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xcc, 0xc5, 0xc4, 0xff, 0xec, 0xe2, 0xe4, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xd6, 0xd2, 0xd4, 0xff, 0xba, 0xb6, 0xb4, 0xff, + 0xc4, 0xbe, 0xc4, 0xff, 0xcc, 0xbd, 0xbc, 0xff, 0xb4, 0xaa, 0xac, 0xff, + 0x94, 0x8c, 0x8c, 0xff, 0xae, 0xa4, 0xa4, 0xff, 0xf4, 0xea, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xdc, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xfa, 0xfe, 0xdc, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0x64, 0x6a, 0x6c, 0xff, 0x9a, 0x94, 0x94, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xba, 0xb6, 0xb4, 0xff, 0x7b, 0x7a, 0x7c, 0xff, + 0x83, 0x82, 0x84, 0xff, 0xc2, 0xc2, 0xbc, 0xff, 0xa3, 0xa3, 0xa4, 0xff, + 0xa1, 0x9e, 0x9c, 0xff, 0xa3, 0xa3, 0xa4, 0xff, 0xb3, 0xae, 0xac, 0xff, + 0xb4, 0xaa, 0xac, 0xff, 0xbc, 0xaa, 0xac, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x64, 0x4e, 0x54, 0xff, 0x6b, 0x56, 0x5c, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x69, 0x55, 0x54, 0xff, 0x6b, 0x56, 0x5c, 0xff, 0x84, 0x77, 0x74, 0xff, + 0x84, 0x77, 0x74, 0xff, 0x84, 0x79, 0x7c, 0xff, 0x71, 0x6a, 0x64, 0xff, + 0x6f, 0x6c, 0x6c, 0xff, 0xa6, 0x95, 0x94, 0xff, 0xb4, 0xb2, 0xb4, 0xff, + 0xc4, 0xba, 0xbc, 0xff, 0xdc, 0xba, 0xbc, 0xff, 0xc6, 0xb1, 0xb4, 0xff, + 0x6b, 0x56, 0x5c, 0xff, 0x75, 0x56, 0x54, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x72, 0x5b, 0x54, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x44, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x61, 0x48, 0x44, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x44, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x6a, 0x53, 0x4c, 0xff, 0x84, 0x77, 0x74, 0xff, + 0x84, 0x77, 0x74, 0xff, 0x81, 0x7e, 0x7c, 0xff, 0x8f, 0x7f, 0x7c, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0x84, 0x79, 0x7c, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0x89, 0x86, 0x84, 0xff, 0x8c, 0x81, 0x84, 0xff, 0x84, 0x79, 0x7c, 0xff, + 0xa6, 0x95, 0x94, 0xff, 0xa1, 0x9e, 0x9c, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0xa6, 0x95, 0x94, 0xff, 0xa1, 0x99, 0x9c, 0xff, 0xac, 0xa9, 0xac, 0xff, + 0xcc, 0xc5, 0xc4, 0xff, 0xb4, 0xb2, 0xb4, 0xff, 0xbc, 0xb1, 0xb4, 0xff, + 0xac, 0xa9, 0xac, 0xff, 0xb3, 0xae, 0xac, 0xff, 0xb4, 0xb2, 0xb4, 0xff, + 0xac, 0xa9, 0xac, 0xff, 0xc2, 0xbe, 0xbc, 0xff, 0xcc, 0xc5, 0xc4, 0xff, + 0xba, 0xb6, 0xb4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xcc, 0xc5, 0xc4, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xbc, 0xb9, 0xbc, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xcf, 0xc6, 0xcc, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0xcc, 0xc5, 0xc4, 0xff, 0xbc, 0xb9, 0xbc, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0xc4, 0xba, 0xbc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xc5, 0xb7, 0xb4, 0xff, + 0x94, 0x8c, 0x8c, 0xff, 0x9c, 0x93, 0x8c, 0xff, 0xd7, 0xcc, 0xc4, 0xff, + 0xfb, 0xf9, 0xec, 0xff, 0xfb, 0xf9, 0xec, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xdc, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xfa, 0xfe, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0x5d, 0x62, 0x5c, 0xff, 0x7b, 0x7a, 0x7c, 0xff, 0xdc, 0xdc, 0xdc, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0x8b, 0x8b, 0x8c, 0xff, + 0x71, 0x72, 0x74, 0xff, 0xa3, 0xa3, 0xa4, 0xff, 0xa1, 0xa2, 0x9c, 0xff, + 0xb4, 0xb2, 0xb4, 0xff, 0xa1, 0x9e, 0x9c, 0xff, 0xa4, 0x9e, 0xa4, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0xa1, 0x99, 0x9c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x58, 0x49, 0x4c, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x64, 0x4e, 0x54, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x6c, 0x61, 0x64, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x6f, 0x6c, 0x6c, 0xff, + 0x6f, 0x6c, 0x6c, 0xff, 0xa1, 0x99, 0x9c, 0xff, 0xc4, 0xba, 0xbc, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0xcc, 0xbe, 0xc4, 0xff, 0xc4, 0xba, 0xbc, 0xff, + 0x8e, 0x72, 0x74, 0xff, 0x69, 0x55, 0x54, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x74, 0x55, 0x4c, 0xff, 0x74, 0x55, 0x4c, 0xff, 0x6c, 0x4a, 0x44, 0xff, + 0x6c, 0x4a, 0x44, 0xff, 0x5c, 0x42, 0x44, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x44, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x61, 0x48, 0x44, 0xff, 0x61, 0x48, 0x44, 0xff, 0x78, 0x77, 0x74, 0xff, + 0x84, 0x77, 0x74, 0xff, 0x81, 0x72, 0x74, 0xff, 0x84, 0x79, 0x7c, 0xff, + 0xa8, 0x9b, 0x94, 0xff, 0x89, 0x86, 0x84, 0xff, 0x94, 0x8c, 0x8c, 0xff, + 0x9d, 0x8d, 0x8c, 0xff, 0xa6, 0x95, 0x94, 0xff, 0x81, 0x72, 0x74, 0xff, + 0x9d, 0x8d, 0x8c, 0xff, 0xae, 0xa4, 0xa4, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0xa1, 0x99, 0x9c, 0xff, 0xa1, 0x99, 0x9c, 0xff, 0x92, 0x92, 0x8c, 0xff, + 0xbc, 0xb9, 0xbc, 0xff, 0xba, 0xb6, 0xb4, 0xff, 0xba, 0xb6, 0xb4, 0xff, + 0xc2, 0xbe, 0xbc, 0xff, 0xcc, 0xc5, 0xc4, 0xff, 0xbc, 0xb9, 0xbc, 0xff, + 0xba, 0xb6, 0xb4, 0xff, 0xba, 0xb6, 0xb4, 0xff, 0xec, 0xea, 0xec, 0xff, + 0xbc, 0xb9, 0xbc, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xc2, 0xbe, 0xbc, 0xff, 0xb4, 0xb2, 0xb4, 0xff, + 0xba, 0xb6, 0xb4, 0xff, 0xbc, 0xb9, 0xbc, 0xff, 0xa3, 0xa3, 0xa4, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xbc, 0xb9, 0xbc, 0xff, + 0xbc, 0xb1, 0xb4, 0xff, 0xba, 0xb6, 0xb4, 0xff, 0xcf, 0xc6, 0xcc, 0xff, + 0xad, 0x9e, 0x9e, 0xff, 0x89, 0x86, 0x84, 0xff, 0xa8, 0x9b, 0x94, 0xff, + 0xf2, 0xe9, 0xdc, 0xff, 0xfc, 0xf2, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xdc, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xfa, 0xfe, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x71, 0x72, 0x6c, 0xff, 0xbc, 0xb9, 0xbc, 0xff, + 0xbc, 0xb9, 0xbc, 0xff, 0x92, 0x92, 0x8c, 0xff, 0x71, 0x72, 0x74, 0xff, + 0x83, 0x82, 0x84, 0xff, 0x92, 0x92, 0x8c, 0xff, 0x83, 0x82, 0x84, 0xff, + 0xb4, 0xb2, 0xb4, 0xff, 0xb4, 0xb2, 0xb4, 0xff, 0x83, 0x82, 0x84, 0xff, + 0xa1, 0xa2, 0x9c, 0xff, 0x8b, 0x8b, 0x8c, 0xff, 0xa6, 0x95, 0x94, 0xff, + 0x6f, 0x6c, 0x6c, 0xff, 0x75, 0x62, 0x64, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x69, 0x55, 0x54, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x64, 0x5d, 0x5c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x6c, 0x61, 0x64, 0xff, + 0x6f, 0x6c, 0x6c, 0xff, 0x8b, 0x8b, 0x8c, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0xa4, 0x9e, 0xa4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0x81, 0x72, 0x74, 0xff, 0x75, 0x62, 0x64, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x69, 0x55, 0x54, 0xff, 0x74, 0x55, 0x4c, 0xff, + 0x69, 0x4e, 0x4c, 0xff, 0x6c, 0x4a, 0x44, 0xff, 0x5c, 0x3e, 0x34, 0xff, + 0x5c, 0x42, 0x44, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x44, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x54, 0x46, 0x3c, 0xff, 0x8f, 0x7f, 0x7c, 0xff, + 0x84, 0x77, 0x74, 0xff, 0x7e, 0x6d, 0x6c, 0xff, 0x7e, 0x6d, 0x6c, 0xff, + 0x9d, 0x8d, 0x8c, 0xff, 0x9a, 0x94, 0x94, 0xff, 0x89, 0x86, 0x84, 0xff, + 0xa1, 0x9e, 0x9c, 0xff, 0x9a, 0x94, 0x94, 0xff, 0x9d, 0x8d, 0x8c, 0xff, + 0x81, 0x72, 0x74, 0xff, 0x94, 0x8e, 0x94, 0xff, 0xbc, 0xb1, 0xb4, 0xff, + 0xbc, 0xb0, 0xac, 0xff, 0xad, 0x9a, 0x9c, 0xff, 0x94, 0x8c, 0x8c, 0xff, + 0x94, 0x8e, 0x94, 0xff, 0xb4, 0xb2, 0xb4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xbc, 0xb9, 0xbc, 0xff, 0xc8, 0xca, 0xc4, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xba, 0xb6, 0xb4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xcc, 0xc5, 0xc4, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0xbc, 0xb9, 0xbc, 0xff, 0xb4, 0xb2, 0xb4, 0xff, 0xbc, 0xb9, 0xbc, 0xff, + 0xf4, 0xea, 0xe4, 0xff, 0xdc, 0xdc, 0xdc, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0xc4, 0xba, 0xbc, 0xff, 0xbc, 0xb9, 0xbc, 0xff, 0xd5, 0xcd, 0xcc, 0xff, + 0xd4, 0xc6, 0xc4, 0xff, 0x94, 0x8c, 0x8c, 0xff, 0x90, 0x7f, 0x74, 0xff, + 0xbc, 0xb0, 0xac, 0xff, 0xfb, 0xf9, 0xec, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xfa, 0xfe, 0xdc, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x81, 0x7e, 0x7c, 0xff, + 0xac, 0xa9, 0xac, 0xff, 0xa3, 0xa3, 0xa4, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x88, 0x8a, 0x84, 0xff, 0x71, 0x72, 0x74, 0xff, 0x64, 0x6a, 0x6c, 0xff, + 0x8b, 0x8b, 0x8c, 0xff, 0x8b, 0x8b, 0x8c, 0xff, 0x81, 0x7e, 0x7c, 0xff, + 0x83, 0x82, 0x84, 0xff, 0x89, 0x86, 0x84, 0xff, 0xb4, 0xb2, 0xb4, 0xff, + 0xb4, 0xb2, 0xb4, 0xff, 0x6f, 0x6c, 0x6c, 0xff, 0x64, 0x5d, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x6c, 0x61, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x64, 0x5d, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x71, 0x72, 0x74, 0xff, 0x78, 0x77, 0x74, 0xff, 0xbc, 0xb9, 0xbc, 0xff, + 0xa1, 0x99, 0x9c, 0xff, 0xc5, 0xb7, 0xb4, 0xff, 0x96, 0x86, 0x8c, 0xff, + 0xb4, 0xb2, 0xb4, 0xff, 0x96, 0x85, 0x84, 0xff, 0x78, 0x66, 0x64, 0xff, + 0x69, 0x4e, 0x4c, 0xff, 0x6a, 0x53, 0x4c, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x69, 0x4e, 0x4c, 0xff, 0x6c, 0x4a, 0x44, 0xff, 0x5c, 0x42, 0x44, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x4e, 0x42, 0x44, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x60, 0x46, 0x3c, 0xff, 0x5c, 0x42, 0x44, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x61, 0x48, 0x44, 0xff, 0x7f, 0x72, 0x6c, 0xff, + 0x8f, 0x7f, 0x7c, 0xff, 0x84, 0x79, 0x7c, 0xff, 0x6c, 0x61, 0x64, 0xff, + 0x84, 0x79, 0x7c, 0xff, 0xad, 0x9e, 0x9e, 0xff, 0x8c, 0x81, 0x84, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0xa6, 0x95, 0x94, 0xff, 0xa4, 0x9e, 0xa4, 0xff, + 0x9e, 0x8e, 0x94, 0xff, 0x81, 0x72, 0x74, 0xff, 0x9d, 0x8d, 0x8c, 0xff, + 0xb4, 0xb2, 0xb4, 0xff, 0xb4, 0xb2, 0xb4, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0x89, 0x86, 0x84, 0xff, 0xb1, 0xaa, 0xa4, 0xff, 0xbc, 0xb9, 0xbc, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xcc, 0xc5, 0xc4, 0xff, 0xe4, 0xe1, 0xe4, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xbc, 0xb9, 0xbc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xcc, 0xc5, 0xc4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xc2, 0xc2, 0xbc, 0xff, 0xbc, 0xb9, 0xbc, 0xff, + 0xc2, 0xbe, 0xbc, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xcf, 0xc6, 0xcc, 0xff, + 0xcc, 0xc5, 0xc4, 0xff, 0xae, 0xa4, 0xa4, 0xff, 0xd6, 0xd2, 0xd4, 0xff, + 0xcc, 0xc5, 0xc4, 0xff, 0xb0, 0xa3, 0x9c, 0xff, 0x81, 0x7e, 0x7c, 0xff, + 0x94, 0x8b, 0x84, 0xff, 0xe4, 0xe2, 0xd8, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfc, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf7, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf0, 0xd4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x63, 0x6a, 0x64, 0xff, 0x64, 0x6a, 0x6c, 0xff, + 0xac, 0xa9, 0xac, 0xff, 0x88, 0x8a, 0x84, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x83, 0x82, 0x84, 0xff, 0x64, 0x6a, 0x6c, 0xff, 0x63, 0x6a, 0x64, 0xff, + 0x71, 0x72, 0x74, 0xff, 0x64, 0x6a, 0x6c, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x5f, 0x62, 0x64, 0xff, 0xa1, 0x9e, 0x9c, 0xff, + 0x8b, 0x8b, 0x8c, 0xff, 0x6f, 0x6c, 0x6c, 0xff, 0x6f, 0x6c, 0x6c, 0xff, + 0x64, 0x5d, 0x5c, 0xff, 0x64, 0x5d, 0x5c, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x89, 0x86, 0x84, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x6f, 0x6c, 0x6c, 0xff, + 0x71, 0x72, 0x74, 0xff, 0x6f, 0x6c, 0x6c, 0xff, 0xa1, 0x9e, 0x9c, 0xff, + 0x8b, 0x8b, 0x8c, 0xff, 0x9c, 0x9a, 0x94, 0xff, 0x6f, 0x6c, 0x6c, 0xff, + 0x6c, 0x61, 0x64, 0xff, 0x8c, 0x81, 0x84, 0xff, 0x81, 0x7e, 0x7c, 0xff, + 0x71, 0x6a, 0x64, 0xff, 0x69, 0x55, 0x54, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x6a, 0x53, 0x4c, 0xff, 0x75, 0x56, 0x54, 0xff, 0x6c, 0x4a, 0x44, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x4e, 0x42, 0x44, 0xff, 0x60, 0x46, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, + 0x61, 0x48, 0x44, 0xff, 0x61, 0x48, 0x44, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x90, 0x7f, 0x74, 0xff, 0x84, 0x79, 0x7c, 0xff, 0x6f, 0x6c, 0x6c, 0xff, + 0x84, 0x77, 0x74, 0xff, 0x96, 0x85, 0x84, 0xff, 0x8c, 0x81, 0x84, 0xff, + 0x96, 0x85, 0x84, 0xff, 0xa1, 0x99, 0x9c, 0xff, 0x94, 0x8c, 0x8c, 0xff, + 0xa1, 0x9e, 0x9c, 0xff, 0xa4, 0x9e, 0xa4, 0xff, 0x8c, 0x81, 0x84, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0xbc, 0xb1, 0xb4, 0xff, 0xa6, 0x95, 0x94, 0xff, + 0x94, 0x8c, 0x8c, 0xff, 0xa3, 0xa3, 0xa4, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0xcc, 0xc5, 0xc4, 0xff, 0xd7, 0xd6, 0xd4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xcf, 0xc6, 0xcc, 0xff, 0xd7, 0xd6, 0xd4, 0xff, 0xc8, 0xca, 0xc4, 0xff, + 0xe4, 0xe1, 0xe4, 0xff, 0xbc, 0xb9, 0xbc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xcc, 0xc5, 0xc4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xcc, 0xc5, 0xc4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xcf, 0xc6, 0xcc, 0xff, 0xac, 0xa9, 0xac, 0xff, + 0xba, 0xb6, 0xb4, 0xff, 0xb4, 0xaa, 0xac, 0xff, 0xc4, 0xba, 0xbc, 0xff, + 0xd5, 0xcd, 0xcc, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0x8f, 0x7f, 0x7c, 0xff, + 0x94, 0x8b, 0x84, 0xff, 0xb4, 0xae, 0x9c, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x63, 0x6a, 0x64, 0xff, + 0x64, 0x6a, 0x6c, 0xff, 0x63, 0x6a, 0x64, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x63, 0x6a, 0x64, 0xff, 0x63, 0x6a, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x5d, 0x62, 0x5c, 0xff, 0x5d, 0x62, 0x5c, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x64, 0x6a, 0x6c, 0xff, 0x63, 0x66, 0x64, 0xff, 0x8b, 0x8b, 0x8c, 0xff, + 0x71, 0x72, 0x74, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x5d, 0x62, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x81, 0x7e, 0x7c, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x6f, 0x6c, 0x6c, 0xff, + 0x71, 0x72, 0x74, 0xff, 0x71, 0x6a, 0x64, 0xff, 0x64, 0x6a, 0x6c, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0x7b, 0x7a, 0x7c, 0xff, 0x78, 0x77, 0x74, 0xff, + 0x78, 0x77, 0x74, 0xff, 0x7b, 0x7a, 0x7c, 0xff, 0x96, 0x86, 0x8c, 0xff, + 0x83, 0x82, 0x84, 0xff, 0x75, 0x62, 0x64, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x69, 0x55, 0x54, 0xff, 0x69, 0x55, 0x54, 0xff, 0x69, 0x4e, 0x4c, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x61, 0x48, 0x44, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x44, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x7e, 0x6d, 0x6c, 0xff, 0x81, 0x7e, 0x7c, 0xff, 0x7e, 0x6d, 0x6c, 0xff, + 0x84, 0x79, 0x7c, 0xff, 0x96, 0x85, 0x84, 0xff, 0x7e, 0x6d, 0x6c, 0xff, + 0x81, 0x72, 0x74, 0xff, 0x8c, 0x81, 0x84, 0xff, 0x94, 0x8c, 0x8c, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0xad, 0x9e, 0x9e, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0x84, 0x79, 0x7c, 0xff, 0x96, 0x85, 0x84, 0xff, 0x9e, 0x8e, 0x94, 0xff, + 0x8c, 0x81, 0x84, 0xff, 0x9a, 0x94, 0x94, 0xff, 0xa3, 0xa3, 0xa4, 0xff, + 0xba, 0xb6, 0xb4, 0xff, 0xcc, 0xc5, 0xc4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xd6, 0xd2, 0xd4, 0xff, 0xd7, 0xd6, 0xd4, 0xff, + 0xd6, 0xd2, 0xd4, 0xff, 0xdc, 0xdc, 0xdc, 0xff, 0xd9, 0xd4, 0xcc, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xcc, 0xc5, 0xc4, 0xff, + 0xc8, 0xca, 0xc4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0xbc, 0xb1, 0xb4, 0xff, 0xba, 0xb6, 0xb4, 0xff, 0xbc, 0xb1, 0xb4, 0xff, + 0xd6, 0xd2, 0xd4, 0xff, 0xd9, 0xd4, 0xcc, 0xff, 0x9c, 0x93, 0x8c, 0xff, + 0x88, 0x8a, 0x84, 0xff, 0x8f, 0x86, 0x7c, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfb, 0xfe, 0xec, 0xff, 0xfb, 0xfe, 0xec, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfc, 0xf9, 0xe4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xfc, 0xf9, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xfc, 0xf9, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf0, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x64, 0x6a, 0x6c, 0xff, + 0x88, 0x8a, 0x84, 0xff, 0x64, 0x6a, 0x6c, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x6f, 0x6c, 0x6c, 0xff, 0x71, 0x72, 0x74, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x6f, 0x6c, 0x6c, 0xff, 0x5d, 0x62, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x6f, 0x6c, 0x6c, 0xff, 0x71, 0x6a, 0x64, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x6c, 0x66, 0x6c, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x64, 0x6a, 0x6c, 0xff, 0x83, 0x82, 0x84, 0xff, + 0x7b, 0x7a, 0x7c, 0xff, 0x71, 0x72, 0x6c, 0xff, 0x78, 0x77, 0x74, 0xff, + 0x6f, 0x6c, 0x6c, 0xff, 0x6f, 0x6c, 0x6c, 0xff, 0x6c, 0x61, 0x64, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x69, 0x4e, 0x4c, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x5c, 0x42, 0x44, 0xff, 0x61, 0x48, 0x44, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x69, 0x4e, 0x4c, 0xff, 0x5c, 0x42, 0x3c, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x4e, 0x42, 0x44, 0xff, 0x60, 0x46, 0x3c, 0xff, + 0x75, 0x62, 0x64, 0xff, 0x96, 0x85, 0x84, 0xff, 0x81, 0x7e, 0x7c, 0xff, + 0x7e, 0x6d, 0x6c, 0xff, 0x94, 0x8b, 0x84, 0xff, 0x96, 0x86, 0x8c, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x8f, 0x7f, 0x7c, 0xff, 0x9d, 0x8d, 0x8c, 0xff, + 0x89, 0x86, 0x84, 0xff, 0x9e, 0x8e, 0x94, 0xff, 0x9c, 0x9a, 0x94, 0xff, + 0xb4, 0xaa, 0xac, 0xff, 0x94, 0x8c, 0x8c, 0xff, 0xa6, 0x95, 0x94, 0xff, + 0x94, 0x8c, 0x8c, 0xff, 0x8b, 0x8b, 0x8c, 0xff, 0xa4, 0x9e, 0xa4, 0xff, + 0xb3, 0xae, 0xac, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xc2, 0xc2, 0xbc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xd7, 0xd6, 0xd4, 0xff, + 0xcf, 0xc6, 0xcc, 0xff, 0xdc, 0xdc, 0xdc, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0xd6, 0xd2, 0xd4, 0xff, 0xc8, 0xca, 0xc4, 0xff, 0xcc, 0xc5, 0xc4, 0xff, + 0xcc, 0xc5, 0xc4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xcf, 0xc6, 0xcc, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xcf, 0xc6, 0xcc, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0xb3, 0xae, 0xac, 0xff, 0xae, 0xa4, 0xa4, 0xff, 0xbc, 0xb1, 0xb4, 0xff, + 0xd4, 0xc6, 0xc4, 0xff, 0xd6, 0xd2, 0xd4, 0xff, 0xc6, 0xb1, 0xb4, 0xff, + 0x94, 0x8c, 0x8c, 0xff, 0x9c, 0x9a, 0x94, 0xff, 0xfb, 0xf9, 0xec, 0xff, + 0xfb, 0xf9, 0xec, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x64, 0x6a, 0x6c, 0xff, + 0x71, 0x72, 0x74, 0xff, 0x71, 0x72, 0x74, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x64, 0x6a, 0x6c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x8b, 0x8b, 0x8c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x6c, 0x66, 0x6c, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x55, 0x55, 0x54, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x64, 0x6a, 0x6c, 0xff, 0x71, 0x72, 0x74, 0xff, + 0x64, 0x6a, 0x6c, 0xff, 0x64, 0x6a, 0x6c, 0xff, 0x8c, 0x81, 0x84, 0xff, + 0x6c, 0x61, 0x64, 0xff, 0x69, 0x55, 0x54, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x69, 0x55, 0x54, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x72, 0x5b, 0x54, 0xff, + 0x5d, 0x5a, 0x54, 0xff, 0x61, 0x48, 0x44, 0xff, 0x5c, 0x42, 0x44, 0xff, + 0x5c, 0x42, 0x3c, 0xff, 0x53, 0x41, 0x3c, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x58, 0x49, 0x4c, 0xff, 0x6f, 0x6c, 0x6c, 0xff, 0x96, 0x85, 0x84, 0xff, + 0x8e, 0x7a, 0x7c, 0xff, 0x8c, 0x81, 0x84, 0xff, 0xb1, 0xaa, 0xa4, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0x8c, 0x81, 0x84, 0xff, 0x70, 0x5e, 0x5c, 0xff, + 0x71, 0x72, 0x74, 0xff, 0x8f, 0x7f, 0x7c, 0xff, 0x9a, 0x94, 0x94, 0xff, + 0xa6, 0x95, 0x94, 0xff, 0xa6, 0x95, 0x94, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0xb4, 0xaa, 0xac, 0xff, 0x94, 0x8e, 0x94, 0xff, 0xa1, 0x9e, 0x9c, 0xff, + 0xba, 0xb6, 0xb4, 0xff, 0xba, 0xb6, 0xb4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xcc, 0xc5, 0xc4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xcc, 0xc5, 0xc4, 0xff, 0xdc, 0xdc, 0xdc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xd6, 0xd2, 0xd4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xd7, 0xd6, 0xd4, 0xff, 0xdc, 0xdc, 0xdc, 0xff, 0xdc, 0xdc, 0xdc, 0xff, + 0xcc, 0xc5, 0xc4, 0xff, 0xcc, 0xc5, 0xc4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xa1, 0x99, 0x9c, 0xff, 0xb4, 0xaa, 0xac, 0xff, + 0xcc, 0xbe, 0xc4, 0xff, 0xcf, 0xc6, 0xcc, 0xff, 0xd7, 0xd6, 0xd4, 0xff, + 0xa1, 0x9e, 0x9c, 0xff, 0x92, 0x92, 0x8c, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xfb, 0xfe, 0xec, 0xff, 0xfb, 0xfe, 0xec, 0xff, 0xfb, 0xfe, 0xec, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xfa, 0xfe, 0xdc, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x63, 0x6a, 0x64, 0xff, 0x63, 0x6a, 0x64, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x5d, 0x62, 0x5c, 0xff, 0x63, 0x6a, 0x64, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x83, 0x82, 0x84, 0xff, 0x81, 0x7e, 0x7c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x64, 0x6a, 0x6c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x64, 0x6a, 0x6c, 0xff, 0x6f, 0x6c, 0x6c, 0xff, + 0x6f, 0x6c, 0x6c, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x71, 0x72, 0x6c, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x94, 0x8c, 0x8c, 0xff, + 0x81, 0x7e, 0x7c, 0xff, 0x64, 0x5d, 0x5c, 0xff, 0x64, 0x5d, 0x5c, 0xff, + 0x5d, 0x5a, 0x54, 0xff, 0x5d, 0x5a, 0x54, 0xff, 0x72, 0x62, 0x5c, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x53, 0x41, 0x3c, 0xff, 0x61, 0x48, 0x44, 0xff, 0x61, 0x48, 0x44, 0xff, + 0x69, 0x55, 0x54, 0xff, 0x6f, 0x6c, 0x6c, 0xff, 0x8e, 0x7a, 0x7c, 0xff, + 0x78, 0x77, 0x74, 0xff, 0x9d, 0x8d, 0x8c, 0xff, 0xae, 0xa4, 0xa4, 0xff, + 0xbc, 0xb1, 0xb4, 0xff, 0xcc, 0xc5, 0xc4, 0xff, 0x94, 0x8c, 0x8c, 0xff, + 0x75, 0x62, 0x64, 0xff, 0x64, 0x5d, 0x5c, 0xff, 0x8c, 0x81, 0x84, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0x94, 0x8c, 0x8c, 0xff, 0x9a, 0x94, 0x94, 0xff, + 0xba, 0xb6, 0xb4, 0xff, 0xba, 0xb6, 0xb4, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0xbc, 0xb9, 0xbc, 0xff, 0xba, 0xb6, 0xb4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0xd6, 0xd2, 0xd4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xd6, 0xd2, 0xd4, 0xff, + 0xd7, 0xd6, 0xd4, 0xff, 0xd7, 0xd6, 0xd4, 0xff, 0xd6, 0xd2, 0xd4, 0xff, + 0xd6, 0xd2, 0xd4, 0xff, 0xcc, 0xc5, 0xc4, 0xff, 0xcc, 0xc5, 0xc4, 0xff, + 0xcf, 0xc6, 0xcc, 0xff, 0xa3, 0xa3, 0xa4, 0xff, 0xba, 0xb6, 0xb4, 0xff, + 0xc2, 0xbe, 0xbc, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xcf, 0xc6, 0xcc, 0xff, + 0xc2, 0xbe, 0xbc, 0xff, 0xcf, 0xc6, 0xcc, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0xbc, 0xb1, 0xb4, 0xff, 0xcf, 0xc6, 0xcc, 0xff, 0xcc, 0xbd, 0xbc, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0x9c, 0x93, 0x8c, 0xff, 0xf2, 0xe9, 0xdc, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x5d, 0x62, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x63, 0x6a, 0x64, 0xff, 0x94, 0x8e, 0x94, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x5d, 0x62, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x63, 0x66, 0x64, 0xff, 0x6f, 0x6c, 0x6c, 0xff, + 0x64, 0x6a, 0x6c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x78, 0x77, 0x74, 0xff, + 0x88, 0x8a, 0x84, 0xff, 0x6f, 0x6c, 0x6c, 0xff, 0x64, 0x5d, 0x5c, 0xff, + 0x64, 0x5d, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x5d, 0x62, 0x5c, 0xff, + 0x64, 0x5d, 0x5c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x4e, 0x42, 0x44, 0xff, + 0x61, 0x48, 0x44, 0xff, 0x58, 0x49, 0x4c, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x58, 0x49, 0x4c, 0xff, 0x6c, 0x61, 0x64, 0xff, 0x8f, 0x7f, 0x7c, 0xff, + 0x8c, 0x81, 0x84, 0xff, 0x89, 0x86, 0x84, 0xff, 0xa3, 0xa3, 0xa4, 0xff, + 0xba, 0xb6, 0xb4, 0xff, 0xcc, 0xc5, 0xc4, 0xff, 0xd4, 0xc6, 0xc4, 0xff, + 0x8c, 0x81, 0x84, 0xff, 0x69, 0x55, 0x54, 0xff, 0x75, 0x62, 0x64, 0xff, + 0x94, 0x8c, 0x8c, 0xff, 0x89, 0x86, 0x84, 0xff, 0xa6, 0x95, 0x94, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0xa1, 0x9e, 0x9c, 0xff, 0xa3, 0xa3, 0xa4, 0xff, + 0xb1, 0xaa, 0xa4, 0xff, 0xc4, 0xbe, 0xc4, 0xff, 0xba, 0xb6, 0xb4, 0xff, + 0xbc, 0xb9, 0xbc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xc2, 0xbe, 0xbc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xcc, 0xc5, 0xc4, 0xff, + 0xcc, 0xc5, 0xc4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0x8b, 0x8b, 0x8c, 0xff, 0x7b, 0x7a, 0x7c, 0xff, 0x8b, 0x8b, 0x8c, 0xff, + 0xa3, 0xa3, 0xa4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xc4, 0xbe, 0xc4, 0xff, + 0xc2, 0xbe, 0xbc, 0xff, 0xd6, 0xd2, 0xd4, 0xff, 0xb4, 0xaa, 0xac, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0xc5, 0xb7, 0xb4, 0xff, 0xd6, 0xd2, 0xd4, 0xff, + 0xd7, 0xd6, 0xd4, 0xff, 0x9c, 0x9a, 0x94, 0xff, 0xe2, 0xdc, 0xcc, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xfb, 0xfe, 0xec, 0xff, 0xfb, 0xfe, 0xec, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x5d, 0x62, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x81, 0x7e, 0x7c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x5d, 0x62, 0x5c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x5d, 0x62, 0x5c, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x63, 0x66, 0x64, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x55, 0x55, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x5d, 0x5a, 0x54, 0xff, 0x5d, 0x62, 0x5c, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x6f, 0x6c, 0x6c, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x64, 0x5d, 0x5c, 0xff, 0x69, 0x55, 0x54, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x4e, 0x42, 0x44, 0xff, 0x69, 0x4e, 0x4c, 0xff, 0x70, 0x5e, 0x5c, 0xff, + 0x64, 0x5d, 0x5c, 0xff, 0x6c, 0x61, 0x64, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x8c, 0x81, 0x84, 0xff, 0x81, 0x7e, 0x7c, 0xff, 0x8b, 0x8b, 0x8c, 0xff, + 0xbc, 0xb0, 0xac, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xd5, 0xcd, 0xcc, 0xff, 0x96, 0x86, 0x8c, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x81, 0x72, 0x74, 0xff, 0x9c, 0x9a, 0x94, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0x94, 0x8e, 0x94, 0xff, 0x81, 0x7e, 0x7c, 0xff, 0xcc, 0xc5, 0xc4, 0xff, + 0xb3, 0xae, 0xac, 0xff, 0xc2, 0xbe, 0xbc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xc2, 0xbe, 0xbc, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xcf, 0xc6, 0xcc, 0xff, 0xba, 0xb6, 0xb4, 0xff, + 0xc2, 0xbe, 0xbc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xd7, 0xd6, 0xd4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xb4, 0xb2, 0xb4, 0xff, 0xc2, 0xbe, 0xbc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xc5, 0xb7, 0xb4, 0xff, 0xc4, 0xba, 0xbc, 0xff, 0xd6, 0xd2, 0xd4, 0xff, + 0x9e, 0x8e, 0x94, 0xff, 0xbc, 0xb9, 0xbc, 0xff, 0xd5, 0xcd, 0xcc, 0xff, + 0xdc, 0xdc, 0xdc, 0xff, 0xd9, 0xd4, 0xcc, 0xff, 0xe4, 0xe2, 0xd8, 0xff, + 0xfb, 0xfe, 0xec, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xfa, 0xfe, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x64, 0x6a, 0x6c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x5d, 0x62, 0x5c, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x63, 0x66, 0x64, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x55, 0x55, 0x54, 0xff, 0x5d, 0x5a, 0x54, 0xff, + 0x5d, 0x5a, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x6c, 0x61, 0x64, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x6f, 0x6c, 0x6c, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x55, 0x55, 0x54, 0xff, 0x58, 0x49, 0x4c, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x6b, 0x56, 0x5c, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0x6f, 0x6c, 0x6c, 0xff, 0x64, 0x5d, 0x5c, 0xff, + 0x81, 0x7e, 0x7c, 0xff, 0x81, 0x7e, 0x7c, 0xff, 0x81, 0x7e, 0x7c, 0xff, + 0xb1, 0xaa, 0xa4, 0xff, 0xbc, 0xb0, 0xac, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0xe4, 0xce, 0xcc, 0xff, 0xd5, 0xcd, 0xcc, 0xff, 0x81, 0x72, 0x74, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0xa1, 0x99, 0x9c, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0xa3, 0xa3, 0xa4, 0xff, 0xa1, 0x99, 0x9c, 0xff, 0xc4, 0xbe, 0xc4, 0xff, + 0xb4, 0xb2, 0xb4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xba, 0xb6, 0xb4, 0xff, + 0xcc, 0xc5, 0xc4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xd6, 0xd2, 0xd4, 0xff, 0xd6, 0xd2, 0xd4, 0xff, 0xac, 0xa9, 0xac, 0xff, + 0xa3, 0xa3, 0xa4, 0xff, 0xbc, 0xb9, 0xbc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xd6, 0xd2, 0xd4, 0xff, 0xd7, 0xd6, 0xd4, 0xff, 0xe4, 0xe1, 0xe4, 0xff, + 0xec, 0xea, 0xec, 0xff, 0xba, 0xb6, 0xb4, 0xff, 0xc4, 0xbe, 0xc4, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xbc, 0xb1, 0xb4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0xb4, 0xaa, 0xac, 0xff, 0xbc, 0xaa, 0xac, 0xff, 0xcc, 0xbe, 0xc4, 0xff, + 0xd5, 0xcd, 0xcc, 0xff, 0xd8, 0xdc, 0xd4, 0xff, 0xe8, 0xe7, 0xe4, 0xff, + 0xfb, 0xf9, 0xec, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfb, 0xfe, 0xec, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x5d, 0x62, 0x5c, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x63, 0x66, 0x64, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x5d, 0x62, 0x5c, 0xff, 0x63, 0x66, 0x64, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x6c, 0x61, 0x64, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x5d, 0x5a, 0x54, 0xff, 0x5d, 0x5a, 0x54, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x55, 0x52, 0x4c, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x71, 0x6a, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x64, 0x5d, 0x5c, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x64, 0x4e, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x64, 0x5d, 0x5c, 0xff, 0x78, 0x77, 0x74, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x71, 0x72, 0x74, 0xff, 0x78, 0x77, 0x74, 0xff, 0x78, 0x77, 0x74, 0xff, + 0xa1, 0x9e, 0x9c, 0xff, 0xa1, 0x99, 0x9c, 0xff, 0xb1, 0xaa, 0xa4, 0xff, + 0xd5, 0xcd, 0xcc, 0xff, 0xe6, 0xd6, 0xd6, 0xff, 0xcc, 0xbd, 0xbc, 0xff, + 0x64, 0x5d, 0x5c, 0xff, 0x84, 0x77, 0x74, 0xff, 0x9e, 0x8b, 0x84, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0x89, 0x86, 0x84, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0xdc, 0xdc, 0xdc, 0xff, 0xa3, 0xa3, 0xa4, 0xff, 0xb4, 0xb2, 0xb4, 0xff, + 0xc2, 0xbe, 0xbc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xd9, 0xd4, 0xcc, 0xff, 0xa3, 0xa3, 0xa4, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0xc2, 0xbe, 0xbc, 0xff, 0xcc, 0xc5, 0xc4, 0xff, + 0xd7, 0xd6, 0xd4, 0xff, 0xdc, 0xdc, 0xdc, 0xff, 0xe8, 0xe7, 0xe4, 0xff, + 0xe8, 0xe7, 0xe4, 0xff, 0xdc, 0xdc, 0xdc, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0xd5, 0xcd, 0xcc, 0xff, 0xc2, 0xbe, 0xbc, 0xff, 0xd5, 0xcd, 0xcc, 0xff, + 0xcf, 0xc6, 0xcc, 0xff, 0xa4, 0x9e, 0xa4, 0xff, 0xc5, 0xb7, 0xb4, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xf2, 0xe9, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xfb, 0xfe, 0xec, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x55, 0x52, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x5d, 0x62, 0x5c, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x6c, 0x61, 0x64, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x64, 0x5d, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x71, 0x6a, 0x64, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x5d, 0x62, 0x5c, 0xff, 0x63, 0x6a, 0x64, 0xff, 0x78, 0x77, 0x74, 0xff, + 0x8b, 0x8b, 0x8c, 0xff, 0x83, 0x82, 0x84, 0xff, 0x8b, 0x8b, 0x8c, 0xff, + 0xcc, 0xc5, 0xc4, 0xff, 0xd7, 0xd6, 0xd4, 0xff, 0xd6, 0xd2, 0xd4, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0x84, 0x79, 0x7c, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x96, 0x85, 0x84, 0xff, 0x8b, 0x8b, 0x8c, 0xff, 0x8b, 0x8b, 0x8c, 0xff, + 0xe4, 0xe1, 0xe4, 0xff, 0xa1, 0x99, 0x9c, 0xff, 0xba, 0xb6, 0xb4, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xcc, 0xc5, 0xc4, 0xff, 0xd6, 0xd2, 0xd4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xe8, 0xe7, 0xe4, 0xff, 0xd7, 0xd6, 0xd4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xe4, 0xde, 0xdc, 0xff, 0xe4, 0xe1, 0xe4, 0xff, + 0xf4, 0xf2, 0xf4, 0xff, 0xe8, 0xe7, 0xe4, 0xff, 0xcf, 0xc6, 0xcc, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xd6, 0xd2, 0xd4, 0xff, 0xcf, 0xc6, 0xcc, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xc4, 0xba, 0xbc, 0xff, 0xac, 0xa9, 0xac, 0xff, + 0xcc, 0xc5, 0xc4, 0xff, 0xd9, 0xd4, 0xcc, 0xff, 0xe8, 0xe7, 0xe4, 0xff, + 0xfb, 0xf9, 0xec, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xfb, 0xfe, 0xec, 0xff, + 0xfb, 0xfe, 0xec, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4c, 0x52, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x5d, 0x62, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x5d, 0x62, 0x5c, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x5d, 0x62, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x5d, 0x62, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x6c, 0x61, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x55, 0x55, 0x54, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x6c, 0x61, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x6c, 0x66, 0x6c, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x6f, 0x6c, 0x6c, 0xff, 0x7b, 0x7a, 0x7c, 0xff, + 0x89, 0x86, 0x84, 0xff, 0x83, 0x82, 0x84, 0xff, 0x8b, 0x8b, 0x8c, 0xff, + 0xc2, 0xbe, 0xbc, 0xff, 0xd6, 0xd2, 0xd4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xbc, 0xb1, 0xb4, 0xff, 0xae, 0xa4, 0xa4, 0xff, 0x84, 0x79, 0x7c, 0xff, + 0x6c, 0x61, 0x64, 0xff, 0x81, 0x72, 0x74, 0xff, 0x96, 0x86, 0x8c, 0xff, + 0xa1, 0x9e, 0x9c, 0xff, 0x9a, 0x94, 0x94, 0xff, 0xa1, 0x9e, 0x9c, 0xff, + 0xdc, 0xdc, 0xdc, 0xff, 0xd6, 0xd2, 0xd4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xc8, 0xca, 0xc4, 0xff, 0xe4, 0xe1, 0xe4, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xd7, 0xd6, 0xd4, 0xff, 0xd6, 0xd2, 0xd4, 0xff, + 0xd6, 0xd2, 0xd4, 0xff, 0xdc, 0xdc, 0xdc, 0xff, 0xdc, 0xdc, 0xdc, 0xff, + 0xec, 0xea, 0xec, 0xff, 0xec, 0xea, 0xec, 0xff, 0xd7, 0xd6, 0xd4, 0xff, + 0xcc, 0xc5, 0xc4, 0xff, 0xcc, 0xc5, 0xc4, 0xff, 0xd7, 0xd6, 0xd4, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xc2, 0xbe, 0xbc, 0xff, 0xbc, 0xb9, 0xbc, 0xff, + 0xc2, 0xbe, 0xbc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xd9, 0xd4, 0xcc, 0xff, + 0xd8, 0xdc, 0xd4, 0xff, 0xfb, 0xf9, 0xec, 0xff, 0xfb, 0xf9, 0xec, 0xff, + 0xfb, 0xfe, 0xec, 0xff, 0xfb, 0xfe, 0xec, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xfb, 0xfe, 0xec, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x5d, 0x62, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x6f, 0x6c, 0x6c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x5d, 0x62, 0x5c, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x71, 0x72, 0x74, 0xff, 0x78, 0x77, 0x74, 0xff, + 0x71, 0x72, 0x74, 0xff, 0x71, 0x72, 0x6c, 0xff, 0x7b, 0x7a, 0x7c, 0xff, + 0xa1, 0x99, 0x9c, 0xff, 0xa3, 0xa3, 0xa4, 0xff, 0x81, 0x7e, 0x7c, 0xff, + 0xa4, 0x9e, 0xa4, 0xff, 0xba, 0xb6, 0xb4, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0x8f, 0x7f, 0x7c, 0xff, 0x6c, 0x61, 0x64, 0xff, 0x84, 0x79, 0x7c, 0xff, + 0x96, 0x85, 0x84, 0xff, 0x8b, 0x8b, 0x8c, 0xff, 0x9a, 0x94, 0x94, 0xff, + 0xac, 0xa9, 0xac, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0xcc, 0xc5, 0xc4, 0xff, 0xd6, 0xd2, 0xd4, 0xff, 0xd7, 0xd6, 0xd4, 0xff, + 0xbc, 0xb9, 0xbc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xdc, 0xdc, 0xdc, 0xff, + 0xcc, 0xc5, 0xc4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xdc, 0xdc, 0xdc, 0xff, + 0xd8, 0xdc, 0xd4, 0xff, 0xdc, 0xdc, 0xdc, 0xff, 0xd7, 0xd6, 0xd4, 0xff, + 0xcc, 0xc5, 0xc4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xcc, 0xc5, 0xc4, 0xff, 0xc2, 0xc2, 0xbc, 0xff, 0xcf, 0xc6, 0xcc, 0xff, + 0xbc, 0xb6, 0xac, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xc8, 0xca, 0xc4, 0xff, + 0xc8, 0xca, 0xc4, 0xff, 0xf2, 0xf0, 0xec, 0xff, 0xf2, 0xf0, 0xec, 0xff, + 0xfb, 0xfe, 0xec, 0xff, 0xfb, 0xfe, 0xec, 0xff, 0xfb, 0xfe, 0xec, 0xff, + 0xfb, 0xfe, 0xec, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xfa, 0xfe, 0xe4, 0xff, + 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x5d, 0x62, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x5d, 0x62, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x5d, 0x62, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x64, 0x6a, 0x6c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x63, 0x66, 0x64, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x63, 0x66, 0x64, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x71, 0x72, 0x74, 0xff, 0x64, 0x6a, 0x6c, 0xff, 0x6f, 0x6c, 0x6c, 0xff, + 0x7b, 0x7a, 0x7c, 0xff, 0x81, 0x7e, 0x7c, 0xff, 0x78, 0x77, 0x74, 0xff, + 0x83, 0x82, 0x84, 0xff, 0xa3, 0xa3, 0xa4, 0xff, 0x8b, 0x8b, 0x8c, 0xff, + 0xa3, 0xa3, 0xa4, 0xff, 0x6c, 0x61, 0x64, 0xff, 0x6c, 0x61, 0x64, 0xff, + 0x6f, 0x6c, 0x6c, 0xff, 0xc6, 0xb1, 0xb4, 0xff, 0xb4, 0xb2, 0xb4, 0xff, + 0xa1, 0x9e, 0x9c, 0xff, 0xb3, 0xae, 0xac, 0xff, 0x9a, 0x94, 0x94, 0xff, + 0xba, 0xb6, 0xb4, 0xff, 0xd7, 0xd6, 0xd4, 0xff, 0xdc, 0xdc, 0xdc, 0xff, + 0xdc, 0xdc, 0xdc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xd7, 0xd6, 0xd4, 0xff, + 0xcf, 0xc6, 0xcc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xd6, 0xd2, 0xd4, 0xff, + 0xd6, 0xd2, 0xd4, 0xff, 0xdc, 0xdc, 0xdc, 0xff, 0xd6, 0xd2, 0xd4, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xd7, 0xd6, 0xd4, 0xff, 0xcf, 0xc6, 0xcc, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xcf, 0xc6, 0xcc, 0xff, 0xbc, 0xb9, 0xbc, 0xff, + 0x8b, 0x8b, 0x8c, 0xff, 0xbc, 0xb9, 0xbc, 0xff, 0xd9, 0xd4, 0xcc, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xd8, 0xdc, 0xd4, 0xff, 0xfc, 0xfe, 0xf4, 0xff, + 0xfb, 0xfe, 0xec, 0xff, 0xfa, 0xfe, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xfb, 0xfe, 0xec, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x5d, 0x62, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x5d, 0x62, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x5d, 0x62, 0x5c, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x5d, 0x62, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x64, 0x6a, 0x6c, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x63, 0x6a, 0x64, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x64, 0x5d, 0x5c, 0xff, 0x5d, 0x62, 0x5c, 0xff, + 0x71, 0x72, 0x74, 0xff, 0x6f, 0x6c, 0x6c, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x71, 0x72, 0x74, 0xff, 0x81, 0x7e, 0x7c, 0xff, 0x7b, 0x7a, 0x7c, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0x84, 0x79, 0x7c, 0xff, 0x64, 0x5d, 0x5c, 0xff, + 0x6b, 0x56, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x6f, 0x6c, 0x6c, 0xff, + 0x8c, 0x86, 0x8c, 0xff, 0xac, 0xa9, 0xac, 0xff, 0x9a, 0x94, 0x94, 0xff, + 0xac, 0xa9, 0xac, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xcc, 0xc5, 0xc4, 0xff, + 0xe4, 0xe1, 0xe4, 0xff, 0xd7, 0xd6, 0xd4, 0xff, 0xd7, 0xd6, 0xd4, 0xff, + 0xd7, 0xd6, 0xd4, 0xff, 0xd6, 0xd2, 0xd4, 0xff, 0xdc, 0xdc, 0xdc, 0xff, + 0xdc, 0xdc, 0xdc, 0xff, 0xdc, 0xdc, 0xdc, 0xff, 0xe4, 0xe1, 0xe4, 0xff, + 0xd7, 0xd6, 0xd4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xd7, 0xd6, 0xd4, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xba, 0xb6, 0xb4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xa1, 0xa2, 0x9c, 0xff, 0xbc, 0xb6, 0xac, 0xff, 0xba, 0xb6, 0xb4, 0xff, + 0xd8, 0xdc, 0xd4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xf2, 0xf0, 0xec, 0xff, + 0xfb, 0xf9, 0xec, 0xff, 0xfb, 0xf9, 0xec, 0xff, 0xfb, 0xfe, 0xec, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xfb, 0xf9, 0xec, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xfb, 0xf9, 0xec, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x5d, 0x62, 0x5c, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x63, 0x6a, 0x64, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x5d, 0x62, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x6f, 0x6c, 0x6c, 0xff, 0x64, 0x6a, 0x6c, 0xff, 0x5d, 0x62, 0x5c, 0xff, + 0x64, 0x6a, 0x6c, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x71, 0x6a, 0x64, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0x94, 0x8c, 0x8c, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0x84, 0x79, 0x7c, 0xff, 0x81, 0x7e, 0x7c, 0xff, + 0xac, 0xa9, 0xac, 0xff, 0xa3, 0xa3, 0xa4, 0xff, 0x63, 0x66, 0x64, 0xff, + 0xb3, 0xae, 0xac, 0xff, 0xc2, 0xbe, 0xbc, 0xff, 0xa3, 0xa3, 0xa4, 0xff, + 0xc2, 0xbe, 0xbc, 0xff, 0xc4, 0xbe, 0xc4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xd6, 0xd2, 0xd4, 0xff, 0xd6, 0xd2, 0xd4, 0xff, 0xdc, 0xdc, 0xdc, 0xff, + 0xe4, 0xe1, 0xe4, 0xff, 0xe4, 0xe2, 0xd8, 0xff, 0xe4, 0xe1, 0xe4, 0xff, + 0xdc, 0xdc, 0xdc, 0xff, 0xd7, 0xd6, 0xd4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0xa1, 0x9e, 0x9c, 0xff, 0xb4, 0xb2, 0xb4, 0xff, 0xb3, 0xae, 0xac, 0xff, + 0xc8, 0xca, 0xc4, 0xff, 0xe4, 0xe2, 0xd8, 0xff, 0xe8, 0xe7, 0xe4, 0xff, + 0xfb, 0xf9, 0xec, 0xff, 0xfb, 0xf9, 0xec, 0xff, 0xe4, 0xe2, 0xd8, 0xff, + 0xc9, 0xc0, 0xb4, 0xff, 0xb0, 0xa3, 0x9c, 0xff, 0xb1, 0xa3, 0x94, 0xff, + 0xbc, 0xa4, 0x9c, 0xff, 0xc0, 0xaa, 0x9c, 0xff, 0xd6, 0xc5, 0xbc, 0xff, + 0xcc, 0xbe, 0xac, 0xff, 0xd9, 0xcc, 0xbc, 0xff, 0xe2, 0xdc, 0xcc, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf7, 0xdc, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x52, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x5d, 0x62, 0x5c, 0xff, 0x5d, 0x62, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x63, 0x66, 0x64, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x5d, 0x62, 0x5c, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x63, 0x66, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x5d, 0x62, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x8b, 0x8b, 0x8c, 0xff, 0xa1, 0x9e, 0x9c, 0xff, 0xbc, 0xb1, 0xb4, 0xff, + 0xb4, 0xb2, 0xb4, 0xff, 0x8b, 0x8b, 0x8c, 0xff, 0x81, 0x7e, 0x7c, 0xff, + 0xa1, 0x9e, 0x9c, 0xff, 0xba, 0xb6, 0xb4, 0xff, 0x64, 0x6a, 0x6c, 0xff, + 0x83, 0x82, 0x84, 0xff, 0x8b, 0x8b, 0x8c, 0xff, 0xa1, 0x99, 0x9c, 0xff, + 0xac, 0xa9, 0xac, 0xff, 0xba, 0xb6, 0xb4, 0xff, 0xb4, 0xb2, 0xb4, 0xff, + 0xc2, 0xbe, 0xbc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xdc, 0xdc, 0xdc, 0xff, 0xdc, 0xdc, 0xdc, 0xff, 0xec, 0xea, 0xec, 0xff, + 0xe8, 0xe7, 0xe4, 0xff, 0xdc, 0xdc, 0xdc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xbc, 0xb9, 0xbc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xc2, 0xc2, 0xbc, 0xff, + 0xa3, 0xa3, 0xa4, 0xff, 0xb1, 0xaa, 0xa4, 0xff, 0xb3, 0xae, 0xac, 0xff, + 0xba, 0xb6, 0xb4, 0xff, 0xd9, 0xd4, 0xcc, 0xff, 0xe8, 0xe7, 0xe4, 0xff, + 0xd9, 0xd4, 0xcc, 0xff, 0xd7, 0xcc, 0xc4, 0xff, 0xbc, 0xb6, 0xac, 0xff, + 0xb0, 0xa3, 0x9c, 0xff, 0xc4, 0xb2, 0xac, 0xff, 0xbc, 0xa4, 0x9c, 0xff, + 0xa4, 0x85, 0x84, 0xff, 0x9e, 0x8b, 0x84, 0xff, 0xa7, 0x94, 0x84, 0xff, + 0x9c, 0x8e, 0x7c, 0xff, 0xa9, 0x9b, 0x8c, 0xff, 0xb4, 0xaa, 0x94, 0xff, + 0xbc, 0xb6, 0xac, 0xff, 0xda, 0xd4, 0xc4, 0xff, 0xf2, 0xe9, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x5d, 0x62, 0x5c, 0xff, 0x5d, 0x62, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x64, 0x6a, 0x6c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x6f, 0x6c, 0x6c, 0xff, 0x6f, 0x6c, 0x6c, 0xff, 0x81, 0x7e, 0x7c, 0xff, + 0xba, 0xb6, 0xb4, 0xff, 0xa4, 0x9e, 0xa4, 0xff, 0x89, 0x86, 0x84, 0xff, + 0xa1, 0x9e, 0x9c, 0xff, 0xa3, 0xa3, 0xa4, 0xff, 0x6f, 0x6c, 0x6c, 0xff, + 0x88, 0x8a, 0x84, 0xff, 0xcc, 0xc5, 0xc4, 0xff, 0x9a, 0x94, 0x94, 0xff, + 0x89, 0x86, 0x84, 0xff, 0x9a, 0x94, 0x94, 0xff, 0xbc, 0xb9, 0xbc, 0xff, + 0xbc, 0xb9, 0xbc, 0xff, 0x83, 0x82, 0x84, 0xff, 0x94, 0x8e, 0x94, 0xff, + 0xd7, 0xd6, 0xd4, 0xff, 0xf4, 0xf2, 0xf4, 0xff, 0xd6, 0xd2, 0xd4, 0xff, + 0xdc, 0xdc, 0xdc, 0xff, 0xe4, 0xe1, 0xe4, 0xff, 0xd8, 0xdc, 0xd4, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xd6, 0xd2, 0xd4, 0xff, + 0xa1, 0x99, 0x9c, 0xff, 0xb3, 0xae, 0xac, 0xff, 0xbc, 0xb6, 0xac, 0xff, + 0xb1, 0xaa, 0xa4, 0xff, 0xc2, 0xbe, 0xbc, 0xff, 0xe4, 0xe2, 0xd8, 0xff, + 0xf2, 0xf0, 0xec, 0xff, 0xd8, 0xdc, 0xd4, 0xff, 0xd5, 0xcd, 0xcc, 0xff, + 0xcc, 0xbd, 0xbc, 0xff, 0xef, 0xe2, 0xdc, 0xff, 0xc6, 0xb1, 0xb4, 0xff, + 0xac, 0x8d, 0x8c, 0xff, 0xac, 0x8d, 0x84, 0xff, 0xa4, 0x89, 0x7c, 0xff, + 0x9c, 0x88, 0x7c, 0xff, 0x9c, 0x8e, 0x7c, 0xff, 0x9c, 0x8e, 0x7c, 0xff, + 0xb1, 0xa3, 0x94, 0xff, 0xb1, 0xa3, 0x94, 0xff, 0xb4, 0xae, 0x9c, 0xff, + 0xd9, 0xcc, 0xbc, 0xff, 0xf2, 0xe9, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x5d, 0x62, 0x5c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x52, 0x4c, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x5d, 0x62, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x5d, 0x62, 0x5c, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x6f, 0x6c, 0x6c, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0xa3, 0xa3, 0xa4, 0xff, 0x81, 0x7e, 0x7c, 0xff, + 0xb3, 0xae, 0xac, 0xff, 0xa1, 0x99, 0x9c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x7b, 0x7a, 0x7c, 0xff, 0xbc, 0xb9, 0xbc, 0xff, 0x88, 0x8a, 0x84, 0xff, + 0x64, 0x6a, 0x6c, 0xff, 0x83, 0x82, 0x84, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0x9c, 0x9a, 0x94, 0xff, 0x89, 0x86, 0x84, 0xff, 0x71, 0x72, 0x6c, 0xff, + 0xb4, 0xb2, 0xb4, 0xff, 0xe8, 0xe7, 0xe4, 0xff, 0xec, 0xea, 0xec, 0xff, + 0xe8, 0xe7, 0xe4, 0xff, 0xe4, 0xe1, 0xe4, 0xff, 0xdc, 0xdc, 0xdc, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xc4, 0xbe, 0xc4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0xc4, 0xc3, 0xc4, 0xff, 0x8b, 0x8b, 0x8c, 0xff, 0xb4, 0xb2, 0xb4, 0xff, + 0x9c, 0x9a, 0x94, 0xff, 0xac, 0xa9, 0xac, 0xff, 0xd7, 0xd6, 0xd4, 0xff, + 0xf2, 0xf0, 0xec, 0xff, 0xd7, 0xd6, 0xd4, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0xcc, 0xc2, 0xbc, 0xff, 0xdc, 0xba, 0xbc, 0xff, 0xad, 0x9e, 0x9e, 0xff, + 0x9c, 0x80, 0x7c, 0xff, 0xa4, 0x85, 0x84, 0xff, 0x9c, 0x88, 0x7c, 0xff, + 0x9c, 0x88, 0x7c, 0xff, 0x9c, 0x88, 0x7c, 0xff, 0x8f, 0x86, 0x7c, 0xff, + 0xa4, 0x86, 0x74, 0xff, 0x9c, 0x88, 0x7c, 0xff, 0xa8, 0x93, 0x8c, 0xff, + 0xb1, 0xa3, 0x94, 0xff, 0xb4, 0xae, 0x9c, 0xff, 0xe2, 0xdc, 0xcc, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x52, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x63, 0x66, 0x64, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x64, 0x6a, 0x6c, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x64, 0x6a, 0x6c, 0xff, 0x81, 0x7e, 0x7c, 0xff, 0x64, 0x6a, 0x6c, 0xff, + 0x83, 0x82, 0x84, 0xff, 0x64, 0x6a, 0x6c, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x6f, 0x6c, 0x6c, 0xff, 0xa3, 0xa3, 0xa4, 0xff, 0x83, 0x82, 0x84, 0xff, + 0x8b, 0x8b, 0x8c, 0xff, 0x9a, 0x94, 0x94, 0xff, 0xa1, 0x9e, 0x9c, 0xff, + 0x7b, 0x7a, 0x7c, 0xff, 0x64, 0x6a, 0x6c, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x94, 0x8e, 0x94, 0xff, 0xba, 0xb6, 0xb4, 0xff, 0xcc, 0xcc, 0xcc, 0xff, + 0xe8, 0xe7, 0xe4, 0xff, 0xd7, 0xd6, 0xd4, 0xff, 0xdc, 0xd6, 0xdc, 0xff, + 0xb3, 0xae, 0xac, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xba, 0xb6, 0xb4, 0xff, + 0xd9, 0xd4, 0xcc, 0xff, 0xb4, 0xb2, 0xb4, 0xff, 0xac, 0xa9, 0xac, 0xff, + 0xa1, 0x9e, 0x9c, 0xff, 0xa1, 0x9e, 0x9c, 0xff, 0xa3, 0xa3, 0xa4, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xf4, 0xea, 0xe4, 0xff, 0xbc, 0xb0, 0xac, 0xff, + 0xbc, 0xaa, 0xac, 0xff, 0xad, 0x9e, 0x9e, 0xff, 0xa8, 0x93, 0x8c, 0xff, + 0xa4, 0x85, 0x84, 0xff, 0xa4, 0x85, 0x84, 0xff, 0x9d, 0x8d, 0x8c, 0xff, + 0xa8, 0x9b, 0x94, 0xff, 0xbc, 0xa4, 0x9c, 0xff, 0xbf, 0xaa, 0xa4, 0xff, + 0xa6, 0x95, 0x94, 0xff, 0xac, 0x8d, 0x84, 0xff, 0x9c, 0x88, 0x7c, 0xff, + 0x90, 0x7f, 0x74, 0xff, 0xac, 0x8d, 0x84, 0xff, 0xba, 0xb0, 0xa4, 0xff, + 0xf4, 0xe9, 0xd4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf7, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x5d, 0x62, 0x5c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4c, 0x52, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x52, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x5d, 0x62, 0x5c, 0xff, + 0x5d, 0x62, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x5d, 0x62, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x64, 0x6a, 0x6c, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x7b, 0x7a, 0x7c, 0xff, 0x63, 0x66, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x81, 0x7e, 0x7c, 0xff, 0x71, 0x72, 0x74, 0xff, + 0x88, 0x8a, 0x84, 0xff, 0x89, 0x86, 0x84, 0xff, 0x7b, 0x7a, 0x7c, 0xff, + 0x64, 0x6a, 0x6c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x78, 0x77, 0x74, 0xff, 0xa3, 0xa3, 0xa4, 0xff, 0x8b, 0x8b, 0x8c, 0xff, + 0xdc, 0xdc, 0xdc, 0xff, 0xac, 0xa9, 0xac, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0x8b, 0x8b, 0x8c, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xbc, 0xb9, 0xbc, 0xff, + 0xcc, 0xcc, 0xcc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xdc, 0xdc, 0xdc, 0xff, + 0xc2, 0xbe, 0xbc, 0xff, 0xbc, 0xb9, 0xbc, 0xff, 0xac, 0xa9, 0xac, 0xff, + 0xdc, 0xdc, 0xdc, 0xff, 0xd6, 0xd2, 0xd4, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0xbc, 0xb0, 0xac, 0xff, 0xa6, 0x95, 0x94, 0xff, 0x96, 0x86, 0x8c, 0xff, + 0x9e, 0x8b, 0x84, 0xff, 0x9d, 0x8d, 0x8c, 0xff, 0xa4, 0x85, 0x84, 0xff, + 0xa4, 0x85, 0x84, 0xff, 0xa8, 0x93, 0x8c, 0xff, 0xad, 0x9e, 0x9e, 0xff, + 0xbd, 0xa6, 0xa4, 0xff, 0xa6, 0x95, 0x94, 0xff, 0xa6, 0x95, 0x94, 0xff, + 0xa4, 0x85, 0x84, 0xff, 0x8f, 0x86, 0x7c, 0xff, 0xa7, 0x94, 0x84, 0xff, + 0xba, 0xb0, 0xa4, 0xff, 0xe4, 0xe2, 0xd8, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf7, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x63, 0x6a, 0x64, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x71, 0x72, 0x74, 0xff, 0x7b, 0x7a, 0x7c, 0xff, 0x63, 0x6a, 0x64, 0xff, + 0x71, 0x72, 0x74, 0xff, 0x55, 0x55, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x63, 0x6a, 0x64, 0xff, 0x64, 0x6a, 0x6c, 0xff, 0x7b, 0x7a, 0x7c, 0xff, + 0xb4, 0xb2, 0xb4, 0xff, 0x7b, 0x7a, 0x7c, 0xff, 0x9c, 0x9a, 0x94, 0xff, + 0x71, 0x72, 0x74, 0xff, 0xb4, 0xb2, 0xb4, 0xff, 0xb4, 0xb2, 0xb4, 0xff, + 0xc8, 0xca, 0xc4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0xb3, 0xae, 0xac, 0xff, 0xc2, 0xbe, 0xbc, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0xe4, 0xe1, 0xe4, 0xff, 0xd4, 0xc6, 0xc4, 0xff, 0xd5, 0xcd, 0xcc, 0xff, + 0xa6, 0x95, 0x94, 0xff, 0xa8, 0x93, 0x8c, 0xff, 0x9c, 0x80, 0x7c, 0xff, + 0x9c, 0x7a, 0x7c, 0xff, 0xa4, 0x85, 0x84, 0xff, 0xa4, 0x85, 0x84, 0xff, + 0x8e, 0x79, 0x74, 0xff, 0x9c, 0x80, 0x7c, 0xff, 0xb4, 0x96, 0x94, 0xff, + 0xbd, 0xa6, 0xa4, 0xff, 0xc5, 0xb7, 0xb4, 0xff, 0xbc, 0xa4, 0x9c, 0xff, + 0xa6, 0x95, 0x94, 0xff, 0x9c, 0x88, 0x7c, 0xff, 0x9c, 0x88, 0x7c, 0xff, + 0x9c, 0x92, 0x84, 0xff, 0xc7, 0xb8, 0xac, 0xff, 0xf2, 0xe9, 0xdc, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x50, 0x4e, 0x44, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x5d, 0x62, 0x5c, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x63, 0x66, 0x64, 0xff, 0x63, 0x6a, 0x64, 0xff, + 0x83, 0x82, 0x84, 0xff, 0x63, 0x6a, 0x64, 0xff, 0x64, 0x6a, 0x6c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0xa1, 0xa2, 0x9c, 0xff, 0xb4, 0xb2, 0xb4, 0xff, + 0xbc, 0xb9, 0xbc, 0xff, 0xc2, 0xc2, 0xbc, 0xff, 0x83, 0x82, 0x84, 0xff, + 0x7b, 0x7a, 0x7c, 0xff, 0xa1, 0x9e, 0x9c, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0xdc, 0xd6, 0xdc, 0xff, 0xd4, 0xc6, 0xc4, 0xff, 0xd4, 0xc6, 0xc4, 0xff, + 0xc6, 0xb1, 0xb4, 0xff, 0xe6, 0xd6, 0xd6, 0xff, 0xcc, 0xbe, 0xc4, 0xff, + 0xb4, 0x96, 0x94, 0xff, 0xa4, 0x85, 0x84, 0xff, 0x9c, 0x7a, 0x74, 0xff, + 0x9c, 0x7a, 0x7c, 0xff, 0x9c, 0x80, 0x7c, 0xff, 0x9c, 0x80, 0x7c, 0xff, + 0x9d, 0x8d, 0x8c, 0xff, 0xa6, 0x95, 0x94, 0xff, 0xb0, 0xa3, 0x9c, 0xff, + 0xad, 0x9e, 0x9e, 0xff, 0xa8, 0x93, 0x8c, 0xff, 0x90, 0x7f, 0x74, 0xff, + 0x9c, 0x81, 0x74, 0xff, 0xa9, 0x9b, 0x8c, 0xff, 0xd8, 0xdc, 0xd4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x52, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x5d, 0x62, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x5d, 0x62, 0x5c, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x64, 0x4e, 0x54, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x64, 0x6a, 0x6c, 0xff, 0x8b, 0x8b, 0x8c, 0xff, 0xc4, 0xc3, 0xc4, 0xff, + 0x9a, 0x94, 0x94, 0xff, 0xb4, 0xb2, 0xb4, 0xff, 0x71, 0x72, 0x74, 0xff, + 0x83, 0x82, 0x84, 0xff, 0x89, 0x86, 0x84, 0xff, 0xa1, 0x9e, 0x9c, 0xff, + 0xbc, 0xb9, 0xbc, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xc2, 0xbe, 0xbc, 0xff, + 0xa6, 0x95, 0x94, 0xff, 0xd4, 0xc6, 0xc4, 0xff, 0xe4, 0xd2, 0xd4, 0xff, + 0xb4, 0x9b, 0x94, 0xff, 0x96, 0x86, 0x8c, 0xff, 0x9c, 0x7a, 0x7c, 0xff, + 0x9c, 0x7a, 0x74, 0xff, 0x8e, 0x7a, 0x7c, 0xff, 0x9c, 0x80, 0x7c, 0xff, + 0x96, 0x85, 0x84, 0xff, 0xb4, 0x9b, 0x94, 0xff, 0xad, 0x9e, 0x9e, 0xff, + 0xba, 0xb0, 0xa4, 0xff, 0xbf, 0xaa, 0xa4, 0xff, 0xa8, 0x93, 0x8c, 0xff, + 0x84, 0x7e, 0x74, 0xff, 0x90, 0x7f, 0x74, 0xff, 0xa9, 0x9b, 0x8c, 0xff, + 0xd9, 0xc6, 0xb4, 0xff, 0xf2, 0xe9, 0xdc, 0xff, 0xf2, 0xe9, 0xdc, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x5d, 0x62, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x63, 0x6a, 0x64, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x63, 0x66, 0x64, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x4c, 0x52, 0x4c, 0xff, 0x64, 0x4e, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, 0xa1, 0x9e, 0x9c, 0xff, + 0x81, 0x7e, 0x7c, 0xff, 0x64, 0x6a, 0x6c, 0xff, 0x64, 0x6a, 0x6c, 0xff, + 0x64, 0x6a, 0x6c, 0xff, 0x83, 0x82, 0x84, 0xff, 0x8b, 0x8b, 0x8c, 0xff, + 0xb4, 0xb2, 0xb4, 0xff, 0xcc, 0xc5, 0xc4, 0xff, 0xac, 0xa9, 0xac, 0xff, + 0x7b, 0x7a, 0x7c, 0xff, 0xbf, 0xaa, 0xa4, 0xff, 0x8f, 0x7f, 0x7c, 0xff, + 0x96, 0x85, 0x84, 0xff, 0x9c, 0x7a, 0x74, 0xff, 0x8e, 0x72, 0x74, 0xff, + 0x9c, 0x7a, 0x7c, 0xff, 0x9c, 0x80, 0x7c, 0xff, 0x8e, 0x79, 0x74, 0xff, + 0x96, 0x85, 0x84, 0xff, 0xa8, 0x93, 0x8c, 0xff, 0xa8, 0x9b, 0x94, 0xff, + 0xae, 0xa4, 0xa4, 0xff, 0xbf, 0xaa, 0xa4, 0xff, 0xa8, 0x93, 0x8c, 0xff, + 0x8e, 0x79, 0x74, 0xff, 0x8a, 0x76, 0x6c, 0xff, 0x84, 0x7e, 0x74, 0xff, + 0xa9, 0x9b, 0x8c, 0xff, 0xc9, 0xc0, 0xb4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x34, 0x33, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x5d, 0x62, 0x5c, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x63, 0x66, 0x64, 0xff, 0x64, 0x6a, 0x6c, 0xff, + 0x64, 0x6a, 0x6c, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x64, 0x4e, 0x54, 0xff, 0x42, 0x42, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x64, 0x5d, 0x5c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x5d, 0x62, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x81, 0x7e, 0x7c, 0xff, 0x83, 0x82, 0x84, 0xff, + 0xb3, 0xae, 0xac, 0xff, 0x9c, 0x9a, 0x94, 0xff, 0xa3, 0xa3, 0xa4, 0xff, + 0x6f, 0x6c, 0x6c, 0xff, 0x9c, 0x93, 0x8c, 0xff, 0x8f, 0x7f, 0x7c, 0xff, + 0x7e, 0x6d, 0x6c, 0xff, 0x81, 0x72, 0x74, 0xff, 0x7f, 0x72, 0x6c, 0xff, + 0x8f, 0x7f, 0x7c, 0xff, 0x8f, 0x7f, 0x7c, 0xff, 0x8e, 0x79, 0x74, 0xff, + 0x8e, 0x79, 0x74, 0xff, 0x96, 0x85, 0x84, 0xff, 0xa4, 0x85, 0x84, 0xff, + 0xa8, 0x93, 0x8c, 0xff, 0xb4, 0x9b, 0x94, 0xff, 0xa8, 0x93, 0x8c, 0xff, + 0x7f, 0x72, 0x6c, 0xff, 0x8c, 0x6e, 0x64, 0xff, 0x90, 0x7f, 0x74, 0xff, + 0xa7, 0x94, 0x84, 0xff, 0xb0, 0xa3, 0x9c, 0xff, 0xe4, 0xd2, 0xc4, 0xff, + 0xf2, 0xe9, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3b, 0x3a, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x5d, 0x62, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x64, 0x4e, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x58, 0x49, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x64, 0x4e, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x64, 0x5d, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x64, 0x5d, 0x5c, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x64, 0x6a, 0x6c, 0xff, 0x92, 0x92, 0x8c, 0xff, 0x64, 0x6a, 0x6c, 0xff, + 0x83, 0x82, 0x84, 0xff, 0x7b, 0x7a, 0x7c, 0xff, 0x8b, 0x8b, 0x8c, 0xff, + 0x71, 0x6a, 0x64, 0xff, 0x81, 0x7e, 0x7c, 0xff, 0x6f, 0x6c, 0x6c, 0xff, + 0x71, 0x6a, 0x64, 0xff, 0x7e, 0x6d, 0x6c, 0xff, 0x7f, 0x72, 0x6c, 0xff, + 0x8e, 0x79, 0x74, 0xff, 0x8e, 0x72, 0x74, 0xff, 0x78, 0x66, 0x64, 0xff, + 0x8e, 0x79, 0x74, 0xff, 0x96, 0x85, 0x84, 0xff, 0x9c, 0x80, 0x7c, 0xff, + 0x96, 0x85, 0x84, 0xff, 0x9d, 0x8d, 0x8c, 0xff, 0x9e, 0x8b, 0x84, 0xff, + 0x8e, 0x79, 0x74, 0xff, 0x9c, 0x92, 0x84, 0xff, 0x8e, 0x79, 0x74, 0xff, + 0x8e, 0x79, 0x74, 0xff, 0xa7, 0x94, 0x84, 0xff, 0xb1, 0xa3, 0x94, 0xff, + 0xda, 0xd4, 0xc4, 0xff, 0xf2, 0xe9, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf3, 0xf2, 0xdc, 0xff, 0xf3, 0xf2, 0xdc, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3b, 0x3a, 0x34, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x63, 0x66, 0x64, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x63, 0x6a, 0x64, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4e, 0x42, 0x44, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x64, 0x4e, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x63, 0x66, 0x64, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x71, 0x6a, 0x64, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x63, 0x66, 0x64, 0xff, 0x71, 0x72, 0x6c, 0xff, + 0x6f, 0x6c, 0x6c, 0xff, 0x63, 0x66, 0x64, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x81, 0x72, 0x74, 0xff, 0x81, 0x72, 0x74, 0xff, 0x6f, 0x6c, 0x6c, 0xff, + 0x81, 0x72, 0x74, 0xff, 0x96, 0x86, 0x8c, 0xff, 0xad, 0x9a, 0x9c, 0xff, + 0xa4, 0x85, 0x84, 0xff, 0xa4, 0x85, 0x84, 0xff, 0x8d, 0x72, 0x6b, 0xff, + 0x78, 0x66, 0x64, 0xff, 0x8f, 0x7f, 0x7c, 0xff, 0x8f, 0x7f, 0x7c, 0xff, + 0x8e, 0x79, 0x74, 0xff, 0x9c, 0x7a, 0x74, 0xff, 0xa4, 0x89, 0x7c, 0xff, + 0xa8, 0x9b, 0x94, 0xff, 0xe2, 0xdc, 0xcc, 0xff, 0xf2, 0xe9, 0xdc, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4c, 0x52, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x64, 0x6a, 0x6c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x5d, 0x62, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x64, 0x4e, 0x54, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x4e, 0x42, 0x44, 0xff, 0x58, 0x49, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x69, 0x55, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x58, 0x49, 0x4c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x6c, 0x61, 0x64, 0xff, 0x5d, 0x5a, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x64, 0x5d, 0x5c, 0xff, 0x64, 0x5d, 0x5c, 0xff, 0x6c, 0x61, 0x64, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x64, 0x5d, 0x5c, 0xff, 0x6c, 0x61, 0x64, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x81, 0x7e, 0x7c, 0xff, 0x78, 0x66, 0x64, 0xff, + 0x84, 0x77, 0x74, 0xff, 0x9d, 0x8d, 0x8c, 0xff, 0xbc, 0xaa, 0xac, 0xff, + 0xac, 0x8d, 0x8c, 0xff, 0x96, 0x86, 0x8c, 0xff, 0x7e, 0x6d, 0x6c, 0xff, + 0x75, 0x62, 0x64, 0xff, 0x84, 0x77, 0x74, 0xff, 0xbd, 0xa6, 0xa4, 0xff, + 0x9c, 0x80, 0x7c, 0xff, 0x8e, 0x79, 0x74, 0xff, 0x9c, 0x7a, 0x74, 0xff, + 0x9c, 0x88, 0x7c, 0xff, 0xa8, 0x9b, 0x94, 0xff, 0xe4, 0xe2, 0xd8, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0xf2, 0xe9, 0xdc, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x34, 0x32, 0x2c, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x5d, 0x62, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x4c, 0x52, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x52, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4c, 0x52, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x6b, 0x56, 0x5c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x64, 0x5d, 0x5c, 0xff, + 0x5d, 0x5a, 0x54, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x64, 0x5d, 0x5c, 0xff, + 0x64, 0x5d, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x70, 0x66, 0x5c, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x6c, 0x61, 0x64, 0xff, 0x64, 0x5d, 0x5c, 0xff, + 0x77, 0x66, 0x6c, 0xff, 0x7e, 0x6d, 0x6c, 0xff, 0x84, 0x79, 0x7c, 0xff, + 0x96, 0x86, 0x8c, 0xff, 0xac, 0x8d, 0x84, 0xff, 0x8e, 0x72, 0x74, 0xff, + 0x7f, 0x6a, 0x64, 0xff, 0xad, 0x9e, 0x9e, 0xff, 0xba, 0xb0, 0xa4, 0xff, + 0xb4, 0x9b, 0x94, 0xff, 0x8e, 0x72, 0x74, 0xff, 0x8e, 0x79, 0x74, 0xff, + 0x8e, 0x79, 0x74, 0xff, 0x84, 0x7e, 0x74, 0xff, 0xda, 0xd4, 0xc4, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0xf4, 0xf8, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x44, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x64, 0x4e, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x5d, 0x62, 0x5c, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x44, 0x47, 0x44, 0xff, 0x53, 0x41, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x64, 0x4e, 0x54, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x5d, 0x5a, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x55, 0x52, 0x4c, 0xff, 0x55, 0x52, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x5d, 0x62, 0x5c, 0xff, + 0x5d, 0x5a, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x64, 0x5d, 0x5c, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x78, 0x66, 0x64, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x6c, 0x61, 0x64, 0xff, 0x8e, 0x79, 0x74, 0xff, + 0x8c, 0x81, 0x84, 0xff, 0xa8, 0x93, 0x8c, 0xff, 0x8f, 0x7f, 0x7c, 0xff, + 0x72, 0x62, 0x5c, 0xff, 0x7f, 0x72, 0x6c, 0xff, 0x9d, 0x8d, 0x8c, 0xff, + 0xa8, 0x9b, 0x94, 0xff, 0x9c, 0x80, 0x7c, 0xff, 0x8e, 0x79, 0x74, 0xff, + 0x7f, 0x72, 0x6c, 0xff, 0x8f, 0x86, 0x7c, 0xff, 0xb1, 0xaa, 0xa4, 0xff, + 0xe4, 0xe2, 0xd8, 0xff, 0xf4, 0xf2, 0xe4, 0xff, 0xf3, 0xf2, 0xdc, 0xff, + 0xf4, 0xf2, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x42, 0x42, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x44, 0x47, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x34, 0x32, 0x2c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x64, 0x4e, 0x54, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x64, 0x4e, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x64, 0x5d, 0x5c, 0xff, + 0x6b, 0x56, 0x5c, 0xff, 0x55, 0x52, 0x4c, 0xff, 0x6b, 0x56, 0x5c, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x64, 0x5d, 0x5c, 0xff, 0x64, 0x5d, 0x5c, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0x5d, 0x62, 0x5c, 0xff, 0x77, 0x66, 0x6c, 0xff, + 0x7e, 0x6d, 0x6c, 0xff, 0x8f, 0x7f, 0x7c, 0xff, 0x6c, 0x61, 0x64, 0xff, + 0x64, 0x5d, 0x5c, 0xff, 0x71, 0x6a, 0x64, 0xff, 0x7e, 0x6d, 0x6c, 0xff, + 0x9d, 0x8d, 0x8c, 0xff, 0x84, 0x79, 0x7c, 0xff, 0x7f, 0x72, 0x6c, 0xff, + 0x7f, 0x72, 0x6c, 0xff, 0x7c, 0x72, 0x64, 0xff, 0x94, 0x8b, 0x84, 0xff, + 0xda, 0xd4, 0xc4, 0xff, 0xf4, 0xea, 0xe4, 0xff, 0xf2, 0xe9, 0xdc, 0xff, + 0xf4, 0xea, 0xe4, 0xff, 0xf4, 0xf8, 0xe4, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x42, 0x42, 0x44, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x4e, 0x42, 0x44, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x55, 0x55, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x64, 0x5d, 0x5c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x6f, 0x6c, 0x6c, 0xff, 0x78, 0x66, 0x64, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x5d, 0x5a, 0x54, 0xff, 0x63, 0x66, 0x64, 0xff, 0x81, 0x72, 0x74, 0xff, + 0x8c, 0x81, 0x84, 0xff, 0x81, 0x72, 0x74, 0xff, 0x81, 0x72, 0x74, 0xff, + 0x71, 0x6a, 0x64, 0xff, 0x63, 0x6a, 0x64, 0xff, 0x84, 0x7e, 0x74, 0xff, + 0xc2, 0xbe, 0xbc, 0xff, 0xe4, 0xe2, 0xd8, 0xff, 0xc9, 0xc0, 0xb4, 0xff, + 0xf4, 0xea, 0xe4, 0xff, 0xf4, 0xf2, 0xe4, 0xff, + 0x4c, 0x52, 0x4c, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x42, 0x42, 0x44, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x42, 0x42, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x64, 0x4e, 0x54, 0xff, 0x42, 0x42, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x55, 0x52, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x69, 0x55, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x55, 0x55, 0x54, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x5d, 0x5a, 0x54, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x64, 0x5d, 0x5c, 0xff, 0x5d, 0x62, 0x5c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x70, 0x5e, 0x5c, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x5d, 0x5a, 0x54, 0xff, 0x5d, 0x5a, 0x54, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x63, 0x66, 0x64, 0xff, 0x6c, 0x61, 0x64, 0xff, + 0x81, 0x72, 0x74, 0xff, 0x84, 0x77, 0x74, 0xff, 0x77, 0x66, 0x6c, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x71, 0x6a, 0x64, 0xff, 0x71, 0x72, 0x6c, 0xff, + 0xb1, 0xaa, 0xa4, 0xff, 0xd6, 0xc5, 0xbc, 0xff, 0x9a, 0x94, 0x94, 0xff, + 0xd9, 0xd4, 0xcc, 0xff, 0xe4, 0xe2, 0xd8, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x34, 0x32, 0x2c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x34, 0x33, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x4c, 0x52, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x4c, 0x52, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x6b, 0x56, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x55, 0x52, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x5d, 0x5a, 0x54, 0xff, 0x64, 0x5d, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x64, 0x5d, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x5d, 0x62, 0x5c, 0xff, 0x63, 0x66, 0x64, 0xff, 0x55, 0x52, 0x4c, 0xff, + 0x6c, 0x61, 0x64, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x6c, 0x61, 0x64, 0xff, + 0x6c, 0x66, 0x6c, 0xff, 0x6f, 0x6c, 0x6c, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x5d, 0x62, 0x5c, 0xff, 0x71, 0x6a, 0x64, 0xff, 0x6f, 0x6c, 0x6c, 0xff, + 0x84, 0x77, 0x74, 0xff, 0x89, 0x86, 0x84, 0xff, 0x8f, 0x86, 0x7c, 0xff, + 0xcc, 0xc2, 0xbc, 0xff, 0xe4, 0xe2, 0xd8, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x34, 0x2e, 0x34, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x34, 0x33, 0x34, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x34, 0x33, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x5d, 0x62, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x55, 0x52, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x64, 0x5d, 0x5c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x69, 0x55, 0x54, 0xff, + 0x5d, 0x62, 0x5c, 0xff, 0x64, 0x5d, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x5d, 0x62, 0x5c, 0xff, + 0x64, 0x5d, 0x5c, 0xff, 0x5d, 0x62, 0x5c, 0xff, 0x5d, 0x62, 0x5c, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0x64, 0x5d, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x64, 0x5d, 0x5c, 0xff, 0x6f, 0x6c, 0x6c, 0xff, 0x71, 0x6a, 0x64, 0xff, + 0x71, 0x6a, 0x64, 0xff, 0x70, 0x66, 0x5c, 0xff, 0x72, 0x62, 0x5c, 0xff, + 0x88, 0x8a, 0x84, 0xff, 0xa8, 0x9b, 0x94, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x3b, 0x3a, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x34, 0x33, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x6b, 0x56, 0x5c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x4e, 0x42, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x44, 0x3a, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x3a, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x64, 0x4e, 0x54, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x55, 0x52, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x5d, 0x5a, 0x54, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x64, 0x5d, 0x5c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x5d, 0x5a, 0x54, 0xff, 0x64, 0x5d, 0x5c, 0xff, 0x64, 0x5d, 0x5c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x64, 0x5d, 0x5c, 0xff, 0x64, 0x5d, 0x5c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x5d, 0x5a, 0x54, 0xff, 0x64, 0x5d, 0x5c, 0xff, + 0x5f, 0x62, 0x64, 0xff, 0x5f, 0x62, 0x64, 0xff, 0x5d, 0x62, 0x5c, 0xff, + 0x63, 0x66, 0x64, 0xff, 0x64, 0x5d, 0x5c, 0xff, 0x72, 0x5b, 0x54, 0xff, + 0x78, 0x77, 0x74, 0xff, 0x8f, 0x86, 0x7c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x34, 0x32, 0x2c, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x34, 0x32, 0x2c, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x33, 0x2c, 0x2c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x3b, 0x3a, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x5d, 0x5a, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x55, 0x52, 0x4c, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x64, 0x5d, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x5d, 0x5a, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x64, 0x5d, 0x5c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x55, 0x52, 0x4c, 0xff, 0x64, 0x5d, 0x5c, 0xff, + 0x5d, 0x62, 0x5c, 0xff, 0x64, 0x5d, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x70, 0x5e, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x55, 0x52, 0x4c, 0xff, + 0x70, 0x66, 0x5c, 0xff, 0x63, 0x66, 0x64, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x34, 0x33, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x6b, 0x56, 0x5c, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x4e, 0x42, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4c, 0x52, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x4e, 0x42, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x55, 0x52, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x58, 0x49, 0x4c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x69, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x64, 0x5d, 0x5c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x55, 0x52, 0x4c, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x55, 0x52, 0x4c, 0xff, 0x69, 0x55, 0x54, 0xff, 0x55, 0x52, 0x4c, 0xff, + 0x64, 0x5d, 0x5c, 0xff, 0x5d, 0x5a, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x33, 0x2c, 0x2c, 0xff, 0x30, 0x2a, 0x24, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x42, 0x42, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x52, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x33, 0x2c, 0x2c, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x34, 0x2e, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x44, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x58, 0x49, 0x4c, 0xff, 0x64, 0x4e, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x55, 0x52, 0x4c, 0xff, 0x5d, 0x5a, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x55, 0x52, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x55, 0x52, 0x4c, 0xff, 0x64, 0x5d, 0x5c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x55, 0x55, 0x54, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x64, 0x5d, 0x5c, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x55, 0x52, 0x4c, 0xff, + 0x55, 0x52, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x5d, 0x5a, 0x54, 0xff, + 0x5d, 0x5a, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x34, 0x32, 0x2c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x30, 0x2a, 0x24, 0xff, 0x2c, 0x26, 0x2c, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x64, 0x4e, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x55, 0x52, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x58, 0x49, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x55, 0x52, 0x4c, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x55, 0x52, 0x4c, 0xff, 0x55, 0x52, 0x4c, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x2c, 0x26, 0x2c, 0xff, 0x34, 0x32, 0x2c, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x3b, 0x3a, 0x34, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x55, 0x55, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x53, 0x41, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x4e, 0x42, 0x44, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4e, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4e, 0x42, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x55, 0x52, 0x4c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x55, 0x52, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x69, 0x55, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x55, 0x52, 0x4c, 0xff, 0x5d, 0x5a, 0x54, 0xff, + 0x50, 0x4e, 0x44, 0xff, 0x55, 0x52, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x34, 0x33, 0x34, 0xff, 0x34, 0x32, 0x2c, 0xff, + 0x34, 0x32, 0x2c, 0xff, 0x33, 0x2c, 0x2c, 0xff, 0x34, 0x32, 0x2c, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x55, 0x52, 0x4c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x64, 0x4e, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x55, 0x55, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x34, 0x33, 0x34, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x64, 0x4e, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x55, 0x52, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x6b, 0x56, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x55, 0x52, 0x4c, 0xff, 0x58, 0x49, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x5d, 0x5a, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x55, 0x52, 0x4c, 0xff, 0x55, 0x52, 0x4c, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3b, 0x3a, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x44, 0x3a, 0x3c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x5d, 0x5a, 0x54, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x3a, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x55, 0x52, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4c, 0x52, 0x4c, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x50, 0x4e, 0x44, 0xff, 0x55, 0x52, 0x4c, 0xff, + 0x55, 0x52, 0x4c, 0xff, 0x50, 0x4e, 0x44, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x4c, 0x52, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x34, 0x33, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x3b, 0x3a, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x34, 0x2e, 0x34, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x33, 0x2c, 0x2c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x46, 0x3c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x55, 0x52, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x53, 0x41, 0x3c, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x44, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x5d, 0x5a, 0x54, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x55, 0x52, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x55, 0x52, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x55, 0x52, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x34, 0x33, 0x34, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x34, 0x32, 0x2c, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x34, 0x33, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x42, 0x42, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x55, 0x55, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x64, 0x5d, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x64, 0x4e, 0x54, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x58, 0x49, 0x4c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x53, 0x41, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4e, 0x42, 0x44, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x64, 0x4e, 0x54, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x50, 0x4e, 0x44, 0xff, 0x55, 0x52, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x50, 0x4e, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x44, 0x3a, 0x3c, 0xff, 0x34, 0x32, 0x2c, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x44, 0x46, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x34, 0x32, 0x2c, 0xff, 0x34, 0x33, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x33, 0x2c, 0x2c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x3a, 0x3c, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x55, 0x52, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4e, 0x42, 0x44, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x5d, 0x5a, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x50, 0x4e, 0x44, 0xff, 0x44, 0x46, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, 0x53, 0x5a, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x4e, 0x42, 0x44, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3b, 0x3a, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x3b, 0x3a, 0x34, 0xff, 0x30, 0x2a, 0x24, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x32, 0x2c, 0xff, 0x3c, 0x32, 0x2c, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x33, 0x2c, 0x2c, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x34, 0x32, 0x2c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x44, 0x3a, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x55, 0x52, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x64, 0x5d, 0x5c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x34, 0x2e, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x5f, 0x62, 0x64, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x4e, 0x42, 0x44, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x4e, 0x42, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x55, 0x52, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x44, 0x46, 0x3c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x50, 0x4e, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x3b, 0x3a, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x3a, 0x3c, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x44, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x30, 0x2a, 0x24, 0xff, + 0x34, 0x32, 0x2c, 0xff, 0x30, 0x2a, 0x24, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x30, 0x2a, 0x24, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x64, 0x4e, 0x54, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x32, 0x2c, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x44, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x34, 0x33, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x64, 0x4e, 0x54, 0xff, 0x44, 0x46, 0x3c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x53, 0x5a, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x4e, 0x42, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x55, 0x52, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x55, 0x52, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x55, 0x52, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x34, 0x33, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x34, 0x2e, 0x34, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x3b, 0x3a, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x34, 0x32, 0x2c, 0xff, 0x30, 0x2a, 0x24, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3c, 0x32, 0x2c, 0xff, 0x30, 0x2a, 0x24, 0xff, + 0x30, 0x2a, 0x24, 0xff, 0x33, 0x2c, 0x2c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x4c, 0x52, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4c, 0x52, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x34, 0x32, 0x2c, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x55, 0x52, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x58, 0x49, 0x4c, 0xff, + 0x4c, 0x52, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x44, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x34, 0xff, 0x4e, 0x42, 0x44, 0xff, + 0x44, 0x3a, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x44, 0x3a, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x53, 0x41, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x46, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x44, 0x46, 0x3c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x33, 0x2c, 0x2c, 0xff, 0x30, 0x26, 0x24, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x34, 0x32, 0x2c, 0xff, 0x33, 0x2c, 0x2c, 0xff, 0x30, 0x26, 0x24, 0xff, + 0x30, 0x2a, 0x24, 0xff, 0x30, 0x26, 0x24, 0xff, 0x30, 0x26, 0x24, 0xff, + 0x30, 0x26, 0x24, 0xff, 0x30, 0x2a, 0x24, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x44, 0x47, 0x44, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x33, 0x2c, 0x2c, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x34, 0x32, 0x2c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x44, 0x46, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x34, 0x32, 0x2c, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x58, 0x49, 0x4c, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x44, 0x3a, 0x3c, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x58, 0x49, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x44, 0x46, 0x3c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x34, 0x33, 0x34, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x30, 0x2a, 0x24, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x33, 0x2c, 0x2c, 0xff, 0x30, 0x26, 0x24, 0xff, + 0x30, 0x26, 0x24, 0xff, 0x30, 0x26, 0x24, 0xff, 0x30, 0x26, 0x24, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x34, 0x32, 0x2c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x3b, 0x3a, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x4c, 0x52, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x33, 0x2c, 0x2c, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3b, 0x3a, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, 0x3c, 0x32, 0x2c, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3c, 0x32, 0x2c, 0xff, 0x34, 0x32, 0x2c, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x32, 0x2c, 0xff, + 0x3c, 0x32, 0x2c, 0xff, 0x34, 0x2e, 0x34, 0xff, 0x3c, 0x32, 0x2c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x58, 0x49, 0x4c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x4e, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x55, 0x55, 0x54, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x44, 0x3a, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x53, 0x41, 0x3c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x53, 0x41, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x55, 0x52, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x4c, 0x52, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x58, 0x5c, 0x5c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x34, 0x2e, 0x34, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x2c, 0x26, 0x2c, 0xff, 0x30, 0x26, 0x24, 0xff, 0x30, 0x26, 0x24, 0xff, + 0x30, 0x26, 0x24, 0xff, 0x30, 0x26, 0x24, 0xff, 0x30, 0x2a, 0x24, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x33, 0x2c, 0x2c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x3b, 0x3a, 0x34, 0xff, 0x3c, 0x2e, 0x2c, 0xff, + 0x3c, 0x2e, 0x2c, 0xff, 0x3c, 0x32, 0x2c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x2e, 0x2c, 0xff, + 0x3c, 0x2e, 0x2c, 0xff, 0x34, 0x33, 0x34, 0xff, 0x3c, 0x2e, 0x2c, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x4e, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x4e, 0x42, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x58, 0x49, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x53, 0x41, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3c, 0x2e, 0x2c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x34, 0x2e, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x64, 0x4e, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x3a, 0x3c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x34, 0x32, 0x2c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x34, 0x32, 0x2c, 0xff, 0x34, 0x32, 0x2c, 0xff, + 0x30, 0x26, 0x24, 0xff, 0x30, 0x26, 0x24, 0xff, 0x30, 0x26, 0x24, 0xff, + 0x30, 0x26, 0x24, 0xff, 0x2c, 0x26, 0x2c, 0xff, 0x30, 0x26, 0x24, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x44, 0x46, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x3b, 0x3a, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x34, 0x32, 0x2c, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x2e, 0x2c, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x3c, 0x32, 0x2c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x32, 0x2c, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3c, 0x2e, 0x2c, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x55, 0x52, 0x4c, 0xff, + 0x4e, 0x42, 0x44, 0xff, 0x34, 0x33, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x44, 0x3a, 0x3c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x5d, 0x5a, 0x54, 0xff, 0x6b, 0x56, 0x5c, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x53, 0x41, 0x3c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x44, 0x3a, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x4e, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x4c, 0x52, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x3a, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x4e, 0x42, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x4e, 0x42, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x33, 0x2c, 0x2c, 0xff, 0x30, 0x26, 0x24, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x30, 0x2a, 0x24, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x34, 0x2e, 0x34, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x30, 0x26, 0x24, 0xff, 0x30, 0x26, 0x24, 0xff, 0x30, 0x26, 0x24, 0xff, + 0x30, 0x26, 0x24, 0xff, 0x33, 0x2c, 0x2c, 0xff, 0x30, 0x26, 0x24, 0xff, + 0x30, 0x26, 0x24, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x3b, 0x3a, 0x34, 0xff, 0x34, 0x32, 0x2c, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x3b, 0x3a, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x34, 0x33, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x3c, 0x2e, 0x2c, 0xff, 0x34, 0x33, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x3c, 0x32, 0x2c, 0xff, 0x34, 0x33, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x32, 0x2c, 0xff, 0x3c, 0x32, 0x2c, 0xff, + 0x3c, 0x2e, 0x2c, 0xff, 0x3c, 0x2e, 0x2c, 0xff, 0x3c, 0x2e, 0x2c, 0xff, + 0x5c, 0x3e, 0x34, 0xff, 0x3c, 0x32, 0x2c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x3c, 0x2e, 0x2c, 0xff, 0x34, 0x33, 0x34, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x58, 0x49, 0x4c, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x2e, 0x2c, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x53, 0x41, 0x3c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x44, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x5d, 0x62, 0x5c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3c, 0x2e, 0x2c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x44, 0x3a, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x4e, 0x42, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x44, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x44, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x34, 0x2e, 0x34, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x2c, 0x26, 0x2c, 0xff, 0x30, 0x2a, 0x24, 0xff, 0x30, 0x26, 0x24, 0xff, + 0x30, 0x26, 0x24, 0xff, 0x30, 0x26, 0x24, 0xff, 0x30, 0x26, 0x24, 0xff, + 0x30, 0x26, 0x24, 0xff, 0x30, 0x26, 0x24, 0xff, 0x30, 0x26, 0x24, 0xff, + 0x2c, 0x26, 0x2c, 0xff, 0x44, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, 0x2c, 0x26, 0x2c, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x33, 0x2c, 0x2c, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x34, 0x33, 0x34, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x33, 0x2c, 0x2c, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x3b, 0x3a, 0x34, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x34, 0x32, 0x2c, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x3c, 0x2e, 0x2c, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x3c, 0x2e, 0x2c, 0xff, 0x3c, 0x2e, 0x2c, 0xff, + 0x3c, 0x2e, 0x2c, 0xff, 0x33, 0x2c, 0x2c, 0xff, 0x3c, 0x2e, 0x2c, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3c, 0x2e, 0x2c, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x44, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x4e, 0x42, 0x44, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x44, 0x3a, 0x3c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x58, 0x5c, 0x5c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x55, 0x4e, 0x4c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x34, 0x33, 0x34, 0xff, 0x3c, 0x2e, 0x2c, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x44, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x4e, 0x42, 0x44, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x2c, 0x26, 0x2c, 0xff, 0x30, 0x2a, 0x24, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x42, 0x42, 0x44, 0xff, 0x34, 0x32, 0x2c, 0xff, + 0x30, 0x2a, 0x24, 0xff, 0x2c, 0x26, 0x2c, 0xff, 0x30, 0x26, 0x24, 0xff, + 0x30, 0x26, 0x24, 0xff, 0x30, 0x26, 0x24, 0xff, 0x30, 0x26, 0x24, 0xff, + 0x30, 0x26, 0x24, 0xff, 0x2c, 0x26, 0x2c, 0xff, 0x30, 0x2a, 0x24, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x44, 0x47, 0x44, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x34, 0x32, 0x2c, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x34, 0x32, 0x2c, 0xff, 0x33, 0x2c, 0x2c, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x33, 0x2c, 0x2c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x34, 0x32, 0x2c, 0xff, 0x3c, 0x2e, 0x2c, 0xff, 0x30, 0x2a, 0x24, 0xff, + 0x3c, 0x2e, 0x2c, 0xff, 0x3c, 0x2e, 0x2c, 0xff, 0x3c, 0x2e, 0x2c, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x3c, 0x2e, 0x2c, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x3c, 0x2e, 0x2c, 0xff, 0x33, 0x2c, 0x2c, 0xff, 0x30, 0x26, 0x24, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x55, 0x55, 0x54, 0xff, 0x58, 0x49, 0x4c, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x44, 0x3a, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x42, 0x42, 0x44, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x55, 0x4e, 0x4c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x44, 0x3a, 0x3c, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x44, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x53, 0x5a, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x30, 0x26, 0x24, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x55, 0x4e, 0x4c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x33, 0x2c, 0x2c, 0xff, 0x2c, 0x26, 0x2c, 0xff, + 0x2c, 0x26, 0x2c, 0xff, 0x2c, 0x26, 0x2c, 0xff, 0x30, 0x26, 0x24, 0xff, + 0x2c, 0x26, 0x2c, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x30, 0x26, 0x24, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x42, 0x42, 0x44, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x33, 0x2c, 0x2c, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x34, 0x33, 0x34, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x30, 0x2a, 0x24, 0xff, 0x34, 0x2e, 0x34, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x34, 0x2e, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x34, 0x32, 0x2c, 0xff, 0x3c, 0x2e, 0x2c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x4e, 0x42, 0x44, 0xff, 0x33, 0x2c, 0x2c, 0xff, 0x3c, 0x2e, 0x2c, 0xff, + 0x3c, 0x2e, 0x2c, 0xff, 0x30, 0x2a, 0x24, 0xff, 0x3c, 0x2e, 0x2c, 0xff, + 0x30, 0x2a, 0x24, 0xff, 0x3c, 0x2e, 0x2c, 0xff, 0x30, 0x2a, 0x24, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x34, 0x2e, 0x34, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x4e, 0x42, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x34, 0x32, 0x2c, 0xff, 0x34, 0x33, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x55, 0x52, 0x4c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x44, 0x3a, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x3a, 0x3c, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x49, 0x4a, 0x4c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x30, 0x26, 0x24, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x4c, 0x47, 0x44, 0xff, 0x4c, 0x53, 0x54, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x34, 0x32, 0x2c, 0xff, + 0x3c, 0x2e, 0x2c, 0xff, 0x30, 0x26, 0x24, 0xff, 0x30, 0x26, 0x24, 0xff, + 0x2c, 0x26, 0x2c, 0xff, 0x44, 0x3a, 0x3c, 0xff, 0x2c, 0x26, 0x2c, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x55, 0x55, 0x54, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x33, 0x2c, 0x2c, 0xff, 0x34, 0x32, 0x2c, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x33, 0x2c, 0x2c, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x44, 0x3a, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x44, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x42, 0x42, 0x44, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, + 0x30, 0x2a, 0x24, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3b, 0x3a, 0x34, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x4c, 0x53, 0x54, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x33, 0x2c, 0x2c, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x34, 0x33, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x33, 0x2c, 0x2c, 0xff, 0x34, 0x33, 0x34, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x34, 0x32, 0x2c, 0xff, 0x34, 0x32, 0x2c, 0xff, + 0x34, 0x33, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x2e, 0x2c, 0xff, 0x3c, 0x2e, 0x2c, 0xff, + 0x3c, 0x2e, 0x2c, 0xff, 0x30, 0x26, 0x24, 0xff, 0x30, 0x26, 0x24, 0xff, + 0x3c, 0x2e, 0x2c, 0xff, 0x30, 0x2a, 0x24, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x30, 0x2a, 0x24, 0xff, 0x33, 0x2c, 0x2c, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x55, 0x52, 0x4c, 0xff, 0x55, 0x52, 0x4c, 0xff, 0x4e, 0x42, 0x44, 0xff, + 0x3c, 0x32, 0x2c, 0xff, 0x33, 0x2c, 0x2c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x3b, 0x3a, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x4c, 0x53, 0x54, 0xff, 0x55, 0x55, 0x54, 0xff, 0x4c, 0x52, 0x4c, 0xff, + 0x4b, 0x4e, 0x4c, 0xff, 0x55, 0x55, 0x54, 0xff, 0x4b, 0x4e, 0x4c, 0xff, + 0x49, 0x4a, 0x4c, 0xff, 0x34, 0x32, 0x2c, 0xff, 0x34, 0x32, 0x2c, 0xff, + 0x33, 0x2c, 0x2c, 0xff, 0x44, 0x3a, 0x3c, 0xff, 0x4e, 0x42, 0x44, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x34, 0x2e, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x3c, 0x35, 0x34, 0xff, 0x3b, 0x3a, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x3b, 0x3a, 0x34, 0xff, 0x44, 0x3a, 0x3c, 0xff, 0x42, 0x42, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, 0x49, 0x4a, 0x4c, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x3c, 0x35, 0x34, 0xff, 0x3c, 0x35, 0x34, 0xff, + 0x3b, 0x3a, 0x3c, 0xff, 0x40, 0x3f, 0x3c, 0xff, 0x44, 0x47, 0x44, 0xff, + 0x44, 0x47, 0x44, 0xff, 0x4c, 0x47, 0x44, 0xff, +}; + +#endif // WEBP_TESTS_FUZZER_IMG_PEAK_H_ diff --git a/third-party/webp/libwebp/tests/fuzzer/makefile.unix b/third-party/webp/libwebp/tests/fuzzer/makefile.unix new file mode 100644 index 0000000000..3a3aff0ab1 --- /dev/null +++ b/third-party/webp/libwebp/tests/fuzzer/makefile.unix @@ -0,0 +1,31 @@ +# This Makefile will compile all fuzzing targets. It doesn't check tool +# requirements and paths may need to be updated depending on your environment. +# Note a clang 6+ toolchain is assumed for use of -fsanitize=fuzzer. + +CC = clang +CXX = clang++ +CFLAGS = -fsanitize=fuzzer -I../../src -I../.. -Wall -Wextra +CXXFLAGS = $(CFLAGS) +LDFLAGS = -fsanitize=fuzzer +LDLIBS = ../../src/mux/libwebpmux.a ../../src/demux/libwebpdemux.a +LDLIBS += ../../src/libwebp.a ../../imageio/libimageio_util.a +LDLIBS += ../../sharpyuv/libsharpyuv.a + +FUZZERS = advanced_api_fuzzer animation_api_fuzzer animdecoder_fuzzer +FUZZERS += animencoder_fuzzer enc_dec_fuzzer huffman_fuzzer +FUZZERS += mux_demux_api_fuzzer simple_api_fuzzer + +%.o: fuzz_utils.h img_alpha.h img_grid.h img_peak.h +all: $(FUZZERS) + +define FUZZER_template +$(1): $$(addsuffix .o, $(1)) $(LDLIBS) +OBJS += $$(addsuffix .o, $(1)) +endef + +$(foreach fuzzer, $(FUZZERS), $(eval $(call FUZZER_template, $(fuzzer)))) + +clean: + $(RM) $(FUZZERS) $(OBJS) + +.PHONY: all clean diff --git a/third-party/webp/libwebp/tests/fuzzer/mux_demux_api_fuzzer.c b/third-party/webp/libwebp/tests/fuzzer/mux_demux_api_fuzzer.c new file mode 100644 index 0000000000..4ed0142757 --- /dev/null +++ b/third-party/webp/libwebp/tests/fuzzer/mux_demux_api_fuzzer.c @@ -0,0 +1,96 @@ +// Copyright 2018 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + +#include "./fuzz_utils.h" +#include "src/webp/demux.h" +#include "src/webp/mux.h" + +int LLVMFuzzerTestOneInput(const uint8_t* const data, size_t size) { + WebPData webp_data; + WebPDataInit(&webp_data); + webp_data.size = size; + webp_data.bytes = data; + + // Extracted chunks and frames are not processed or decoded, + // which is already covered extensively by the other fuzz targets. + + if (size & 1) { + // Mux API + WebPMux* mux = WebPMuxCreate(&webp_data, size & 2); + if (!mux) return 0; + + WebPData chunk; + WebPMuxGetChunk(mux, "EXIF", &chunk); + WebPMuxGetChunk(mux, "ICCP", &chunk); + WebPMuxGetChunk(mux, "FUZZ", &chunk); // unknown + + uint32_t flags; + WebPMuxGetFeatures(mux, &flags); + + WebPMuxAnimParams params; + WebPMuxGetAnimationParams(mux, ¶ms); + + WebPMuxError status; + WebPMuxFrameInfo info; + for (int i = 0; i < kFuzzFrameLimit; i++) { + status = WebPMuxGetFrame(mux, i + 1, &info); + if (status == WEBP_MUX_NOT_FOUND) { + break; + } else if (status == WEBP_MUX_OK) { + WebPDataClear(&info.bitstream); + } + } + + WebPMuxDelete(mux); + } else { + // Demux API + WebPDemuxer* demux; + if (size & 2) { + WebPDemuxState state; + demux = WebPDemuxPartial(&webp_data, &state); + if (state < WEBP_DEMUX_PARSED_HEADER) { + WebPDemuxDelete(demux); + return 0; + } + } else { + demux = WebPDemux(&webp_data); + if (!demux) return 0; + } + + WebPChunkIterator chunk_iter; + if (WebPDemuxGetChunk(demux, "EXIF", 1, &chunk_iter)) { + WebPDemuxNextChunk(&chunk_iter); + } + WebPDemuxReleaseChunkIterator(&chunk_iter); + if (WebPDemuxGetChunk(demux, "ICCP", 0, &chunk_iter)) { // 0 == last + WebPDemuxPrevChunk(&chunk_iter); + } + WebPDemuxReleaseChunkIterator(&chunk_iter); + // Skips FUZZ because the Demux API has no concept of (un)known chunks. + + WebPIterator iter; + if (WebPDemuxGetFrame(demux, 1, &iter)) { + for (int i = 1; i < kFuzzFrameLimit; i++) { + if (!WebPDemuxNextFrame(&iter)) break; + } + } + + WebPDemuxReleaseIterator(&iter); + WebPDemuxDelete(demux); + } + + return 0; +} diff --git a/third-party/webp/libwebp/tests/fuzzer/simple_api_fuzzer.c b/third-party/webp/libwebp/tests/fuzzer/simple_api_fuzzer.c new file mode 100644 index 0000000000..7d2b7f81a9 --- /dev/null +++ b/third-party/webp/libwebp/tests/fuzzer/simple_api_fuzzer.c @@ -0,0 +1,88 @@ +// Copyright 2018 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + +#include "./fuzz_utils.h" +#include "src/webp/decode.h" + +int LLVMFuzzerTestOneInput(const uint8_t* const data, size_t size) { + int w, h; + if (!WebPGetInfo(data, size, &w, &h)) return 0; + if ((size_t)w * h > kFuzzPxLimit) return 0; + + const uint8_t value = FuzzHash(data, size); + uint8_t* buf = NULL; + + // For *Into functions, which decode into an external buffer, an + // intentionally too small buffer can be given with low probability. + if (value < 0x16) { + buf = WebPDecodeRGBA(data, size, &w, &h); + } else if (value < 0x2b) { + buf = WebPDecodeBGRA(data, size, &w, &h); +#if !defined(WEBP_REDUCE_CSP) + } else if (value < 0x40) { + buf = WebPDecodeARGB(data, size, &w, &h); + } else if (value < 0x55) { + buf = WebPDecodeRGB(data, size, &w, &h); + } else if (value < 0x6a) { + buf = WebPDecodeBGR(data, size, &w, &h); +#endif // !defined(WEBP_REDUCE_CSP) + } else if (value < 0x7f) { + uint8_t *u, *v; + int stride, uv_stride; + buf = WebPDecodeYUV(data, size, &w, &h, &u, &v, &stride, &uv_stride); + } else if (value < 0xe8) { + const int stride = (value < 0xbe ? 4 : 3) * w; + size_t buf_size = stride * h; + if (value % 0x10 == 0) buf_size--; + uint8_t* const ext_buf = (uint8_t*)malloc(buf_size); + if (value < 0x94) { + WebPDecodeRGBAInto(data, size, ext_buf, buf_size, stride); +#if !defined(WEBP_REDUCE_CSP) + } else if (value < 0xa9) { + WebPDecodeARGBInto(data, size, ext_buf, buf_size, stride); + } else if (value < 0xbe) { + WebPDecodeBGRInto(data, size, ext_buf, buf_size, stride); + } else if (value < 0xd3) { + WebPDecodeRGBInto(data, size, ext_buf, buf_size, stride); +#endif // !defined(WEBP_REDUCE_CSP) + } else { + WebPDecodeBGRAInto(data, size, ext_buf, buf_size, stride); + } + free(ext_buf); + } else { + size_t luma_size = w * h; + const int uv_stride = (w + 1) / 2; + size_t u_size = uv_stride * (h + 1) / 2; + size_t v_size = uv_stride * (h + 1) / 2; + if (value % 0x10 == 0) { + if (size & 1) luma_size--; + if (size & 2) u_size--; + if (size & 4) v_size--; + } + uint8_t* const luma_buf = (uint8_t*)malloc(luma_size); + uint8_t* const u_buf = (uint8_t*)malloc(u_size); + uint8_t* const v_buf = (uint8_t*)malloc(v_size); + WebPDecodeYUVInto(data, size, luma_buf, luma_size, w /* luma_stride */, + u_buf, u_size, uv_stride, v_buf, v_size, uv_stride); + free(luma_buf); + free(u_buf); + free(v_buf); + } + + if (buf) WebPFree(buf); + + return 0; +} diff --git a/third-party/webp/libwebp/xcframeworkbuild.sh b/third-party/webp/libwebp/xcframeworkbuild.sh new file mode 100755 index 0000000000..8d484c2a53 --- /dev/null +++ b/third-party/webp/libwebp/xcframeworkbuild.sh @@ -0,0 +1,255 @@ +#!/bin/bash +# +# This script generates 'WebP.xcframework', 'WebPDecoder.xcframework', +# 'WebPDemux.xcframework' and 'WebPMux.xcframework'. +# An iOS, Mac or Mac Catalyst app can decode WebP images by including +# 'WebPDecoder.xcframework' and both encode and decode WebP images by including +# 'WebP.xcframework'. +# +# Run ./xcframeworkbuild.sh to generate the frameworks under the current +# directory (the previous build will be erased if it exists). +# + +set -e + +# Set these variables based on the desired minimum deployment target. +readonly IOS_MIN_VERSION=6.0 +readonly MACOSX_MIN_VERSION=10.15 +readonly MACOSX_CATALYST_MIN_VERSION=14.0 + +# Extract Xcode version. +readonly XCODE=$(xcodebuild -version | grep Xcode | cut -d " " -f2) +if [[ -z "${XCODE}" ]] || [[ "${XCODE%%.*}" -lt 11 ]]; then + echo "Xcode 11.0 or higher is required!" + exit 1 +fi + +# Extract the latest SDK version from the final field of the form: iphoneosX.Y +# / macosxX.Y +readonly SDK=($( + xcodebuild -showsdks \ + | grep iphoneos | sort | tail -n 1 | awk '{print substr($NF, 9)}' + xcodebuild -showsdks \ + | grep macosx | sort | tail -n 1 | awk '{print substr($NF, 7)}' +)) +readonly IOS=0 +readonly MACOS=1 +readonly IOS_SIMULATOR=2 +readonly MACOS_CATALYST=3 +readonly NUM_PLATFORMS=4 + +readonly OLDPATH=${PATH} + +# Names should be of the form '-[-]'. +PLATFORMS[$IOS]="iPhoneOS-armv7 iPhoneOS-armv7s iPhoneOS-arm64" +PLATFORMS[$IOS_SIMULATOR]="iPhoneSimulator-i386 iPhoneSimulator-x86_64" +PLATFORMS[$MACOS]="MacOSX-x86_64" +PLATFORMS[$MACOS_CATALYST]="MacOSX-Catalyst-x86_64" +if [[ "${XCODE%%.*}" -ge 12 ]]; then + PLATFORMS[$MACOS]+=" MacOSX-arm64" + PLATFORMS[$MACOS_CATALYST]+=" MacOSX-Catalyst-arm64" + PLATFORMS[$IOS_SIMULATOR]+=" iPhoneSimulator-arm64" +elif [[ "${XCODE%%.*}" -eq 11 ]]; then + cat << EOF +WARNING: Xcode 12.0 or higher is required to build targets for +WARNING: Apple Silicon (arm64). The XCFrameworks generated with Xcode 11 will +WARNING: contain libraries for MacOS & Catalyst supporting x86_64 only. +WARNING: The build will continue in 5 seconds... +EOF + sleep 5 +else + echo "Xcode 11.0 or higher is required!" + exit 1 +fi +readonly PLATFORMS +readonly SRCDIR=$(dirname $0) +readonly TOPDIR=$(pwd) +readonly BUILDDIR="${TOPDIR}/xcframeworkbuild" +readonly TARGETDIR="${TOPDIR}/WebP.xcframework" +readonly DECTARGETDIR="${TOPDIR}/WebPDecoder.xcframework" +readonly MUXTARGETDIR="${TOPDIR}/WebPMux.xcframework" +readonly DEMUXTARGETDIR="${TOPDIR}/WebPDemux.xcframework" +readonly DEVELOPER=$(xcode-select --print-path) +readonly DEVROOT="${DEVELOPER}/Toolchains/XcodeDefault.xctoolchain" +readonly PLATFORMSROOT="${DEVELOPER}/Platforms" +readonly LIPO=$(xcrun -sdk iphoneos${SDK[$IOS]} -find lipo) + +if [[ -z "${SDK[$IOS]}" ]] || [[ ${SDK[$IOS]%%.*} -lt 8 ]]; then + echo "iOS SDK version 8.0 or higher is required!" + exit 1 +fi + +####################################### +# Moves Headers/*.h to Headers// +# +# Places framework headers in a subdirectory to avoid Xcode errors when using +# multiple frameworks: +# error: Multiple commands produce +# '.../Build/Products/Debug-iphoneos/include/types.h' +# Arguments: +# $1 - path to framework +####################################### +update_headers_path() { + local framework_name="$(basename ${1%.xcframework})" + local subdir + for d in $(find "$1" -path "*/Headers"); do + subdir="$d/$framework_name" + mkdir "$subdir" + mv "$d/"*.h "$subdir" + done +} + +echo "Xcode Version: ${XCODE}" +echo "iOS SDK Version: ${SDK[$IOS]}" +echo "MacOS SDK Version: ${SDK[$MACOS]}" + +if [[ -e "${BUILDDIR}" || -e "${TARGETDIR}" || -e "${DECTARGETDIR}" \ + || -e "${MUXTARGETDIR}" || -e "${DEMUXTARGETDIR}" ]]; then + cat << EOF +WARNING: The following directories will be deleted: +WARNING: ${BUILDDIR} +WARNING: ${TARGETDIR} +WARNING: ${DECTARGETDIR} +WARNING: ${MUXTARGETDIR} +WARNING: ${DEMUXTARGETDIR} +WARNING: The build will continue in 5 seconds... +EOF + sleep 5 +fi +rm -rf ${BUILDDIR} ${TARGETDIR} ${DECTARGETDIR} \ + ${MUXTARGETDIR} ${DEMUXTARGETDIR} + +if [[ ! -e ${SRCDIR}/configure ]]; then + if ! (cd ${SRCDIR} && sh autogen.sh); then + cat << EOF +Error creating configure script! +This script requires the autoconf/automake and libtool to build. MacPorts or +Homebrew can be used to obtain these: +https://www.macports.org/install.php +https://brew.sh/ +EOF + exit 1 + fi +fi + +for (( i = 0; i < $NUM_PLATFORMS; ++i )); do + LIBLIST=() + DECLIBLIST=() + MUXLIBLIST=() + DEMUXLIBLIST=() + + for PLATFORM in ${PLATFORMS[$i]}; do + ROOTDIR="${BUILDDIR}/${PLATFORM}" + mkdir -p "${ROOTDIR}" + + ARCH="${PLATFORM##*-}" + case "${PLATFORM}" in + iPhone*) + sdk="${SDK[$IOS]}" + ;; + MacOS*) + sdk="${SDK[$MACOS]}" + ;; + *) + echo "Unrecognized platform: ${PLATFORM}!" + exit 1 + ;; + esac + + SDKROOT="${PLATFORMSROOT}/${PLATFORM%%-*}.platform/" + SDKROOT+="Developer/SDKs/${PLATFORM%%-*}${sdk}.sdk/" + CFLAGS="-pipe -isysroot ${SDKROOT} -O3 -DNDEBUG" + case "${PLATFORM}" in + iPhone*) + CFLAGS+=" -fembed-bitcode" + CFLAGS+=" -target ${ARCH}-apple-ios${IOS_MIN_VERSION}" + [[ "${PLATFORM}" == *Simulator* ]] && CFLAGS+="-simulator" + ;; + MacOSX-Catalyst*) + CFLAGS+=" -target" + CFLAGS+=" ${ARCH}-apple-ios${MACOSX_CATALYST_MIN_VERSION}-macabi" + ;; + MacOSX*) + CFLAGS+=" -mmacosx-version-min=${MACOSX_MIN_VERSION}" + ;; + esac + + set -x + export PATH="${DEVROOT}/usr/bin:${OLDPATH}" + ${SRCDIR}/configure --host=${ARCH/arm64/aarch64}-apple-darwin \ + --build=$(${SRCDIR}/config.guess) \ + --prefix=${ROOTDIR} \ + --disable-shared --enable-static \ + --enable-libwebpdecoder --enable-swap-16bit-csp \ + --enable-libwebpmux \ + CC="clang -arch ${ARCH}" \ + CFLAGS="${CFLAGS}" + set +x + + # Build only the libraries, skip the examples. + make V=0 -C sharpyuv + make V=0 -C src install + + LIBLIST+=("${ROOTDIR}/lib/libwebp.a") + DECLIBLIST+=("${ROOTDIR}/lib/libwebpdecoder.a") + MUXLIBLIST+=("${ROOTDIR}/lib/libwebpmux.a") + DEMUXLIBLIST+=("${ROOTDIR}/lib/libwebpdemux.a") + # xcodebuild requires a directory for the -headers option, these will match + # for all builds. + make -C src install-data DESTDIR="${ROOTDIR}/lib-headers" + make -C src install-commonHEADERS DESTDIR="${ROOTDIR}/dec-headers" + make -C src/demux install-data DESTDIR="${ROOTDIR}/demux-headers" + make -C src/mux install-data DESTDIR="${ROOTDIR}/mux-headers" + LIB_HEADERS="${ROOTDIR}/lib-headers/${ROOTDIR}/include/webp" + DEC_HEADERS="${ROOTDIR}/dec-headers/${ROOTDIR}/include/webp" + DEMUX_HEADERS="${ROOTDIR}/demux-headers/${ROOTDIR}/include/webp" + MUX_HEADERS="${ROOTDIR}/mux-headers/${ROOTDIR}/include/webp" + + make distclean + + export PATH=${OLDPATH} + done + + [[ -z "${LIBLIST[@]}" ]] && continue + + # Create a temporary target directory for each [-]. + target_dir="${BUILDDIR}/${PLATFORMS[$i]}" + target_dir="${target_dir%% *}" + target_dir="${target_dir%-*}" + target_lib="${target_dir}/$(basename ${LIBLIST[0]})" + target_declib="${target_dir}/$(basename ${DECLIBLIST[0]})" + target_demuxlib="${target_dir}/$(basename ${DEMUXLIBLIST[0]})" + target_muxlib="${target_dir}/$(basename ${MUXLIBLIST[0]})" + + mkdir -p "${target_dir}" + ${LIPO} -create ${LIBLIST[@]} -output "${target_lib}" + ${LIPO} -create ${DECLIBLIST[@]} -output "${target_declib}" + ${LIPO} -create ${DEMUXLIBLIST[@]} -output "${target_demuxlib}" + ${LIPO} -create ${MUXLIBLIST[@]} -output "${target_muxlib}" + FAT_LIBLIST+=(-library "${target_lib}" -headers "${LIB_HEADERS}") + FAT_DECLIBLIST+=(-library "${target_declib}" -headers "${DEC_HEADERS}") + FAT_DEMUXLIBLIST+=(-library "${target_demuxlib}" -headers "${DEMUX_HEADERS}") + FAT_MUXLIBLIST+=(-library "${target_muxlib}" -headers "${MUX_HEADERS}") +done + +# lipo will not put archives with the same architecture (e.g., x86_64 +# iPhoneSimulator & MacOS) in the same fat output file. xcodebuild +# -create-xcframework requires universal archives to avoid e.g.: +# Both ios-x86_64-maccatalyst and ios-arm64-maccatalyst represent two +# equivalent library definitions +set -x +xcodebuild -create-xcframework "${FAT_LIBLIST[@]}" \ + -output ${TARGETDIR} +xcodebuild -create-xcframework "${FAT_DECLIBLIST[@]}" \ + -output ${DECTARGETDIR} +xcodebuild -create-xcframework "${FAT_DEMUXLIBLIST[@]}" \ + -output ${DEMUXTARGETDIR} +xcodebuild -create-xcframework "${FAT_MUXLIBLIST[@]}" \ + -output ${MUXTARGETDIR} +update_headers_path "${TARGETDIR}" +update_headers_path "${DECTARGETDIR}" +update_headers_path "${DEMUXTARGETDIR}" +update_headers_path "${MUXTARGETDIR}" +set +x + +echo "SUCCESS"