├── .clang-format ├── .github └── workflows │ ├── cifuzz.yml │ ├── cmake_android.yml │ ├── cmake_linux.yml │ ├── cmake_mac.yml │ └── cmake_win.yml ├── .gitignore ├── Android.bp ├── CMakeLists.txt ├── DESCRIPTION ├── LICENSE ├── README.md ├── adobe-hdr-gain-map-license ├── Android.bp └── NOTICE ├── benchmark ├── Android.bp ├── AndroidTest.xml ├── DynamicConfig.xml └── benchmark_test.cpp ├── cmake ├── FindEGL.cmake ├── FindOpenGLES3.cmake ├── cmake_uninstall.cmake.in ├── libuhdr.pc.in ├── package.cmake └── toolchains │ ├── aarch64-linux-gnu.cmake │ ├── android.cmake │ ├── arm-linux-gnueabihf.cmake │ ├── loong64-linux-gnu.cmake │ ├── riscv32-linux-gnu.cmake │ └── riscv64-linux-gnu.cmake ├── docs ├── building.md ├── code-of-conduct.md ├── contributing.md ├── fuzzers.md └── jpegr_format.png ├── examples ├── Android.bp ├── metadata.cfg └── ultrahdr_app.cpp ├── fuzzer ├── Android.bp ├── ossfuzz.sh ├── ultrahdr_dec_fuzzer.cpp ├── ultrahdr_enc_fuzzer.cpp └── ultrahdr_legacy_fuzzer.cpp ├── java ├── UltraHdrApp.java ├── com │ └── google │ │ └── media │ │ └── codecs │ │ └── ultrahdr │ │ ├── UltraHDRCommon.java │ │ ├── UltraHDRDecoder.java │ │ └── UltraHDREncoder.java ├── jni │ ├── com_google_media_codecs_ultrahdr_UltraHDRCommon.h │ ├── com_google_media_codecs_ultrahdr_UltraHDRDecoder.h │ ├── com_google_media_codecs_ultrahdr_UltraHDREncoder.h │ └── ultrahdr-jni.cpp └── metadata.cfg ├── lib ├── include │ └── ultrahdr │ │ ├── dsp │ │ └── arm │ │ │ └── mem_neon.h │ │ ├── editorhelper.h │ │ ├── gainmapmath.h │ │ ├── gainmapmetadata.h │ │ ├── icc.h │ │ ├── jpegdecoderhelper.h │ │ ├── jpegencoderhelper.h │ │ ├── jpegr.h │ │ ├── jpegrutils.h │ │ ├── multipictureformat.h │ │ ├── ultrahdr.h │ │ └── ultrahdrcommon.h └── src │ ├── dsp │ └── arm │ │ ├── editorhelper_neon.cpp │ │ └── gainmapmath_neon.cpp │ ├── editorhelper.cpp │ ├── gainmapmath.cpp │ ├── gainmapmetadata.cpp │ ├── gpu │ ├── applygainmap_gl.cpp │ ├── editorhelper_gl.cpp │ └── uhdr_gl_utils.cpp │ ├── icc.cpp │ ├── jpegdecoderhelper.cpp │ ├── jpegencoderhelper.cpp │ ├── jpegr.cpp │ ├── jpegrutils.cpp │ ├── multipictureformat.cpp │ └── ultrahdr_api.cpp ├── tests ├── Android.bp ├── AndroidTest.xml ├── data │ ├── LICENSE │ ├── jpeg_image.jpg │ ├── minnie-318x240.yu12 │ ├── minnie-320x240-rgb.jpg │ ├── minnie-320x240-y.jpg │ ├── minnie-320x240-yuv-icc.jpg │ ├── minnie-320x240-yuv.jpg │ ├── minnie-320x240.rgb │ ├── minnie-320x240.y │ ├── minnie-320x240.yu12 │ ├── raw_p010_image.p010 │ └── raw_yuv420_image.yuv420 ├── editorhelper_test.cpp ├── gainmapmath_test.cpp ├── gainmapmetadata_test.cpp ├── icchelper_test.cpp ├── jpegdecoderhelper_test.cpp ├── jpegencoderhelper_test.cpp └── jpegr_test.cpp ├── third_party └── image_io │ ├── LICENSE │ ├── METADATA │ ├── MODULE_LICENSE_APACHE2 │ ├── README.android │ ├── includes │ └── image_io │ │ ├── base │ │ ├── byte_buffer.h │ │ ├── byte_data.h │ │ ├── byte_pointer_data_destination.h │ │ ├── cout_message_writer.h │ │ ├── data_context.h │ │ ├── data_destination.h │ │ ├── data_line_map.h │ │ ├── data_line_map_builder_destination.h │ │ ├── data_match_result.h │ │ ├── data_range.h │ │ ├── data_range_tracking_destination.h │ │ ├── data_scanner.h │ │ ├── data_segment.h │ │ ├── data_segment_data_source.h │ │ ├── data_source.h │ │ ├── image_metadata.h │ │ ├── istream_data_source.h │ │ ├── istream_ref_data_source.h │ │ ├── message.h │ │ ├── message_handler.h │ │ ├── message_stats.h │ │ ├── message_store.h │ │ ├── message_writer.h │ │ ├── ostream_data_destination.h │ │ ├── ostream_ref_data_destination.h │ │ ├── string_ref_data_source.h │ │ ├── types.h │ │ └── validated_number.h │ │ ├── extras │ │ └── base64_decoder_data_destination.h │ │ ├── gcontainer │ │ └── gcontainer.h │ │ ├── jpeg │ │ ├── jpeg_image_extractor.h │ │ ├── jpeg_info.h │ │ ├── jpeg_info_builder.h │ │ ├── jpeg_marker.h │ │ ├── jpeg_scanner.h │ │ ├── jpeg_segment.h │ │ ├── jpeg_segment_builder.h │ │ ├── jpeg_segment_info.h │ │ ├── jpeg_segment_lister.h │ │ ├── jpeg_segment_processor.h │ │ ├── jpeg_xmp_data_extractor.h │ │ ├── jpeg_xmp_info.h │ │ └── jpeg_xmp_info_builder.h │ │ ├── utils │ │ ├── file_utils.h │ │ ├── message_stats_writer.h │ │ ├── string_outputter.h │ │ └── string_outputter_message_writer.h │ │ └── xml │ │ ├── xml_action.h │ │ ├── xml_attribute_rule.h │ │ ├── xml_cdata_and_comment_rules.h │ │ ├── xml_element_rules.h │ │ ├── xml_handler.h │ │ ├── xml_handler_context.h │ │ ├── xml_pi_rule.h │ │ ├── xml_portion.h │ │ ├── xml_reader.h │ │ ├── xml_rule.h │ │ ├── xml_terminal.h │ │ ├── xml_token_context.h │ │ └── xml_writer.h │ └── src │ ├── base │ ├── byte_buffer.cc │ ├── byte_pointer_data_destination.cc │ ├── data_context.cc │ ├── data_line_map.cc │ ├── data_range_tracking_destination.cc │ ├── data_scanner.cc │ ├── data_segment.cc │ ├── data_segment_data_source.cc │ ├── istream_ref_data_source.cc │ ├── message_handler.cc │ ├── message_writer.cc │ ├── ostream_ref_data_destination.cc │ └── string_ref_data_source.cc │ ├── extras │ └── base64_decoder_data_destination.cc │ ├── gcontainer │ └── gcontainer.cc │ ├── jpeg │ ├── jpeg_image_extractor.cc │ ├── jpeg_info_builder.cc │ ├── jpeg_marker.cc │ ├── jpeg_scanner.cc │ ├── jpeg_segment.cc │ ├── jpeg_segment_builder.cc │ ├── jpeg_segment_lister.cc │ ├── jpeg_xmp_data_extractor.cc │ ├── jpeg_xmp_info.cc │ └── jpeg_xmp_info_builder.cc │ ├── modp_b64 │ ├── BUILD.gn │ ├── DEPS │ ├── LICENSE │ ├── METADATA │ ├── MODULE_LICENSE_BSD │ ├── Makefile │ ├── README.chromium │ ├── common.mk │ ├── modp_b64.cc │ ├── modp_b64.gyp │ ├── modp_b64 │ │ └── modp_b64.h │ ├── modp_b64_data.h │ └── modp_b64_nacl.gyp │ ├── utils │ └── file_utils.cc │ └── xml │ ├── xml_attribute_rule.cc │ ├── xml_cdata_and_comment_rules.cc │ ├── xml_element_rules.cc │ ├── xml_handler.cc │ ├── xml_pi_rule.cc │ ├── xml_reader.cc │ ├── xml_rule.cc │ ├── xml_token_context.cc │ └── xml_writer.cc └── ultrahdr_api.h /.clang-format: -------------------------------------------------------------------------------- 1 | # Run manually to reformat a file: 2 | # clang-format -i --style=file 3 | 4 | Language: Cpp 5 | BasedOnStyle: Google 6 | ColumnLimit: 100 7 | SortIncludes: false 8 | -------------------------------------------------------------------------------- /.github/workflows/cifuzz.yml: -------------------------------------------------------------------------------- 1 | name: CIFuzz 2 | on: [pull_request] 3 | jobs: 4 | Fuzzing: 5 | runs-on: ubuntu-latest 6 | strategy: 7 | matrix: 8 | sanitizer: [address, memory] 9 | steps: 10 | - name: Build Fuzzers 11 | id: build 12 | uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master 13 | with: 14 | oss-fuzz-project-name: 'libultrahdr' 15 | language: c++ 16 | - name: Run Fuzzers 17 | uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master 18 | with: 19 | oss-fuzz-project-name: 'libultrahdr' 20 | language: c++ 21 | fuzz-seconds: 600 22 | - name: Upload Crash 23 | uses: actions/upload-artifact@v4 24 | if: failure() && steps.build.outcome == 'success' 25 | with: 26 | name: artifacts 27 | path: ./out/artifacts 28 | -------------------------------------------------------------------------------- /.github/workflows/cmake_android.yml: -------------------------------------------------------------------------------- 1 | name: Build CI - Android 2 | # Build CI for Android 3 | 4 | on: [ push, pull_request ] 5 | 6 | jobs: 7 | build: 8 | runs-on: ${{ matrix.os }} 9 | 10 | strategy: 11 | fail-fast: true 12 | matrix: 13 | os: [ubuntu-latest] 14 | abi: [armeabi-v7a, arm64-v8a, x86, x86_64] 15 | 16 | steps: 17 | - name: Checkout the repository 18 | uses: actions/checkout@v3 19 | 20 | - name: Set up JDK 17 21 | uses: actions/setup-java@v3 22 | with: 23 | java-version: '17' 24 | distribution: 'temurin' 25 | 26 | - name: Download and Setup the Android NDK 27 | uses: nttld/setup-ndk@v1 28 | id: setup-ndk 29 | with: 30 | # r25c is the same as 25.2.9519653. 31 | ndk-version: r25c 32 | add-to-path: false 33 | 34 | - name: Setup ninja 35 | uses: seanmiddleditch/gha-setup-ninja@master 36 | 37 | - name: Setup cmake 38 | uses: jwlawson/actions-setup-cmake@v2 39 | 40 | - name: Configure CMake 41 | shell: bash 42 | run: | 43 | mkdir build 44 | cmake -G Ninja -B build -DCMAKE_TOOLCHAIN_FILE=./cmake/toolchains/android.cmake -DUHDR_ANDROID_NDK_PATH=${{ steps.setup-ndk.outputs.ndk-path }} -DUHDR_BUILD_TESTS=1 -DUHDR_ENABLE_LOGS=1 -DUHDR_BUILD_DEPS=1 -DANDROID_ABI=${{ matrix.abi }} -DANDROID_PLATFORM=android-23 -DUHDR_BUILD_JAVA=1 -DUHDR_ENABLE_WERROR=1 45 | 46 | - name: Build 47 | run: cmake --build build 48 | -------------------------------------------------------------------------------- /.github/workflows/cmake_linux.yml: -------------------------------------------------------------------------------- 1 | name: Build and Test CI - Linux 2 | # Build and Test CI for ubuntu-latest 3 | 4 | on: [ push, pull_request ] 5 | 6 | jobs: 7 | build: 8 | name: ${{ matrix.config.name }} 9 | runs-on: ${{ matrix.config.os }} 10 | strategy: 11 | fail-fast: true 12 | matrix: 13 | config: 14 | # 15 | - name: "ubuntu latest gcc rel ninja" 16 | os: ubuntu-latest 17 | build_type: Release 18 | cc: gcc 19 | cxx: g++ 20 | cmake-opts: '-DUHDR_BUILD_TESTS=1 -DUHDR_ENABLE_LOGS=1 -DUHDR_ENABLE_INSTALL=1 -DUHDR_ENABLE_WERROR=1' 21 | 22 | # 23 | - name: "ubuntu latest clang rel ninja" 24 | os: ubuntu-latest 25 | build_type: Release 26 | cc: clang 27 | cxx: clang++ 28 | cmake-opts: '-DUHDR_BUILD_TESTS=1 -DUHDR_ENABLE_LOGS=1 -DUHDR_ENABLE_INSTALL=1 -DUHDR_ENABLE_WERROR=1' 29 | 30 | # 31 | - name: "ubuntu latest gcc rel ninja with deps" 32 | os: ubuntu-latest 33 | build_type: Release 34 | cc: gcc 35 | cxx: g++ 36 | cmake-opts: '-DUHDR_BUILD_TESTS=1 -DUHDR_ENABLE_LOGS=1 -DUHDR_BUILD_DEPS=1 -DUHDR_ENABLE_WERROR=1' 37 | 38 | # 39 | - name: "ubuntu latest clang rel ninja with deps sanitize address" 40 | os: ubuntu-latest 41 | build_type: Release 42 | cc: clang 43 | cxx: clang++ 44 | cmake-opts: '-DUHDR_BUILD_TESTS=1 -DUHDR_ENABLE_LOGS=1 -DUHDR_BUILD_DEPS=1 -DUHDR_SANITIZE_OPTIONS=address -DUHDR_ENABLE_WERROR=1' 45 | 46 | # 47 | - name: "ubuntu latest clang rel ninja fuzzers sanitize address" 48 | os: ubuntu-latest 49 | build_type: Release 50 | cc: clang 51 | cxx: clang++ 52 | cmake-opts: '-DUHDR_BUILD_FUZZERS=1 -DUHDR_SANITIZE_OPTIONS=address -DUHDR_ENABLE_WERROR=1' 53 | 54 | # 55 | - name: "ubuntu latest gcc rel ninja static" 56 | os: ubuntu-latest 57 | build_type: Release 58 | cc: gcc 59 | cxx: g++ 60 | cmake-opts: '-DUHDR_BUILD_TESTS=1 -DUHDR_ENABLE_LOGS=1 -DUHDR_ENABLE_INSTALL=1 -DBUILD_SHARED_LIBS=0 -DUHDR_ENABLE_WERROR=1' 61 | 62 | # 63 | - name: "ubuntu latest clang rel ninja static" 64 | os: ubuntu-latest 65 | build_type: Release 66 | cc: clang 67 | cxx: clang++ 68 | cmake-opts: '-DUHDR_BUILD_TESTS=1 -DUHDR_ENABLE_LOGS=1 -DUHDR_ENABLE_INSTALL=1 -DBUILD_SHARED_LIBS=0 -DUHDR_ENABLE_WERROR=1' 69 | 70 | steps: 71 | - name: Checkout the repository 72 | uses: actions/checkout@v4 73 | 74 | - name: Setup ninja 75 | uses: seanmiddleditch/gha-setup-ninja@master 76 | 77 | - name: Setup cmake 78 | uses: jwlawson/actions-setup-cmake@v2 79 | 80 | - name: Install dependencies on Ubuntu 81 | run: sudo apt install -y libjpeg-dev 82 | 83 | - name: Configure CMake 84 | shell: bash 85 | run: | 86 | export CC=${{ matrix.config.cc }} 87 | export CXX=${{ matrix.config.cxx }} 88 | mkdir build 89 | cmake -G Ninja -B build -DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} ${{ matrix.config.cmake-opts }} 90 | 91 | - name: Build 92 | run: cmake --build build --config ${{ matrix.config.build_type }} 93 | 94 | - name: Test 95 | working-directory: build 96 | run: ctest --build-config ${{ matrix.config.build_type }} -------------------------------------------------------------------------------- /.github/workflows/cmake_mac.yml: -------------------------------------------------------------------------------- 1 | name: Build and Test CI - macOS 2 | # Build and Test CI for macOS-latest 3 | 4 | on: [ push, pull_request ] 5 | 6 | jobs: 7 | build: 8 | name: ${{ matrix.config.name }} 9 | runs-on: ${{ matrix.config.os }} 10 | strategy: 11 | fail-fast: true 12 | matrix: 13 | config: 14 | # 15 | - name: "macOS latest ARM64 clang rel ninja" 16 | os: macos-latest 17 | build_type: Release 18 | cc: clang 19 | cxx: clang++ 20 | cmake-opts: '-DUHDR_BUILD_TESTS=1 -DUHDR_ENABLE_LOGS=1 -DUHDR_ENABLE_INSTALL=1 -DUHDR_ENABLE_WERROR=1' 21 | 22 | # 23 | - name: "macOS-13 clang rel ninja" 24 | os: macos-13 25 | build_type: Release 26 | cc: clang 27 | cxx: clang++ 28 | cmake-opts: '-DUHDR_BUILD_TESTS=1 -DUHDR_ENABLE_LOGS=1 -DUHDR_ENABLE_INSTALL=1 -DUHDR_ENABLE_WERROR=1' 29 | 30 | # 31 | - name: "macOS latest ARM64 clang rel ninja with deps" 32 | os: macos-latest 33 | build_type: Release 34 | cc: clang 35 | cxx: clang++ 36 | cmake-opts: '-DUHDR_BUILD_TESTS=1 -DUHDR_ENABLE_LOGS=1 -DUHDR_BUILD_DEPS=1 -DUHDR_ENABLE_WERROR=1' 37 | 38 | # 39 | - name: "macOS latest ARM64 clang rel ninja static" 40 | os: macos-latest 41 | build_type: Release 42 | cc: clang 43 | cxx: clang++ 44 | cmake-opts: '-DUHDR_BUILD_TESTS=1 -DUHDR_ENABLE_LOGS=1 -DUHDR_ENABLE_INSTALL=1 -DBUILD_SHARED_LIBS=0 -DUHDR_ENABLE_WERROR=1' 45 | 46 | # 47 | - name: "macOS-13 clang rel ninja static" 48 | os: macos-13 49 | build_type: Release 50 | cc: clang 51 | cxx: clang++ 52 | cmake-opts: '-DUHDR_BUILD_TESTS=1 -DUHDR_ENABLE_LOGS=1 -DUHDR_ENABLE_INSTALL=1 -DBUILD_SHARED_LIBS=0 -DUHDR_ENABLE_WERROR=1' 53 | 54 | steps: 55 | - name: Checkout the repository 56 | uses: actions/checkout@v4 57 | 58 | - name: Setup ninja 59 | uses: seanmiddleditch/gha-setup-ninja@master 60 | 61 | - name: Setup cmake 62 | uses: jwlawson/actions-setup-cmake@v2 63 | 64 | - name: Install dependencies on macOS 65 | run: | 66 | if ! command -v pkg-config &> /dev/null; then 67 | brew install pkg-config 68 | fi 69 | if ! brew list jpeg-turbo &> /dev/null; then 70 | brew install jpeg-turbo 71 | fi 72 | 73 | - name: Configure CMake 74 | shell: bash 75 | run: | 76 | export CC=${{ matrix.config.cc }} 77 | export CXX=${{ matrix.config.cxx }} 78 | mkdir build 79 | cmake -G Ninja -B build -DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} ${{ matrix.config.cmake-opts }} 80 | 81 | - name: Build 82 | run: cmake --build build --config ${{ matrix.config.build_type }} 83 | 84 | - name: Test 85 | working-directory: build 86 | run: ctest --build-config ${{ matrix.config.build_type }} -------------------------------------------------------------------------------- /.github/workflows/cmake_win.yml: -------------------------------------------------------------------------------- 1 | name: Build and Test CI - Windows 2 | # Build and Test CI for windows-latest 3 | 4 | on: [ push, pull_request ] 5 | 6 | jobs: 7 | build: 8 | name: ${{ matrix.config.name }} 9 | runs-on: ${{ matrix.config.os }} 10 | strategy: 11 | fail-fast: true 12 | matrix: 13 | config: 14 | # 15 | - name: "windows latest cl rel visual studio 17 2022 with deps" 16 | os: windows-latest 17 | build_type: Release 18 | cc: cl 19 | cxx: cl 20 | cmake-opts: '-DUHDR_BUILD_TESTS=1 -DUHDR_ENABLE_LOGS=1 -DUHDR_BUILD_DEPS=1 -DUHDR_ENABLE_WERROR=1' 21 | 22 | steps: 23 | - name: Checkout the repository 24 | uses: actions/checkout@v4 25 | 26 | - name: Setup cmake 27 | uses: jwlawson/actions-setup-cmake@v2 28 | 29 | - name: Configure CMake 30 | shell: bash 31 | run: | 32 | export CC=${{ matrix.config.cc }} 33 | export CXX=${{ matrix.config.cxx }} 34 | mkdir build 35 | cmake -G "Visual Studio 17 2022" -B build -DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} ${{ matrix.config.cmake-opts }} 36 | 37 | - name: Build 38 | run: cmake --build build --config ${{ matrix.config.build_type }} 39 | 40 | - name: Test 41 | working-directory: build 42 | run: ctest --build-config ${{ matrix.config.build_type }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # build output directories 2 | build 3 | build* 4 | 5 | # downloaded dependencies 6 | third_party/googletest 7 | third_party/turbojpeg 8 | third_party/benchmark 9 | tests/data -------------------------------------------------------------------------------- /Android.bp: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Android Open Source Project 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package { 16 | // See: http://go/android-license-faq 17 | default_applicable_licenses: [ 18 | "external_libultrahdr_license", 19 | "adobe_hdr_gain_map_license", 20 | ], 21 | } 22 | 23 | license { 24 | name: "external_libultrahdr_license", 25 | visibility: [":__subpackages__"], 26 | license_kinds: [ 27 | "SPDX-license-identifier-Apache-2.0", 28 | ], 29 | license_text: [ 30 | "LICENSE", 31 | ], 32 | } 33 | 34 | cc_library { 35 | name: "libultrahdr", 36 | host_supported: true, 37 | vendor_available: true, 38 | export_include_dirs: [ 39 | ".", 40 | "lib/include", 41 | ], 42 | local_include_dirs: ["lib/include"], 43 | cflags: ["-DUHDR_ENABLE_INTRINSICS", 44 | "-DUHDR_WRITE_XMP",], 45 | srcs: [ 46 | "lib/src/icc.cpp", 47 | "lib/src/jpegr.cpp", 48 | "lib/src/gainmapmath.cpp", 49 | "lib/src/gainmapmetadata.cpp", 50 | "lib/src/jpegrutils.cpp", 51 | "lib/src/multipictureformat.cpp", 52 | "lib/src/editorhelper.cpp", 53 | "lib/src/ultrahdr_api.cpp", 54 | ], 55 | shared_libs: [ 56 | "libimage_io", 57 | "libjpeg", 58 | "libjpegencoder", 59 | "libjpegdecoder", 60 | "liblog", 61 | ], 62 | rtti: true, 63 | target: { 64 | windows: { 65 | enabled: true, 66 | }, 67 | android: { 68 | srcs: [ 69 | "lib/src/gpu/applygainmap_gl.cpp", 70 | "lib/src/gpu/editorhelper_gl.cpp", 71 | "lib/src/gpu/uhdr_gl_utils.cpp", 72 | ], 73 | cflags: ["-DUHDR_ENABLE_GLES"], 74 | shared_libs: [ 75 | "libEGL", 76 | "libGLESv3", 77 | ], 78 | }, 79 | }, 80 | arch: { 81 | arm: { 82 | srcs: [ 83 | "lib/src/dsp/arm/editorhelper_neon.cpp", 84 | "lib/src/dsp/arm/gainmapmath_neon.cpp", 85 | ], 86 | }, 87 | arm64: { 88 | srcs: [ 89 | "lib/src/dsp/arm/editorhelper_neon.cpp", 90 | "lib/src/dsp/arm/gainmapmath_neon.cpp", 91 | ], 92 | }, 93 | }, 94 | } 95 | 96 | cc_library { 97 | name: "libjpegencoder", 98 | host_supported: true, 99 | vendor_available: true, 100 | shared_libs: [ 101 | "libjpeg", 102 | "liblog", 103 | ], 104 | export_include_dirs: ["lib/include"], 105 | srcs: [ 106 | "lib/src/jpegencoderhelper.cpp", 107 | ], 108 | target: { 109 | windows: { 110 | enabled: true, 111 | }, 112 | }, 113 | } 114 | 115 | cc_library { 116 | name: "libjpegdecoder", 117 | host_supported: true, 118 | vendor_available: true, 119 | shared_libs: [ 120 | "libjpeg", 121 | "liblog", 122 | ], 123 | export_include_dirs: ["lib/include"], 124 | srcs: [ 125 | "lib/src/jpegdecoderhelper.cpp", 126 | ], 127 | target: { 128 | windows: { 129 | enabled: true, 130 | }, 131 | }, 132 | } 133 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | libultrahdr is an image compression library that uses gain map technology 2 | to store and distribute HDR images. Conceptually on the encoding side, the 3 | library accepts SDR and HDR rendition of an image and from these a Gain Map 4 | (quotient between the two renditions) is computed. The library then uses 5 | backward compatible means to store the base image (SDR), gain map image and 6 | some associated metadata. Legacy readers that do not support handling the 7 | gain map image and/or metadata, will display the base image. Readers that 8 | support the format combine the base image with the gain map and render a 9 | high dynamic range image on compatible displays. 10 | 11 | For additional information, see android hdr-image-format 12 | https://developer.android.com/guide/topics/media/platform/hdr-image-format. 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Introduction 2 | 3 | libultrahdr is an image compression library that uses gain map technology 4 | to store and distribute HDR images. Conceptually on the encoding side, the 5 | library accepts SDR and HDR rendition of an image and from these a Gain Map 6 | (quotient between the two renditions) is computed. The library then uses 7 | backward compatible means to store the base image (SDR), gain map image and 8 | some associated metadata. Legacy readers that do not support handling the 9 | gain map image and/or metadata, will display the base image. Readers that 10 | support the format combine the base image with the gain map and render a 11 | high dynamic range image on compatible displays. 12 | 13 | For additional information, see android hdr-image-format 14 | [guide](https://developer.android.com/guide/topics/media/platform/hdr-image-format). 15 | 16 | ## Build from source using CMake 17 | 18 | This software suite has been built and tested on platforms: 19 | - Android 20 | - Linux 21 | - macOS 22 | - Windows 23 | 24 | Refer to [building.md](docs/building.md) for complete instructions. 25 | 26 | ## Using libultrahdr 27 | 28 | A detailed description of libultrahdr encode and decode api is included in [ultrahdr_api.h](ultrahdr_api.h) 29 | and for sample usage refer [demo app](examples/ultrahdr_app.cpp). 30 | 31 | libultrahdr includes two classes of APIs, one to compress and the other to decompress HDR images: 32 | 33 | ### Encoding api outline: 34 | 35 | | Scenario | Hdr intent raw | Sdr intent raw | Sdr intent compressed | Gain map compressed | Quality | Exif | Use Case | 36 | |:---------:| :----------: | :----------: | :---------------------: | :-------------------: | :-------: | :---------: | :-------- | 37 | | API - 0 | P010 or rgba1010102 or rgbaf16 | No | No | No | Optional| Optional | Used if, only hdr raw intent is present. [^1] | 38 | | API - 1 | P010 or rgba1010102 or rgbaf16 | YUV420 or rgba8888 | No | No | Optional| Optional | Used if, hdr raw and sdr raw intents are present.[^2] | 39 | | API - 2 | P010 or rgba1010102 or rgbaf16 | YUV420 or rgba8888 | Yes | No | No | No | Used if, hdr raw, sdr raw and sdr compressed intents are present.[^3] | 40 | | API - 3 | P010 or rgba1010102 or rgbaf16 | No | Yes | No | No | No | Used if, hdr raw and sdr compressed intents are present.[^4] | 41 | | API - 4 | No | No | Yes | Yes | No | No | Used if, sdr compressed, gain map compressed and GainMap Metadata are present.[^5] | 42 | 43 | [^1]: Tonemap hdr to sdr. Compute gain map from hdr and sdr. Compress sdr and gainmap at quality configured. Add exif if provided. Combine sdr compressed, gainmap in multi picture format with gainmap metadata. 44 | [^2]: Compute gain map from hdr and sdr. Compress sdr and gainmap at quality configured. Add exif if provided. Combine sdr compressed, gainmap in multi picture format with gainmap metadata. 45 | [^3]: Compute gain map from hdr and raw sdr. Compress gainmap. Combine sdr compressed, gainmap in multi picture format with gainmap metadata. 46 | [^4]: Decode compressed sdr input. Compute gain map from hdr and decoded sdr. Compress gainmap. Combine sdr compressed, gainmap in multi picture format with gainmap metadata. 47 | [^5]: Combine sdr compressed, gainmap in multi picture format with gainmap metadata. 48 | 49 | ### Decoding api outline: 50 | 51 | Configure display device characteristics (display transfer characteristics, max display boost) for optimal usage. 52 | 53 | | Input | Usage | 54 | | ------------- | ------------- | 55 | | max_display_boost | (optional, >= 1.0) the maximum available boost supported by a display. | 56 | | supported color transfer format pairs |
color transferColor format
SDR32bppRGBA8888
HDR_LINEAR64bppRGBAHalfFloat
HDR_PQ32bppRGBA1010102 PQ
HDR_HLG32bppRGBA1010102 HLG
| 57 | -------------------------------------------------------------------------------- /adobe-hdr-gain-map-license/Android.bp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Android Open Source Project 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | license { 16 | name: "adobe_hdr_gain_map_license", 17 | license_kinds: ["legacy_by_exception_only"], 18 | license_text: ["NOTICE"], 19 | } 20 | -------------------------------------------------------------------------------- /adobe-hdr-gain-map-license/NOTICE: -------------------------------------------------------------------------------- 1 | This product includes Gain Map technology under license by Adobe. 2 | -------------------------------------------------------------------------------- /benchmark/Android.bp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Android Open Source Project 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package { 16 | // See: http://go/android-license-faq 17 | // A large-scale-change added 'default_applicable_licenses' to import 18 | // all of the 'license_kinds' from "external_libultrahdr_license" 19 | // to get the below license kinds: 20 | // SPDX-license-identifier-Apache-2.0 21 | default_applicable_licenses: ["external_libultrahdr_license"], 22 | } 23 | 24 | cc_benchmark { 25 | name: "ultrahdr_benchmark", 26 | host_supported: true, 27 | srcs: ["benchmark_test.cpp"], 28 | static_libs: [ 29 | "libjpegdecoder", 30 | "libjpegencoder", 31 | "libultrahdr", 32 | ], 33 | shared_libs: [ 34 | "libimage_io", 35 | "libjpeg", 36 | "liblog", 37 | ], 38 | target: { 39 | android: { 40 | cflags: ["-DUHDR_ENABLE_GLES"], 41 | shared_libs: [ 42 | "libEGL", 43 | "libGLESv3", 44 | ], 45 | }, 46 | }, 47 | } 48 | -------------------------------------------------------------------------------- /benchmark/AndroidTest.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 38 | -------------------------------------------------------------------------------- /benchmark/DynamicConfig.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | 18 | https://storage.googleapis.com/android_media/external/libultrahdr/benchmark/UltrahdrBenchmarkTestRes-1.2.zip 19 | 20 | -------------------------------------------------------------------------------- /cmake/FindEGL.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2024 The Android Open Source Project 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | # use this file except in compliance with the License. You may obtain a copy of 6 | # the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations under 14 | # the License. 15 | # 16 | 17 | # 18 | # Finds the EGL library. This module defines: 19 | # 20 | # EGL_FOUND - True if EGL library is found, False otherwise 21 | # EGL_LIBRARIES - EGL library 22 | # EGL_INCLUDE_DIRS - Include dir 23 | # 24 | 25 | find_path(EGL_INCLUDE_DIRS EGL/egl.h) 26 | 27 | find_library(EGL_LIBRARIES NAMES EGL libEGL) 28 | 29 | include(FindPackageHandleStandardArgs) 30 | find_package_handle_standard_args(EGL DEFAULT_MSG EGL_INCLUDE_DIRS EGL_LIBRARIES) 31 | 32 | mark_as_advanced(EGL_INCLUDE_DIRS EGL_LIBRARIES) 33 | -------------------------------------------------------------------------------- /cmake/FindOpenGLES3.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2024 The Android Open Source Project 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | # use this file except in compliance with the License. You may obtain a copy of 6 | # the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations under 14 | # the License. 15 | # 16 | 17 | # 18 | # Finds the OpenGLES3 library. This module defines: 19 | # 20 | # OpenGLES3_FOUND - True if OpenGLES 3 library is found, False otherwise 21 | # OPENGLES3_LIBRARIES - OpenGLES3 library 22 | # OPENGLES3_INCLUDE_DIRS - Include dir 23 | # OpenGLES3_API_VERSION - OpenGLES3 Supported API version 24 | # 25 | 26 | find_path(OPENGLES3_INCLUDE_DIRS GLES3/gl3.h) 27 | 28 | # Android has separate library for OpenGLES3 in the form GLESv3 29 | # Many platforms support OpenGLES3 via OpenGLES2 lib. In this case, presence of GLES3/gl*.h will be indicative of GLES3 support 30 | find_library(OPENGLES3_LIBRARIES NAMES GLESv3 GLESv2 libGLESv2) 31 | 32 | if(OPENGLES3_INCLUDE_DIRS) 33 | if(EXISTS ${OPENGLES3_INCLUDE_DIRS}/GLES3/gl32.h) 34 | set(OpenGLES3_API_VERSION "3.2") 35 | elseif(EXISTS ${OPENGLES3_INCLUDE_DIRS}/GLES3/gl31.h) 36 | set(OpenGLES3_API_VERSION "3.1") 37 | else() 38 | set(OpenGLES3_API_VERSION "3.0") 39 | endif() 40 | endif() 41 | 42 | include(FindPackageHandleStandardArgs) 43 | find_package_handle_standard_args(OpenGLES3 OPENGLES3_INCLUDE_DIRS OPENGLES3_LIBRARIES) 44 | 45 | mark_as_advanced(OPENGLES3_INCLUDE_DIRS OPENGLES3_LIBRARIES) 46 | -------------------------------------------------------------------------------- /cmake/cmake_uninstall.cmake.in: -------------------------------------------------------------------------------- 1 | # Source: https://gitlab.kitware.com/cmake/community/-/wikis/FAQ#can-i-do-make-uninstall-with-cmake 2 | 3 | if(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt") 4 | message(FATAL_ERROR "Cannot find install manifest: @CMAKE_BINARY_DIR@/install_manifest.txt") 5 | endif() 6 | 7 | file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files) 8 | string(REGEX REPLACE "\n" ";" files "${files}") 9 | foreach(file ${files}) 10 | message(STATUS "Uninstalling $ENV{DESTDIR}${file}") 11 | if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") 12 | execute_process(COMMAND ${CMAKE_COMMAND} -E remove "$ENV{DESTDIR}${file}" 13 | OUTPUT_VARIABLE rm_out 14 | RESULT_VARIABLE rm_retval) 15 | if(NOT "${rm_retval}" STREQUAL 0) 16 | message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") 17 | endif() 18 | else() 19 | message(STATUS "File $ENV{DESTDIR}${file} does not exist.") 20 | endif() 21 | endforeach() -------------------------------------------------------------------------------- /cmake/libuhdr.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@CMAKE_INSTALL_PREFIX@ 2 | libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ 3 | includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ 4 | 5 | Name: @PROJECT_NAME@ 6 | Description: @CMAKE_PROJECT_DESCRIPTION@ 7 | Version: @PROJECT_VERSION@ 8 | Requires.private: libjpeg 9 | Cflags: -I${includedir} 10 | Libs: -L${libdir} -l@UHDR_TARGET_NAME@ 11 | Libs.private: @CMAKE_THREAD_LIBS_INIT@ @UHDR_GL_DEPS@ 12 | -------------------------------------------------------------------------------- /cmake/package.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2024 The Android Open Source Project 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | # use this file except in compliance with the License. You may obtain a copy of 6 | # the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations under 14 | # the License. 15 | # 16 | 17 | # common package configuration 18 | set(CPACK_PACKAGE_NAME ${CMAKE_PROJECT_NAME}) 19 | set(CPACK_PACKAGE_VENDOR "Google, Inc.") 20 | set(CPACK_PACKAGE_CONTACT "Dichen Zhang ") 21 | set(CPACK_PACKAGE_VERSION_MAJOR ${UHDR_MAJOR_VERSION}) 22 | set(CPACK_PACKAGE_VERSION_MINOR ${UHDR_MINOR_VERSION}) 23 | set(CPACK_PACKAGE_VERSION_PATCH ${UHDR_PATCH_VERSION}) 24 | set(CPACK_PACKAGE_VERSION "${UHDR_MAJOR_VERSION}.${UHDR_MINOR_VERSION}.${UHDR_PATCH_VERSION}") 25 | set(CPACK_PACKAGE_DESCRIPTION_FILE ${CMAKE_SOURCE_DIR}/DESCRIPTION) 26 | set(CPACK_PACKAGE_DESCRIPTION_SUMMARY ${CMAKE_PROJECT_DESCRIPTION}) 27 | set(CPACK_PACKAGE_HOMEPAGE_URL "https://github.com/google/libultrahdr") 28 | if("${CMAKE_SYSTEM_NAME}" STREQUAL "") 29 | message(FATAL_ERROR "Failed to determine CPACK_SYSTEM_NAME. Is CMAKE_SYSTEM_NAME set?" ) 30 | endif() 31 | string(TOLOWER "${CMAKE_SYSTEM_NAME}" CPACK_SYSTEM_NAME) 32 | set(CPACK_PACKAGE_ARCHITECTURE ${ARCH}) 33 | set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CPACK_SYSTEM_NAME}") 34 | set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-${CPACK_PACKAGE_ARCHITECTURE}") 35 | set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/LICENSE) 36 | set(CPACK_PACKAGING_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}) 37 | 38 | # platform specific configuration 39 | if(APPLE) 40 | set(CPACK_GENERATOR "DragNDrop") 41 | elseif(UNIX) 42 | if(EXISTS "/etc/debian_version") 43 | set(CPACK_GENERATOR "DEB") 44 | set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) 45 | set(CPACK_DEBIAN_PACKAGE_RELEASE 1) 46 | set(CPACK_DEBIAN_PACKAGE_HOMEPAGE ${CPACK_PACKAGE_HOMEPAGE_URL}) 47 | elseif(EXISTS "/etc/redhat-release") 48 | set(CPACK_GENERATOR "RPM") 49 | set(CPACK_RPM_PACKAGE_ARCHITECTURE ${CPACK_PACKAGE_ARCHITECTURE}) 50 | set(CPACK_RPM_PACKAGE_RELEASE 1) 51 | set(CPACK_RPM_PACKAGE_LICENSE "Apache 2.0") 52 | set(CPACK_RPM_PACKAGE_URL ${CPACK_PACKAGE_HOMEPAGE_URL}) 53 | else() 54 | set(CPACK_GENERATOR "TGZ") 55 | endif() 56 | else() 57 | set(CPACK_GENERATOR "ZIP") 58 | endif() 59 | -------------------------------------------------------------------------------- /cmake/toolchains/aarch64-linux-gnu.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2023 The Android Open Source Project 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | # use this file except in compliance with the License. You may obtain a copy of 6 | # the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations under 14 | # the License. 15 | # 16 | 17 | if(UHDR_BUILD_CMAKE_TOOLCHAINS_AARCH64_LINUX_GNU_CMAKE_) 18 | return() 19 | endif() 20 | 21 | set(UHDR_BUILD_CMAKE_TOOLCHAINS_AARCH64_LINUX_GNU_CMAKE_ 1) 22 | 23 | set(CMAKE_SYSTEM_NAME "Linux") 24 | set(CMAKE_SYSTEM_PROCESSOR "aarch64") 25 | 26 | if("${CROSS}" STREQUAL "") 27 | set(CROSS aarch64-linux-gnu-) 28 | endif() 29 | 30 | if(NOT CMAKE_C_COMPILER) 31 | set(CMAKE_C_COMPILER ${CROSS}gcc) 32 | endif() 33 | if(NOT CMAKE_CXX_COMPILER) 34 | set(CMAKE_CXX_COMPILER ${CROSS}g++) 35 | endif() 36 | if(NOT AS_EXECUTABLE) 37 | set(AS_EXECUTABLE ${CROSS}as) 38 | endif() 39 | 40 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 41 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 42 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 43 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) 44 | -------------------------------------------------------------------------------- /cmake/toolchains/android.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2023 The Android Open Source Project 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | # use this file except in compliance with the License. You may obtain a copy of 6 | # the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations under 14 | # the License. 15 | # 16 | 17 | if(UHDR_BUILD_CMAKE_TOOLCHAINS_ANDROID_CMAKE_) 18 | return() 19 | endif() 20 | 21 | set(UHDR_BUILD_CMAKE_TOOLCHAINS_ANDROID_CMAKE_ 1) 22 | 23 | if(NOT ANDROID_PLATFORM) 24 | set(ANDROID_PLATFORM android-23) 25 | endif() 26 | 27 | # Choose target architecture with: 28 | # -DANDROID_ABI={armeabi-v7a, arm64-v8a, x86, x86_64} 29 | if(NOT ANDROID_ABI) 30 | set(ANDROID_ABI arm64-v8a) 31 | endif() 32 | 33 | # Toolchain files don't have access to cached variables: 34 | # https://gitlab.kitware.com/cmake/cmake/issues/16170. Set an intermediate 35 | # environment variable when loaded the first time. 36 | if(UHDR_ANDROID_NDK_PATH) 37 | set(ENV{UHDR_ANDROID_NDK_PATH} "${UHDR_ANDROID_NDK_PATH}") 38 | else() 39 | set(UHDR_ANDROID_NDK_PATH "$ENV{UHDR_ANDROID_NDK_PATH}") 40 | endif() 41 | 42 | if(NOT UHDR_ANDROID_NDK_PATH) 43 | message(FATAL_ERROR "UHDR_ANDROID_NDK_PATH not set.") 44 | return() 45 | endif() 46 | 47 | include("${UHDR_ANDROID_NDK_PATH}/build/cmake/android.toolchain.cmake") 48 | 49 | set(CMAKE_SYSTEM_NAME "Android") 50 | 51 | 52 | -------------------------------------------------------------------------------- /cmake/toolchains/arm-linux-gnueabihf.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2023 The Android Open Source Project 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | # use this file except in compliance with the License. You may obtain a copy of 6 | # the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations under 14 | # the License. 15 | # 16 | 17 | if(UHDR_BUILD_CMAKE_TOOLCHAINS_ARM_LINUX_GNUEABIHF_CMAKE_) 18 | return() 19 | endif() 20 | 21 | set(UHDR_BUILD_CMAKE_TOOLCHAINS_ARM_LINUX_GNUEABIHF_CMAKE_ 1) 22 | 23 | set(CMAKE_SYSTEM_NAME "Linux") 24 | set(CMAKE_SYSTEM_PROCESSOR "armv7") 25 | 26 | if("${CROSS}" STREQUAL "") 27 | set(CROSS arm-linux-gnueabihf-) 28 | endif() 29 | 30 | if(NOT CMAKE_C_COMPILER) 31 | set(CMAKE_C_COMPILER ${CROSS}gcc) 32 | endif() 33 | if(NOT CMAKE_CXX_COMPILER) 34 | set(CMAKE_CXX_COMPILER ${CROSS}g++) 35 | endif() 36 | if(NOT AS_EXECUTABLE) 37 | set(AS_EXECUTABLE ${CROSS}as) 38 | endif() 39 | 40 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 41 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 42 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 43 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) 44 | -------------------------------------------------------------------------------- /cmake/toolchains/loong64-linux-gnu.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2023 The Android Open Source Project 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | # use this file except in compliance with the License. You may obtain a copy of 6 | # the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations under 14 | # the License. 15 | # 16 | 17 | if(UHDR_BUILD_CMAKE_TOOLCHAINS_LOONG64_LINUX_GNU_CMAKE_) 18 | return() 19 | endif() 20 | 21 | set(UHDR_BUILD_CMAKE_TOOLCHAINS_LOONG64_LINUX_GNU_CMAKE_ 1) 22 | 23 | set(CMAKE_SYSTEM_NAME "Linux") 24 | set(CMAKE_SYSTEM_PROCESSOR "loongarch64") 25 | 26 | if("${CROSS}" STREQUAL "") 27 | set(CROSS loongarch64-linux-gnu-) 28 | endif() 29 | 30 | if(NOT CMAKE_C_COMPILER) 31 | set(CMAKE_C_COMPILER ${CROSS}gcc) 32 | endif() 33 | if(NOT CMAKE_CXX_COMPILER) 34 | set(CMAKE_CXX_COMPILER ${CROSS}g++) 35 | endif() 36 | if(NOT AS_EXECUTABLE) 37 | set(AS_EXECUTABLE ${CROSS}as) 38 | endif() 39 | 40 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 41 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 42 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 43 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) 44 | -------------------------------------------------------------------------------- /cmake/toolchains/riscv32-linux-gnu.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2023 The Android Open Source Project 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | # use this file except in compliance with the License. You may obtain a copy of 6 | # the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations under 14 | # the License. 15 | # 16 | 17 | if(UHDR_BUILD_CMAKE_TOOLCHAINS_RISCV32_LINUX_GNU_CMAKE_) 18 | return() 19 | endif() 20 | 21 | set(UHDR_BUILD_CMAKE_TOOLCHAINS_RISCV32_LINUX_GNU_CMAKE_ 1) 22 | 23 | set(CMAKE_SYSTEM_NAME "Linux") 24 | set(CMAKE_SYSTEM_PROCESSOR "riscv32") 25 | 26 | if("${CROSS}" STREQUAL "") 27 | set(CROSS riscv32-linux-gnu-) 28 | endif() 29 | 30 | if(NOT CMAKE_C_COMPILER) 31 | set(CMAKE_C_COMPILER ${CROSS}gcc) 32 | endif() 33 | if(NOT CMAKE_CXX_COMPILER) 34 | set(CMAKE_CXX_COMPILER ${CROSS}g++) 35 | endif() 36 | if(NOT AS_EXECUTABLE) 37 | set(AS_EXECUTABLE ${CROSS}as) 38 | endif() 39 | 40 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 41 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 42 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 43 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) 44 | -------------------------------------------------------------------------------- /cmake/toolchains/riscv64-linux-gnu.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2023 The Android Open Source Project 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | # use this file except in compliance with the License. You may obtain a copy of 6 | # the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations under 14 | # the License. 15 | # 16 | 17 | if(UHDR_BUILD_CMAKE_TOOLCHAINS_RISCV64_LINUX_GNU_CMAKE_) 18 | return() 19 | endif() 20 | 21 | set(UHDR_BUILD_CMAKE_TOOLCHAINS_RISCV64_LINUX_GNU_CMAKE_ 1) 22 | 23 | set(CMAKE_SYSTEM_NAME "Linux") 24 | set(CMAKE_SYSTEM_PROCESSOR "riscv64") 25 | 26 | if("${CROSS}" STREQUAL "") 27 | set(CROSS riscv64-linux-gnu-) 28 | endif() 29 | 30 | if(NOT CMAKE_C_COMPILER) 31 | set(CMAKE_C_COMPILER ${CROSS}gcc) 32 | endif() 33 | if(NOT CMAKE_CXX_COMPILER) 34 | set(CMAKE_CXX_COMPILER ${CROSS}g++) 35 | endif() 36 | if(NOT AS_EXECUTABLE) 37 | set(AS_EXECUTABLE ${CROSS}as) 38 | endif() 39 | 40 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 41 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 42 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 43 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) 44 | -------------------------------------------------------------------------------- /docs/contributing.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We would love to accept your patches and contributions to this project. 4 | 5 | ## Before you begin 6 | 7 | ### Sign our Contributor License Agreement 8 | 9 | Contributions to this project must be accompanied by a 10 | [Contributor License Agreement](https://cla.developers.google.com/about) (CLA). 11 | You (or your employer) retain the copyright to your contribution; this simply 12 | gives us permission to use and redistribute your contributions as part of the 13 | project. 14 | 15 | If you or your current employer have already signed the Google CLA (even if it 16 | was for a different project), you probably don't need to do it again. 17 | 18 | Visit to see your current agreements or to 19 | sign a new one. 20 | 21 | ### Review our Community Guidelines 22 | 23 | This project follows [Google's Open Source Community 24 | Guidelines](https://opensource.google/conduct/). 25 | 26 | ## Contribution process 27 | 28 | ### Code Reviews 29 | 30 | All submissions, including submissions by project members, require review. We 31 | use [GitHub pull requests](https://docs.github.com/articles/about-pull-requests) 32 | for this purpose. 33 | -------------------------------------------------------------------------------- /docs/fuzzers.md: -------------------------------------------------------------------------------- 1 | ## Building fuzzers for libultrahdr 2 | 3 | ### Requirements 4 | 5 | - Refer [Requirements](./building.md#Requirements) 6 | 7 | - Additionally compilers are required to support options `-fsanitize=fuzzer, -fsanitize=fuzzer-no-link`. 8 | For instance, `clang 12` (or later) 9 | 10 | ### Building Commands 11 | 12 | ```sh 13 | cmake -G Ninja ../ -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DUHDR_BUILD_FUZZERS=1 14 | ninja 15 | ``` 16 | 17 | This will generate the following files under `build_directory`: 18 | 19 | **ultrahdr_enc_fuzzer** - ultrahdr encoder fuzzer
20 | **ultrahdr_dec_fuzzer** - ultrahdr decoder fuzzer
21 | 22 | Additionally, while building fuzzers, user can enable sanitizers by providing desired 23 | sanitizer option(s) through `UHDR_SANITIZE_OPTIONS`. 24 | 25 | To enable ASan, 26 | 27 | ```sh 28 | cmake -G Ninja ../ -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DUHDR_BUILD_FUZZERS=1 -DUHDR_SANITIZE_OPTIONS=address 29 | ninja 30 | ``` 31 | 32 | To enable MSan, 33 | 34 | ```sh 35 | cmake -G Ninja ../ -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DUHDR_BUILD_FUZZERS=1 -DUHDR_SANITIZE_OPTIONS=memory 36 | ninja 37 | ``` 38 | To enable TSan, 39 | 40 | ```sh 41 | cmake -G Ninja ../ -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DUHDR_BUILD_FUZZERS=1 -DUHDR_SANITIZE_OPTIONS=thread 42 | ninja 43 | ``` 44 | 45 | To enable UBSan, 46 | 47 | ```sh 48 | cmake -G Ninja ../ -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DUHDR_BUILD_FUZZERS=1 -DUHDR_SANITIZE_OPTIONS=undefined 49 | ninja 50 | ``` 51 | 52 | UBSan can be grouped with ASan, MSan or TSan. 53 | 54 | For example, to enable ASan and UBSan, 55 | 56 | ```sh 57 | cmake -G Ninja ../ -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DUHDR_BUILD_FUZZERS=1 -DUHDR_SANITIZE_OPTIONS=address,undefined 58 | ninja 59 | ``` 60 | 61 | ### Running 62 | 63 | To run the fuzzer(s), first create a corpus directory that holds the initial 64 | "seed" sample inputs. For decoder fuzzer, ultrahdr jpeg images can be used and 65 | for encoder fuzzer, sample yuv files can be used. 66 | 67 | Then run the fuzzers on the corpus directory. 68 | 69 | ```sh 70 | mkdir CORPUS_DIR 71 | cp seeds/* CORPUS_DIR 72 | ./ultrahdr_dec_fuzzer CORPUS_DIR 73 | ./ultrahdr_enc_fuzzer CORPUS_DIR 74 | ``` 75 | -------------------------------------------------------------------------------- /docs/jpegr_format.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/libultrahdr/6db3a83ee2b1f79850f3f597172289808dc6a331/docs/jpegr_format.png -------------------------------------------------------------------------------- /examples/Android.bp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Android Open Source Project 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package { 16 | // See: http://go/android-license-faq 17 | // A large-scale-change added 'default_applicable_licenses' to import 18 | // all of the 'license_kinds' from "external_libultrahdr_license" 19 | // to get the below license kinds: 20 | // SPDX-license-identifier-Apache-2.0 21 | default_applicable_licenses: ["external_libultrahdr_license"], 22 | } 23 | 24 | cc_binary { 25 | name: "ultrahdr_app", 26 | host_supported: true, 27 | srcs: [ 28 | "ultrahdr_app.cpp", 29 | ], 30 | shared_libs: [ 31 | "libbase", 32 | "libimage_io", 33 | "libjpeg", 34 | "liblog", 35 | ], 36 | static_libs: [ 37 | "libjpegdecoder", 38 | "libjpegencoder", 39 | "libultrahdr", 40 | ], 41 | target: { 42 | android: { 43 | shared_libs: [ 44 | "libEGL", 45 | "libGLESv3", 46 | ], 47 | }, 48 | }, 49 | } 50 | -------------------------------------------------------------------------------- /examples/metadata.cfg: -------------------------------------------------------------------------------- 1 | --maxContentBoost 6.0 6.0 6.0 2 | --minContentBoost 1.0 1.0 1.0 3 | --gamma 1.0 1.0 1.0 4 | --offsetSdr 0.0 0.0 0.0 5 | --offsetHdr 0.0 0.0 0.0 6 | --hdrCapacityMin 1.0 7 | --hdrCapacityMax 49.2611 8 | --useBaseColorSpace 1 9 | -------------------------------------------------------------------------------- /fuzzer/Android.bp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Android Open Source Project 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package { 16 | // See: http://go/android-license-faq 17 | // A large-scale-change added 'default_applicable_licenses' to import 18 | // all of the 'license_kinds' from "external_libultrahdr_license" 19 | // to get the below license kinds: 20 | // SPDX-license-identifier-Apache-2.0 21 | default_applicable_licenses: ["external_libultrahdr_license"], 22 | } 23 | 24 | cc_defaults { 25 | name: "ultrahdr_fuzzer_defaults", 26 | host_supported: true, 27 | shared_libs: [ 28 | "libimage_io", 29 | "libjpeg", 30 | ], 31 | static_libs: [ 32 | "libjpegdecoder", 33 | "libjpegencoder", 34 | "libultrahdr", 35 | "liblog", 36 | ], 37 | target: { 38 | darwin: { 39 | enabled: false, 40 | }, 41 | android: { 42 | cflags: ["-DUHDR_ENABLE_GLES"], 43 | shared_libs: [ 44 | "libEGL", 45 | "libGLESv3", 46 | ], 47 | }, 48 | }, 49 | fuzz_config: { 50 | cc: [ 51 | "android-media-fuzzing-reports@google.com", 52 | ], 53 | description: "The fuzzers target the APIs of jpeg hdr", 54 | service_privilege: "constrained", 55 | users: "multi_user", 56 | fuzzed_code_usage: "future_version", 57 | vector: "local_no_privileges_required", 58 | }, 59 | } 60 | 61 | cc_fuzz { 62 | name: "ultrahdr_enc_fuzzer", 63 | defaults: ["ultrahdr_fuzzer_defaults"], 64 | srcs: [ 65 | "ultrahdr_enc_fuzzer.cpp", 66 | ], 67 | } 68 | 69 | cc_fuzz { 70 | name: "ultrahdr_dec_fuzzer", 71 | defaults: ["ultrahdr_fuzzer_defaults"], 72 | srcs: [ 73 | "ultrahdr_dec_fuzzer.cpp", 74 | ], 75 | } 76 | 77 | cc_fuzz { 78 | name: "ultrahdr_legacy_fuzzer", 79 | defaults: ["ultrahdr_fuzzer_defaults"], 80 | srcs: [ 81 | "ultrahdr_legacy_fuzzer.cpp", 82 | ], 83 | } 84 | -------------------------------------------------------------------------------- /fuzzer/ossfuzz.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -eu 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | ################################################################################ 16 | # Ensure SRC and WORK are set 17 | test "${SRC}" != "" || exit 1 18 | test "${WORK}" != "" || exit 1 19 | 20 | # Build libultrahdr 21 | build_dir=$WORK/build 22 | rm -rf ${build_dir} 23 | mkdir -p ${build_dir} 24 | pushd ${build_dir} 25 | 26 | cmake $SRC/libultrahdr -DUHDR_BUILD_FUZZERS=1 -DUHDR_MAX_DIMENSION=1280 27 | make -j$(nproc) ultrahdr_dec_fuzzer ultrahdr_enc_fuzzer ultrahdr_legacy_fuzzer 28 | cp ${build_dir}/ultrahdr_dec_fuzzer $OUT/ 29 | cp ${build_dir}/ultrahdr_enc_fuzzer $OUT/ 30 | cp ${build_dir}/ultrahdr_legacy_fuzzer $OUT/ 31 | popd 32 | -------------------------------------------------------------------------------- /java/metadata.cfg: -------------------------------------------------------------------------------- 1 | --maxContentBoost 6.0 6.0 6.0 2 | --minContentBoost 1.0 1.0 1.0 3 | --gamma 1.0 1.0 1.0 4 | --offsetSdr 0.0 0.0 0.0 5 | --offsetHdr 0.0 0.0 0.0 6 | --hdrCapacityMin 1.0 7 | --hdrCapacityMax 49.2611 8 | --useBaseColorSpace 1 9 | -------------------------------------------------------------------------------- /lib/include/ultrahdr/multipictureformat.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef ULTRAHDR_MULTIPICTUREFORMAT_H 18 | #define ULTRAHDR_MULTIPICTUREFORMAT_H 19 | 20 | #include 21 | 22 | #ifndef USE_BIG_ENDIAN_IN_MPF 23 | #define USE_BIG_ENDIAN_IN_MPF true 24 | #endif 25 | 26 | #undef Endian_SwapBE32 27 | #undef Endian_SwapBE16 28 | #if USE_BIG_ENDIAN_IN_MPF 29 | #define Endian_SwapBE32(n) EndianSwap32(n) 30 | #define Endian_SwapBE16(n) EndianSwap16(n) 31 | #else 32 | #define Endian_SwapBE32(n) (n) 33 | #define Endian_SwapBE16(n) (n) 34 | #endif 35 | 36 | #include "ultrahdr/jpegr.h" 37 | #include "ultrahdr/gainmapmath.h" 38 | #include "ultrahdr/jpegrutils.h" 39 | 40 | namespace ultrahdr { 41 | 42 | constexpr size_t kNumPictures = 2; 43 | constexpr size_t kMpEndianSize = 4; 44 | constexpr uint16_t kTagSerializedCount = 3; 45 | constexpr uint32_t kTagSize = 12; 46 | 47 | constexpr uint16_t kTypeLong = 0x4; 48 | constexpr uint16_t kTypeUndefined = 0x7; 49 | 50 | static constexpr uint8_t kMpfSig[] = {'M', 'P', 'F', '\0'}; 51 | constexpr uint8_t kMpLittleEndian[kMpEndianSize] = {0x49, 0x49, 0x2A, 0x00}; 52 | constexpr uint8_t kMpBigEndian[kMpEndianSize] = {0x4D, 0x4D, 0x00, 0x2A}; 53 | 54 | constexpr uint16_t kVersionTag = 0xB000; 55 | constexpr uint16_t kVersionType = kTypeUndefined; 56 | constexpr uint32_t kVersionCount = 4; 57 | constexpr size_t kVersionSize = 4; 58 | constexpr uint8_t kVersionExpected[kVersionSize] = {'0', '1', '0', '0'}; 59 | 60 | constexpr uint16_t kNumberOfImagesTag = 0xB001; 61 | constexpr uint16_t kNumberOfImagesType = kTypeLong; 62 | constexpr uint32_t kNumberOfImagesCount = 1; 63 | 64 | constexpr uint16_t kMPEntryTag = 0xB002; 65 | constexpr uint16_t kMPEntryType = kTypeUndefined; 66 | constexpr uint32_t kMPEntrySize = 16; 67 | 68 | constexpr uint32_t kMPEntryAttributeFormatJpeg = 0x0000000; 69 | constexpr uint32_t kMPEntryAttributeTypePrimary = 0x030000; 70 | 71 | size_t calculateMpfSize(); 72 | std::shared_ptr generateMpf(size_t primary_image_size, size_t primary_image_offset, 73 | size_t secondary_image_size, size_t secondary_image_offset); 74 | 75 | } // namespace ultrahdr 76 | 77 | #endif // ULTRAHDR_MULTIPICTUREFORMAT_H 78 | -------------------------------------------------------------------------------- /lib/src/multipictureformat.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "ultrahdr/multipictureformat.h" 18 | 19 | namespace ultrahdr { 20 | size_t calculateMpfSize() { 21 | return sizeof(kMpfSig) + // Signature 22 | kMpEndianSize + // Endianness 23 | sizeof(uint32_t) + // Index IFD Offset 24 | sizeof(uint16_t) + // Tag count 25 | kTagSerializedCount * kTagSize + // 3 tags at 12 bytes each 26 | sizeof(uint32_t) + // Attribute IFD offset 27 | kNumPictures * kMPEntrySize; // MP Entries for each image 28 | } 29 | 30 | std::shared_ptr generateMpf(size_t primary_image_size, size_t primary_image_offset, 31 | size_t secondary_image_size, 32 | size_t secondary_image_offset) { 33 | size_t mpf_size = calculateMpfSize(); 34 | std::shared_ptr dataStruct = std::make_shared(mpf_size); 35 | 36 | dataStruct->write(static_cast(kMpfSig), sizeof(kMpfSig)); 37 | #if USE_BIG_ENDIAN_IN_MPF 38 | dataStruct->write(static_cast(kMpBigEndian), kMpEndianSize); 39 | #else 40 | dataStruct->write(static_cast(kMpLittleEndian), kMpEndianSize); 41 | #endif 42 | 43 | // Set the Index IFD offset be the position after the endianness value and this offset. 44 | constexpr uint32_t indexIfdOffset = static_cast(kMpEndianSize + sizeof(kMpfSig)); 45 | dataStruct->write32(Endian_SwapBE32(indexIfdOffset)); 46 | 47 | // We will write 3 tags (version, number of images, MP entries). 48 | dataStruct->write16(Endian_SwapBE16(kTagSerializedCount)); 49 | 50 | // Write the version tag. 51 | dataStruct->write16(Endian_SwapBE16(kVersionTag)); 52 | dataStruct->write16(Endian_SwapBE16(kVersionType)); 53 | dataStruct->write32(Endian_SwapBE32(kVersionCount)); 54 | dataStruct->write(kVersionExpected, kVersionSize); 55 | 56 | // Write the number of images. 57 | dataStruct->write16(Endian_SwapBE16(kNumberOfImagesTag)); 58 | dataStruct->write16(Endian_SwapBE16(kNumberOfImagesType)); 59 | dataStruct->write32(Endian_SwapBE32(kNumberOfImagesCount)); 60 | dataStruct->write32(Endian_SwapBE32(kNumPictures)); 61 | 62 | // Write the MP entries. 63 | dataStruct->write16(Endian_SwapBE16(kMPEntryTag)); 64 | dataStruct->write16(Endian_SwapBE16(kMPEntryType)); 65 | dataStruct->write32(Endian_SwapBE32(kMPEntrySize * kNumPictures)); 66 | const uint32_t mpEntryOffset = 67 | static_cast(dataStruct->getBytesWritten() - // The bytes written so far 68 | sizeof(kMpfSig) + // Excluding the MPF signature 69 | sizeof(uint32_t) + // The 4 bytes for this offset 70 | sizeof(uint32_t)); // The 4 bytes for the attribute IFD offset. 71 | dataStruct->write32(Endian_SwapBE32(mpEntryOffset)); 72 | 73 | // Write the attribute IFD offset (zero because we don't write it). 74 | dataStruct->write32(0); 75 | 76 | // Write the MP entries for primary image 77 | dataStruct->write32(Endian_SwapBE32(kMPEntryAttributeFormatJpeg | kMPEntryAttributeTypePrimary)); 78 | dataStruct->write32(Endian_SwapBE32(primary_image_size)); 79 | dataStruct->write32(Endian_SwapBE32(primary_image_offset)); 80 | dataStruct->write16(0); 81 | dataStruct->write16(0); 82 | 83 | // Write the MP entries for secondary image 84 | dataStruct->write32(Endian_SwapBE32(kMPEntryAttributeFormatJpeg)); 85 | dataStruct->write32(Endian_SwapBE32(secondary_image_size)); 86 | dataStruct->write32(Endian_SwapBE32(secondary_image_offset)); 87 | dataStruct->write16(0); 88 | dataStruct->write16(0); 89 | 90 | return dataStruct; 91 | } 92 | 93 | } // namespace ultrahdr 94 | -------------------------------------------------------------------------------- /tests/Android.bp: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Android Open Source Project 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package { 16 | // See: http://go/android-license-faq 17 | // A large-scale-change added 'default_applicable_licenses' to import 18 | // all of the 'license_kinds' from "external_libultrahdr_license" 19 | // to get the below license kinds: 20 | // SPDX-license-identifier-Apache-2.0 21 | default_applicable_licenses: ["external_libultrahdr_license"], 22 | } 23 | 24 | cc_test { 25 | name: "ultrahdr_unit_test", 26 | test_suites: ["device-tests"], 27 | srcs: [ 28 | "editorhelper_test.cpp", 29 | "gainmapmath_test.cpp", 30 | "icchelper_test.cpp", 31 | "jpegr_test.cpp", 32 | "jpegencoderhelper_test.cpp", 33 | "jpegdecoderhelper_test.cpp", 34 | ], 35 | shared_libs: [ 36 | "libimage_io", 37 | "libjpeg", 38 | "liblog", 39 | ], 40 | static_libs: [ 41 | "libgmock", 42 | "libgtest", 43 | "libjpegdecoder", 44 | "libjpegencoder", 45 | "libultrahdr", 46 | ], 47 | target: { 48 | android: { 49 | cflags: ["-DUHDR_ENABLE_GLES"], 50 | shared_libs: [ 51 | "libEGL", 52 | "libGLESv3", 53 | ], 54 | }, 55 | }, 56 | data: [ 57 | "./data/*.*", 58 | ], 59 | } 60 | -------------------------------------------------------------------------------- /tests/AndroidTest.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | 22 | 23 | 26 | 27 | -------------------------------------------------------------------------------- /tests/data/jpeg_image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/libultrahdr/6db3a83ee2b1f79850f3f597172289808dc6a331/tests/data/jpeg_image.jpg -------------------------------------------------------------------------------- /tests/data/minnie-318x240.yu12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/libultrahdr/6db3a83ee2b1f79850f3f597172289808dc6a331/tests/data/minnie-318x240.yu12 -------------------------------------------------------------------------------- /tests/data/minnie-320x240-rgb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/libultrahdr/6db3a83ee2b1f79850f3f597172289808dc6a331/tests/data/minnie-320x240-rgb.jpg -------------------------------------------------------------------------------- /tests/data/minnie-320x240-y.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/libultrahdr/6db3a83ee2b1f79850f3f597172289808dc6a331/tests/data/minnie-320x240-y.jpg -------------------------------------------------------------------------------- /tests/data/minnie-320x240-yuv-icc.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/libultrahdr/6db3a83ee2b1f79850f3f597172289808dc6a331/tests/data/minnie-320x240-yuv-icc.jpg -------------------------------------------------------------------------------- /tests/data/minnie-320x240-yuv.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/libultrahdr/6db3a83ee2b1f79850f3f597172289808dc6a331/tests/data/minnie-320x240-yuv.jpg -------------------------------------------------------------------------------- /tests/data/minnie-320x240.rgb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/libultrahdr/6db3a83ee2b1f79850f3f597172289808dc6a331/tests/data/minnie-320x240.rgb -------------------------------------------------------------------------------- /tests/data/minnie-320x240.y: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/libultrahdr/6db3a83ee2b1f79850f3f597172289808dc6a331/tests/data/minnie-320x240.y -------------------------------------------------------------------------------- /tests/data/minnie-320x240.yu12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/libultrahdr/6db3a83ee2b1f79850f3f597172289808dc6a331/tests/data/minnie-320x240.yu12 -------------------------------------------------------------------------------- /tests/data/raw_p010_image.p010: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/libultrahdr/6db3a83ee2b1f79850f3f597172289808dc6a331/tests/data/raw_p010_image.p010 -------------------------------------------------------------------------------- /tests/data/raw_yuv420_image.yuv420: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/libultrahdr/6db3a83ee2b1f79850f3f597172289808dc6a331/tests/data/raw_yuv420_image.yuv420 -------------------------------------------------------------------------------- /tests/icchelper_test.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | 19 | #include "ultrahdr/icc.h" 20 | 21 | namespace ultrahdr { 22 | 23 | class IccHelperTest : public testing::Test { 24 | public: 25 | IccHelperTest(); 26 | ~IccHelperTest(); 27 | 28 | protected: 29 | virtual void SetUp(); 30 | virtual void TearDown(); 31 | }; 32 | 33 | IccHelperTest::IccHelperTest() {} 34 | 35 | IccHelperTest::~IccHelperTest() {} 36 | 37 | void IccHelperTest::SetUp() {} 38 | 39 | void IccHelperTest::TearDown() {} 40 | 41 | TEST_F(IccHelperTest, iccWriteThenRead) { 42 | std::shared_ptr iccBt709 = IccHelper::writeIccProfile(UHDR_CT_SRGB, UHDR_CG_BT_709); 43 | ASSERT_NE(iccBt709->getLength(), 0); 44 | ASSERT_NE(iccBt709->getData(), nullptr); 45 | EXPECT_EQ(IccHelper::readIccColorGamut(iccBt709->getData(), iccBt709->getLength()), 46 | UHDR_CG_BT_709); 47 | 48 | std::shared_ptr iccP3 = IccHelper::writeIccProfile(UHDR_CT_SRGB, UHDR_CG_DISPLAY_P3); 49 | ASSERT_NE(iccP3->getLength(), 0); 50 | ASSERT_NE(iccP3->getData(), nullptr); 51 | EXPECT_EQ(IccHelper::readIccColorGamut(iccP3->getData(), iccP3->getLength()), UHDR_CG_DISPLAY_P3); 52 | 53 | std::shared_ptr iccBt2100 = IccHelper::writeIccProfile(UHDR_CT_SRGB, UHDR_CG_BT_2100); 54 | ASSERT_NE(iccBt2100->getLength(), 0); 55 | ASSERT_NE(iccBt2100->getData(), nullptr); 56 | EXPECT_EQ(IccHelper::readIccColorGamut(iccBt2100->getData(), iccBt2100->getLength()), 57 | UHDR_CG_BT_2100); 58 | } 59 | 60 | TEST_F(IccHelperTest, iccEndianness) { 61 | std::shared_ptr icc = IccHelper::writeIccProfile(UHDR_CT_SRGB, UHDR_CG_BT_709); 62 | size_t profile_size = icc->getLength() - kICCIdentifierSize; 63 | 64 | uint8_t* icc_bytes = reinterpret_cast(icc->getData()) + kICCIdentifierSize; 65 | uint32_t encoded_size = 66 | static_cast(icc_bytes[0]) << 24 | static_cast(icc_bytes[1]) << 16 | 67 | static_cast(icc_bytes[2]) << 8 | static_cast(icc_bytes[3]); 68 | 69 | EXPECT_EQ(static_cast(encoded_size), profile_size); 70 | } 71 | 72 | } // namespace ultrahdr 73 | -------------------------------------------------------------------------------- /third_party/image_io/METADATA: -------------------------------------------------------------------------------- 1 | name: "image_io" 2 | description: 3 | "Image_io is a library for manipulating image files, especially XMP metadata" 4 | 5 | third_party { 6 | url { 7 | type: PIPER 8 | value: "http://google3/photos/editing/formats/image_io" 9 | } 10 | version: "222429857" 11 | last_upgrade_date { 12 | year: 2018 13 | month: 11 14 | day: 21 15 | } 16 | license_type: NOTICE 17 | } 18 | -------------------------------------------------------------------------------- /third_party/image_io/MODULE_LICENSE_APACHE2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/libultrahdr/6db3a83ee2b1f79850f3f597172289808dc6a331/third_party/image_io/MODULE_LICENSE_APACHE2 -------------------------------------------------------------------------------- /third_party/image_io/README.android: -------------------------------------------------------------------------------- 1 | Library Name: Image IO 2 | License: Apache 2 3 | Description: This library provides a lightweight interface to the images and metadata contained 4 | in Depth and AR photos. 5 | 6 | Local patches 7 | ------------- 8 | - Add an NDK library variant. 9 | 10 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/base/byte_buffer.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_BASE_BYTE_BUFFER_H_ // NOLINT 2 | #define IMAGE_IO_BASE_BYTE_BUFFER_H_ // NOLINT 3 | 4 | #include 5 | #include 6 | 7 | #include "image_io/base/byte_data.h" 8 | 9 | namespace photos_editing_formats { 10 | namespace image_io { 11 | 12 | /// This class provides a means to allocate and fill a Byte buffer with the 13 | /// data specified in a vector of ByteData objects, and then to release that 14 | /// buffer to be used in a DataSegment. This is used for testing purposes 15 | /// initially, but has applicability for use in the image_io itself. 16 | class ByteBuffer { 17 | public: 18 | /// Constructs a ByteBuffer using a previously allocated buffer. 19 | /// @param size The size of the buffer. 20 | /// @param buffer The previously allocated buffer 21 | ByteBuffer(size_t size, std::unique_ptr buffer); 22 | 23 | /// Constructs a ByteBuffer using the vector of byte data. 24 | /// @param byte_data_vector The data to used to define the length and value of 25 | /// the buffer. If any ByteData in the vector is of kHex type, and it 26 | /// contains invalid hex digits, the size value will be set to 0, 27 | /// resulting in a ByteBuffer the IsValid() function of which will return 28 | /// false. 29 | explicit ByteBuffer(const std::vector& byte_data_vector); 30 | 31 | /// @return Whether the byte buffer is valid. 32 | bool IsValid() const { return size_ > 0; } 33 | 34 | /// @return The size of the byte buffer. 35 | size_t GetSize() const { return size_; } 36 | 37 | /// @param location The location in the byte buffer to set. 38 | /// @param value The two-byte value. 39 | /// @return Whether the value was set successfully. 40 | bool SetBigEndianValue(size_t location, std::uint16_t value); 41 | 42 | /// Releases the buffer to the caller and sets this ByteBuffer object to an 43 | /// invalid state. That is, after this call IsValid() will return false, and 44 | /// GetSize() will return 0. 45 | /// @return The buffer pointer or nullptr if the ByteBuffer was invalid. The 46 | /// caller is responsible for deleting the buffer when done. 47 | Byte* Release(); 48 | 49 | private: 50 | std::unique_ptr buffer_; 51 | size_t size_; 52 | }; 53 | 54 | } // namespace image_io 55 | } // namespace photos_editing_formats 56 | 57 | #endif // IMAGE_IO_BASE_BYTE_BUFFER_H_ // NOLINT 58 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/base/byte_pointer_data_destination.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_BASE_BYTE_POINTER_DATA_DESTINATION_H_ // NOLINT 2 | #define IMAGE_IO_BASE_BYTE_POINTER_DATA_DESTINATION_H_ // NOLINT 3 | 4 | #include "image_io/base/data_destination.h" 5 | 6 | namespace photos_editing_formats { 7 | namespace image_io { 8 | 9 | /// A DataDestination that writes its output to byte buffer, the pointer to 10 | /// which is supplied by the client along with a size of that buffer. 11 | class BytePointerDataDestination : public DataDestination { 12 | public: 13 | /// Constructs an BytesDataDestination using the given a buffer and size. 14 | /// @param bytes The buffer to receive the bytes. 15 | /// @param size The size of the buffer to receive the bytes. 16 | BytePointerDataDestination(Byte* bytes, size_t size) 17 | : bytes_(bytes), size_(size), bytes_transferred_(0) {} 18 | BytePointerDataDestination(const BytePointerDataDestination&) = delete; 19 | BytePointerDataDestination& operator=(const BytePointerDataDestination&) = 20 | delete; 21 | 22 | /// @return The number of bytes written to the bytes buffer. 23 | size_t GetBytesTransferred() const override { return bytes_transferred_; } 24 | 25 | void StartTransfer() override; 26 | TransferStatus Transfer(const DataRange& transfer_range, 27 | const DataSegment& data_segment) override; 28 | void FinishTransfer() override; 29 | 30 | private: 31 | /// The bytes buffer to receive the data. 32 | Byte* bytes_; 33 | 34 | /// The size of the bytes buffer. 35 | size_t size_; 36 | 37 | /// The number of bytes written so far. 38 | size_t bytes_transferred_; 39 | }; 40 | 41 | } // namespace image_io 42 | } // namespace photos_editing_formats 43 | 44 | #endif // IMAGE_IO_BASE_BYTE_POINTER_DATA_DESTINATION_H_ // NOLINT 45 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/base/cout_message_writer.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_BASE_COUT_MESSAGE_WRITER_H_ // NOLINT 2 | #define IMAGE_IO_BASE_COUT_MESSAGE_WRITER_H_ // NOLINT 3 | 4 | #include 5 | 6 | #include "image_io/base/message_writer.h" 7 | 8 | namespace photos_editing_formats { 9 | namespace image_io { 10 | 11 | /// This subclass of MessageWriter writes messages to std::cout. 12 | class CoutMessageWriter : public MessageWriter { 13 | public: 14 | void WriteMessage(const Message& message) override { 15 | std::cout << GetFormattedMessage(message) << std::endl; 16 | } 17 | }; 18 | 19 | } // namespace image_io 20 | } // namespace photos_editing_formats 21 | 22 | #endif // IMAGE_IO_BASE_COUT_MESSAGE_WRITER_H_ // NOLINT 23 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/base/data_destination.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_BASE_DATA_DESTINATION_H_ // NOLINT 2 | #define IMAGE_IO_BASE_DATA_DESTINATION_H_ // NOLINT 3 | 4 | #include "image_io/base/data_range.h" 5 | #include "image_io/base/data_segment.h" 6 | #include "image_io/base/types.h" 7 | 8 | namespace photos_editing_formats { 9 | namespace image_io { 10 | 11 | /// DataDestination is the abstract base class for implementations that can 12 | /// efficiently move data from one location and/or form to another. In such 13 | /// a transfer, the StartTransfer() and FinishTransfer() functions are always 14 | /// called, and in between the Transfer() function may be called zero or more 15 | /// times. See the DataSource class to see how to initiate a transfer operation. 16 | class DataDestination { 17 | public: 18 | /// These values indicate what should be done after a DataSource calls a 19 | /// DataDestination's Transfer() function. 20 | enum TransferStatus { 21 | /// An error occurred in the transfer process. DataSource's TransferData() 22 | /// function should stop calling DataDestination's Transfer() function, and 23 | /// return to its caller. 24 | kTransferError, 25 | 26 | /// The transfer was successful. DataSource's TransferData() function can 27 | /// keep calling DataDestination's Transfer() of needed, or if not, 28 | /// return to its caller. 29 | kTransferOk, 30 | 31 | /// The transfer was successful and the DataDestination has decided that 32 | /// it has enough data. DataSource's TransferData() function should stop 33 | /// calling DataDestination's Transfer() function and return to its caller. 34 | kTransferDone 35 | }; 36 | 37 | virtual ~DataDestination() = default; 38 | 39 | /// This function is called prior to the first call to the Transfer() function 40 | /// to allow implementation subclasses a chance to initialize their data 41 | /// members for the transfer process. If a data destination sends its bytes 42 | /// to another data destination, this function must call its StartTransfer() 43 | /// function. 44 | virtual void StartTransfer() = 0; 45 | 46 | /// This function is called to transfer a portion or all of the data in the 47 | /// data segment from the caller to wherever the receiver needs it to go. 48 | /// @param transfer_range The portion of the data in the data_segment that is 49 | /// to be transferred. 50 | /// @param data_segment The data, some or all of which is to be transferred. 51 | /// @return A transfer status value indicating what should be done next. 52 | virtual TransferStatus Transfer(const DataRange& transfer_range, 53 | const DataSegment& data_segment) = 0; 54 | 55 | /// This function is called after the final call to the Transfer() function to 56 | /// allow implementation subclasses a chance to finalize their transfer 57 | /// operations. If a data destination sends its bytes to another data 58 | /// destination, this function must call its FinishTransfer() function. 59 | virtual void FinishTransfer() = 0; 60 | 61 | /// @return The number of bytes written to the data destination. There is some 62 | /// flexibility in the actual value returned. Most "end-point" destination 63 | /// subclasses return the actual number of bytes received/written. Other 64 | /// "mid-point" destinations are allowed to return the value from the next 65 | /// destination in the chain, or the actual number of bytes they are asked 66 | /// to transfer via the transfer_range parameter of the Transfer() 67 | /// function. 68 | virtual size_t GetBytesTransferred() const = 0; 69 | }; 70 | 71 | } // namespace image_io 72 | } // namespace photos_editing_formats 73 | 74 | #endif // IMAGE_IO_BASE_DATA_DESTINATION_H_ // NOLINT 75 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/base/data_line_map.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_BASE_DATA_LINE_MAP_H_ // NOLINT 2 | #define IMAGE_IO_BASE_DATA_LINE_MAP_H_ // NOLINT 3 | 4 | #include 5 | 6 | #include "image_io/base/data_range.h" 7 | #include "image_io/base/data_segment.h" 8 | 9 | namespace photos_editing_formats { 10 | namespace image_io { 11 | 12 | /// The line number and range of a text line in a data source. The range does 13 | /// not include the terminating new line. Valid line numbers are greater than 0. 14 | struct DataLine { 15 | DataLine() : number(0) {} 16 | DataLine(size_t a_number, const DataRange& a_range) 17 | : number(a_number), range(a_range) {} 18 | size_t number; 19 | DataRange range; 20 | }; 21 | 22 | /// A class that maps a data source location to a data line structure that has 23 | /// the line number and data range of the line. 24 | class DataLineMap { 25 | public: 26 | DataLineMap() : last_line_incomplete_(false) {} 27 | 28 | /// Returns the number of data lines in the map. 29 | size_t GetDataLineCount() const { return data_lines_.size(); } 30 | 31 | /// Returns the data lines 32 | const std::vector GetDataLines() const { return data_lines_; } 33 | 34 | /// Returns the data line assocated with the location, or one the number of 35 | /// which is zero and the range of which is invalid. 36 | DataLine GetDataLine(size_t location) const; 37 | 38 | /// Finds the next set of data line numbers and ranges in the segment and adds 39 | /// them to the map. If the map is empty, the line numbers will start at 1; 40 | /// otherwise the numbering of the new lines will start at the next line 41 | /// number indicated in the map. 42 | void FindDataLines(const DataRange& range, const DataSegment& segment); 43 | 44 | /// Clears the map and returns it to its startup state. 45 | void Clear(); 46 | 47 | private: 48 | /// The data lines in the map, sorted by ascending range.GetBegin() value. 49 | std::vector data_lines_; 50 | 51 | /// Whether the last data line in the vector is complete (ended in a newline). 52 | bool last_line_incomplete_; 53 | }; 54 | 55 | } // namespace image_io 56 | } // namespace photos_editing_formats 57 | 58 | #endif // IMAGE_IO_ BASE_DATA_LINE_MAP_H_ // NOLINT 59 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/base/data_line_map_builder_destination.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_BASE_DATA_LINE_MAP_BUILDER_DESTINATION_H_ // NOLINT 2 | #define IMAGE_IO_BASE_DATA_LINE_MAP_BUILDER_DESTINATION_H_ // NOLINT 3 | 4 | #include "image_io/base/data_destination.h" 5 | #include "image_io/base/data_line_map.h" 6 | 7 | namespace photos_editing_formats { 8 | namespace image_io { 9 | 10 | /// A class to build a data line map of the string implied by the transfer 11 | /// range of a data segment before passing the transfer off to an optional 12 | /// next data destination. 13 | class DataLineMapBuilderDestination : public DataDestination { 14 | public: 15 | /// @param data_line_map The data line map to build. 16 | /// @param next_destination An optional next transfer data destination 17 | DataLineMapBuilderDestination(DataLineMap* data_line_map, 18 | DataDestination* next_destination) 19 | : data_line_map_(data_line_map), 20 | next_destination_(next_destination), 21 | bytes_transferred_(0) {} 22 | void StartTransfer() override { 23 | if (next_destination_ != nullptr) { 24 | next_destination_->StartTransfer(); 25 | } 26 | } 27 | void FinishTransfer() override { 28 | if (next_destination_ != nullptr) { 29 | next_destination_->FinishTransfer(); 30 | } 31 | } 32 | TransferStatus Transfer(const DataRange& transfer_range, 33 | const DataSegment& data_segment) override { 34 | bytes_transferred_ += transfer_range.GetLength(); 35 | data_line_map_->FindDataLines(transfer_range, data_segment); 36 | return next_destination_ != nullptr 37 | ? next_destination_->Transfer(transfer_range, data_segment) 38 | : kTransferOk; 39 | } 40 | size_t GetBytesTransferred() const override { return bytes_transferred_; } 41 | 42 | private: 43 | DataLineMap* data_line_map_; 44 | DataDestination* next_destination_; 45 | size_t bytes_transferred_; 46 | }; 47 | 48 | } // namespace image_io 49 | } // namespace photos_editing_formats 50 | 51 | #endif // IMAGE_IO_BASE_DATA_LINE_MAP_BUILDER_DESTINATION_H_ // NOLINT 52 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/base/data_range.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_BASE_DATA_RANGE_H_ // NOLINT 2 | #define IMAGE_IO_BASE_DATA_RANGE_H_ // NOLINT 3 | 4 | #include 5 | 6 | namespace photos_editing_formats { 7 | namespace image_io { 8 | 9 | /// A class to specify a range of bytes in some sort of array. The range is 10 | /// defined like others in STL to include the begin value and exclude the end 11 | /// value: [begin,end). Invalid ranges where end <= begin are ok - no exceptions 12 | /// are ever thrown - but the IsValid() function will return false, and other 13 | /// functions will behave in an appropriate fashion. 14 | class DataRange { 15 | public: 16 | /// The main constructor to define a range. 17 | /// @param begin The begin location of the range. 18 | /// @param end The end location of the range. 19 | DataRange(size_t begin, size_t end) : begin_(begin), end_(end) {} 20 | 21 | /// The default construtor defines an invalid range in which both begin and 22 | /// end are set to 0. 23 | DataRange() : begin_(0), end_(0) {} 24 | 25 | DataRange(const DataRange& data_range) = default; 26 | DataRange& operator=(const DataRange& data_range) = default; 27 | 28 | /// @return The begin value of the range. 29 | size_t GetBegin() const { return begin_; } 30 | 31 | /// @return The end value of the rangel. 32 | size_t GetEnd() const { return end_; } 33 | 34 | /// @return Whether the range is valid. 35 | bool IsValid() const { return begin_ < end_; } 36 | 37 | /// @return The length of the range, or 0 if the range is invalid. 38 | size_t GetLength() const { return IsValid() ? end_ - begin_ : 0; } 39 | 40 | /// Determines if the location is in this range or not. 41 | /// @param location The location being considered for this test. 42 | /// @return True if the location is in the range, else false. 43 | bool Contains(size_t location) const { 44 | return location >= begin_ && location < end_; 45 | } 46 | 47 | /// Determines if another DataRange is a subrange of this range or not. 48 | /// @param data_range The DataRange being considered for this test. 49 | /// @return True if data_range is subrange of this range, else not. 50 | bool Contains(const DataRange& data_range) const { 51 | return IsValid() && data_range.IsValid() && data_range.begin_ >= begin_ && 52 | data_range.end_ <= end_; 53 | } 54 | 55 | /// Computes the DataRange that is the intersection of another range with this 56 | /// one. If there is no intersection, the resulting range will be invalid. 57 | /// @param data_range The DataRange to use compute the intersection with this 58 | /// one. 59 | /// @return The DataRange that represents the intersection, or one that is 60 | /// is invalid if the ranges do not overlap at all. 61 | DataRange GetIntersection(const DataRange& data_range) const { 62 | return DataRange((std::max)(data_range.begin_, begin_), 63 | (std::min)(data_range.end_, end_)); 64 | } 65 | 66 | /// @param rhs A DataRange to compare with this one. 67 | /// @return True if the two ranges are equal (even if invalid), else false. 68 | bool operator==(const DataRange& rhs) const { 69 | return begin_ == rhs.begin_ && end_ == rhs.end_; 70 | } 71 | 72 | /// @param rhs A DataRange to compare with this one. 73 | /// @return True if the two ranges not equal (even if invalid), else false. 74 | bool operator!=(const DataRange& rhs) const { 75 | return begin_ != rhs.begin_ || end_ != rhs.end_; 76 | } 77 | 78 | private: 79 | /// The begin value of the range. 80 | size_t begin_; 81 | 82 | /// The end value of the range. 83 | size_t end_; 84 | }; 85 | 86 | } // namespace image_io 87 | } // namespace photos_editing_formats 88 | 89 | #endif // IMAGE_IO_BASE_DATA_RANGE_H_ // NOLINT 90 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/base/data_range_tracking_destination.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_BASE_DATA_RANGE_TRACKING_DESTINATION_H_ // NOLINT 2 | #define IMAGE_IO_BASE_DATA_RANGE_TRACKING_DESTINATION_H_ // NOLINT 3 | 4 | #include "image_io/base/data_destination.h" 5 | #include "image_io/base/data_range.h" 6 | 7 | namespace photos_editing_formats { 8 | namespace image_io { 9 | 10 | /// A DataDestination that tracks the transfer_range values as they are passed 11 | /// from the caller of the Transfer() function to next DataDestination. 12 | /// Instances of this class can be used to track the number of bytes transferred 13 | /// and/or to ensure that multiple calls to the Transfer() function are called 14 | /// with transfer_range values that join in a end-to-begin fashion. This data 15 | /// can be used to make sure that the data transferred meets the expectations of 16 | /// the client. 17 | class DataRangeTrackingDestination : public DataDestination { 18 | public: 19 | /// @param destination The DataDestination that is next in the chain, or 20 | /// nullptr if there is no destination. 21 | explicit DataRangeTrackingDestination(DataDestination* destination) 22 | : destination_(destination), 23 | bytes_transferred_(0), 24 | has_disjoint_transfer_ranges_(false) {} 25 | 26 | /// @return The number of bytes written to the data destination. Bytes are 27 | /// considered "written" even if the next destination is a nullptr. 28 | size_t GetBytesTransferred() const override { return bytes_transferred_; } 29 | 30 | /// @return The tracked data range (see the class comment for how this value 31 | /// is computed). 32 | const DataRange& GetTrackedDataRange() const { return tracked_data_range_; } 33 | 34 | /// @return Whether disjoint transfer data ranges were detected by the 35 | /// Transfer() function. Disjoint transfer ranges occur when two calls 36 | /// to the Transfer() function occur where first_range.GetEnd() is not 37 | //// equal to the second_range.GetBegin(). 38 | bool HasDisjointTransferRanges() const { 39 | return has_disjoint_transfer_ranges_; 40 | } 41 | 42 | void StartTransfer() override; 43 | TransferStatus Transfer(const DataRange& transfer_range, 44 | const DataSegment& data_segment) override; 45 | void FinishTransfer() override; 46 | 47 | private: 48 | DataDestination* destination_; 49 | DataRange tracked_data_range_; 50 | size_t bytes_transferred_; 51 | bool has_disjoint_transfer_ranges_; 52 | }; 53 | 54 | } // namespace image_io 55 | } // namespace photos_editing_formats 56 | 57 | #endif // IMAGE_IO_BASE_DATA_RANGE_TRACKING_DESTINATION_H_ // NOLINT 58 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/base/data_segment_data_source.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_BASE_DATA_SEGMENT_DATA_SOURCE_H_ // NOLINT 2 | #define IMAGE_IO_BASE_DATA_SEGMENT_DATA_SOURCE_H_ // NOLINT 3 | 4 | #include "image_io/base/data_source.h" 5 | 6 | namespace photos_editing_formats { 7 | namespace image_io { 8 | 9 | /// DataSegmentDataSource is an implementation of DataSource that provides 10 | /// access to requested DataSegment instances from a single (possibly large) 11 | /// in-memory DataSegment. 12 | class DataSegmentDataSource : public DataSource { 13 | public: 14 | explicit DataSegmentDataSource( 15 | const std::shared_ptr& shared_data_segment) 16 | : shared_data_segment_(shared_data_segment) {} 17 | void Reset() override; 18 | std::shared_ptr GetDataSegment(size_t begin, 19 | size_t min_size) override; 20 | TransferDataResult TransferData(const DataRange& data_range, size_t best_size, 21 | DataDestination* data_destination) override; 22 | 23 | private: 24 | std::shared_ptr shared_data_segment_; 25 | }; 26 | 27 | } // namespace image_io 28 | } // namespace photos_editing_formats 29 | 30 | #endif // IMAGE_IO_BASE_DATA_SEGMENT_DATA_SOURCE_H_ // NOLINT 31 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/base/istream_data_source.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_BASE_ISTREAM_DATA_SOURCE_H_ // NOLINT 2 | #define IMAGE_IO_BASE_ISTREAM_DATA_SOURCE_H_ // NOLINT 3 | 4 | #include 5 | #include 6 | 7 | #include "image_io/base/istream_ref_data_source.h" 8 | 9 | namespace photos_editing_formats { 10 | namespace image_io { 11 | 12 | /// A DataSource that obtains data from an istream that it owns. 13 | class IStreamDataSource : public IStreamRefDataSource { 14 | public: 15 | /// Constructs an IStreamDataSource using the given istream. 16 | /// @param istram_ptr The istream from which to read. 17 | explicit IStreamDataSource(std::unique_ptr istream_ptr) 18 | : IStreamRefDataSource(*istream_ptr), istream_(std::move(istream_ptr)) {} 19 | 20 | private: 21 | /// The istream that is owned by this data source. 22 | std::unique_ptr istream_; 23 | }; 24 | 25 | } // namespace image_io 26 | } // namespace photos_editing_formats 27 | 28 | #endif // IMAGE_IO_BASE_ISTREAM_DATA_SOURCE_H_ // NOLINT 29 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/base/istream_ref_data_source.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_BASE_ISTREAM_REF_DATA_SOURCE_H_ // NOLINT 2 | #define IMAGE_IO_BASE_ISTREAM_REF_DATA_SOURCE_H_ // NOLINT 3 | 4 | #include 5 | 6 | #include "image_io/base/data_source.h" 7 | 8 | namespace photos_editing_formats { 9 | namespace image_io { 10 | 11 | /// A DataSource that obtains data from an istream held as a reference. 12 | class IStreamRefDataSource : public DataSource { 13 | public: 14 | /// Constructs an IStreamDataSource using the given istream. 15 | /// @param istream_ref The istream from which to read. 16 | explicit IStreamRefDataSource(std::istream& istream_ref) 17 | : istream_ref_(istream_ref) {} 18 | IStreamRefDataSource(const IStreamRefDataSource&) = delete; 19 | IStreamRefDataSource& operator=(const IStreamRefDataSource&) = delete; 20 | 21 | void Reset() override; 22 | std::shared_ptr GetDataSegment(size_t begin, 23 | size_t min_size) override; 24 | TransferDataResult TransferData(const DataRange& data_range, size_t best_size, 25 | DataDestination* data_destination) override; 26 | 27 | private: 28 | /// The worker function to create a DataSegment and fill it with the given 29 | /// number of bytes read from the istream, starting at the given location. 30 | /// @param begin The location in the istream at which to start reading. 31 | /// @param count The number of bytes to read. 32 | /// @return A DataSegment pointer, or nullptr if the read failed. 33 | std::shared_ptr Read(size_t begin, size_t count); 34 | 35 | private: 36 | /// The istream from which to read. 37 | std::istream& istream_ref_; 38 | 39 | /// The current data segment that was read in the GetDataSegment() function. 40 | std::shared_ptr current_data_segment_; 41 | }; 42 | 43 | } // namespace image_io 44 | } // namespace photos_editing_formats 45 | 46 | #endif // IMAGE_IO_BASE_ISTREAM_REF_DATA_SOURCE_H_ // NOLINT 47 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/base/message.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_BASE_MESSAGE_H_ // NOLINT 2 | #define IMAGE_IO_BASE_MESSAGE_H_ // NOLINT 3 | 4 | #include 5 | 6 | namespace photos_editing_formats { 7 | namespace image_io { 8 | 9 | /// A message that is reported to and managed by the MessageHandler, and 10 | /// possibly written by a MessageWriter. 11 | class Message { 12 | public: 13 | /// The types of Messages. 14 | enum Type { 15 | /// A Status message. 16 | kStatus, 17 | 18 | /// A Warning message. 19 | kWarning, 20 | 21 | /// An error from the stdlib was detected. The std::errno variable can be 22 | /// used to programmatically decide what to do, or use the std::strerror 23 | /// function to get a string description of the error. 24 | kStdLibError, 25 | 26 | /// A premature end of the data being processed was found. 27 | kPrematureEndOfDataError, 28 | 29 | /// An expected string value was not found in the data being processed. 30 | kStringNotFoundError, 31 | 32 | /// An error occurred while decoding the data being processed. 33 | kDecodingError, 34 | 35 | /// An error occurred while parsing the data. 36 | kSyntaxError, 37 | 38 | /// An error occurred while using the data. 39 | kValueError, 40 | 41 | /// An internal error of some sort occurred. 42 | kInternalError 43 | }; 44 | 45 | /// @param type The type of message to create. 46 | /// @param system_errno The errno value to use for kStdLibError type messages. 47 | /// @param text The text of the message. 48 | Message(Type type, int system_errno, const std::string& text) 49 | : type_(type), system_errno_(system_errno), text_(text) {} 50 | 51 | Message() = delete; 52 | 53 | bool operator==(const Message& rhs) const { 54 | return type_ == rhs.type_ && system_errno_ == rhs.system_errno_ && 55 | text_ == rhs.text_; 56 | } 57 | 58 | bool operator!=(const Message& rhs) const { 59 | return type_ != rhs.type_ || system_errno_ != rhs.system_errno_ || 60 | text_ != rhs.text_; 61 | } 62 | 63 | /// @return The type of message. 64 | Type GetType() const { return type_; } 65 | 66 | /// @return The system errno value used for kStdLibError messages. 67 | int GetSystemErrno() const { return system_errno_; } 68 | 69 | /// @return The text of the message. 70 | const std::string& GetText() const { return text_; } 71 | 72 | /// @return Whether the message is an error message. 73 | bool IsError() const { 74 | return type_ != Message::kStatus && type_ != Message::kWarning; 75 | } 76 | 77 | /// @return Whether the message is a warning message. 78 | bool IsWarning() const { return type_ == Message::kWarning; } 79 | 80 | /// @return Whether the message is a status message. 81 | bool IsStatus() const { return type_ == Message::kStatus; } 82 | 83 | private: 84 | /// The type of message. 85 | Type type_; 86 | 87 | /// If type == kStdLibError, the system's errno value at the time 88 | /// the error was reported, else it's value is 0. 89 | int system_errno_; 90 | 91 | /// The text associated with the message. 92 | std::string text_; 93 | }; 94 | 95 | } // namespace image_io 96 | } // namespace photos_editing_formats 97 | 98 | #endif // IMAGE_IO_BASE_MESSAGE_H_ // NOLINT 99 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/base/message_stats.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_BASE_MESSAGE_STATS_H_ // NOLINT 2 | #define IMAGE_IO_BASE_MESSAGE_STATS_H_ // NOLINT 3 | 4 | #include "image_io/base/types.h" 5 | 6 | namespace photos_editing_formats { 7 | namespace image_io { 8 | 9 | /// A structure for holding message stats. 10 | struct MessageStats { 11 | MessageStats() { Clear(); } 12 | void Clear() { error_count = warning_count = status_count = 0; } 13 | bool operator!=(const MessageStats& rhs) const { return !(*this == rhs); } 14 | bool operator==(const MessageStats& rhs) const { 15 | return error_count == rhs.error_count && 16 | warning_count == rhs.warning_count && 17 | status_count == rhs.status_count; 18 | } 19 | size_t error_count; 20 | size_t warning_count; 21 | size_t status_count; 22 | }; 23 | 24 | } // namespace image_io 25 | } // namespace photos_editing_formats 26 | 27 | #endif // IMAGE_IO_BASE_MESSAGE_STATS_H_ // NOLINT 28 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/base/message_store.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_BASE_MESSAGE_STORE_H_ // NOLINT 2 | #define IMAGE_IO_BASE_MESSAGE_STORE_H_ // NOLINT 3 | 4 | #include 5 | #include "image_io/base/message.h" 6 | 7 | namespace photos_editing_formats { 8 | namespace image_io { 9 | 10 | /// An abstract base class for storing and reporting on Messages. 11 | class MessageStore { 12 | public: 13 | virtual ~MessageStore() = default; 14 | 15 | /// Clears the messages maintained by the store. 16 | virtual void ClearMessages() = 0; 17 | 18 | // @message The message to add to the store. 19 | virtual void AddMessage(const Message& message) = 0; 20 | 21 | /// @return A vector of messages maintained by the store; this vector may be 22 | /// empty even if the AddMessage function was called, depending on the 23 | /// concrete subclass is implemented. 24 | virtual std::vector GetMessages() const = 0; 25 | 26 | /// @return Whether the store has error messages or not. This value is 27 | /// guarenteed to be accurate based on the latest calls to the 28 | /// ClearMessages and AddMessage functions. 29 | virtual bool HasErrorMessages() const = 0; 30 | }; 31 | 32 | /// A MessageStore that saves the messages in a vector. The implementation of 33 | /// this class is not thread safe. 34 | class VectorMessageStore : public MessageStore { 35 | public: 36 | void ClearMessages() override { messages_.clear(); } 37 | void AddMessage(const Message& message) override { 38 | messages_.push_back(message); 39 | } 40 | std::vector GetMessages() const override { return messages_; } 41 | bool HasErrorMessages() const override { 42 | for (const auto& message : messages_) { 43 | if (message.GetType() != Message::kStatus) { 44 | return true; 45 | } 46 | } 47 | return false; 48 | } 49 | 50 | private: 51 | std::vector messages_; 52 | }; 53 | 54 | /// A MessageStore that simply keeps track of whether error messages have been 55 | /// added or not, but does not store the messages themselves. The implementation 56 | /// of this class is should not cause any crashes if run in a multi-threaded 57 | /// environment, though there may be some cases where erroneous results are 58 | /// returned by the HasErrorMessages function. 59 | class ErrorFlagMessageStore : public MessageStore { 60 | public: 61 | ErrorFlagMessageStore() : has_error_(false) {} 62 | void ClearMessages() override { has_error_ = false; } 63 | void AddMessage(const Message& message) override { 64 | if (message.IsError()) { 65 | has_error_ = true; 66 | } 67 | } 68 | std::vector GetMessages() const override { 69 | return std::vector(); 70 | } 71 | bool HasErrorMessages() const override { return has_error_; } 72 | 73 | private: 74 | bool has_error_; 75 | }; 76 | 77 | } // namespace image_io 78 | } // namespace photos_editing_formats 79 | 80 | #endif // IMAGE_IO_BASE_MESSAGE_STORE_H_ // NOLINT 81 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/base/message_writer.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_BASE_MESSAGE_WRITER_H_ // NOLINT 2 | #define IMAGE_IO_BASE_MESSAGE_WRITER_H_ // NOLINT 3 | 4 | #include "image_io/base/message.h" 5 | 6 | namespace photos_editing_formats { 7 | namespace image_io { 8 | 9 | /// A message writer is used by MessageHandler to write messages as they are 10 | /// reported via the ReportMessage function. The main function, WriteMessage 11 | /// must be implemented by subclasses. Subclasses can also override any or all 12 | /// of the other virtual functions, GetFormattedMessage(), GetTypeCategory() 13 | /// and GetTypeDescription() to suit their needs. 14 | class MessageWriter { 15 | public: 16 | virtual ~MessageWriter() = default; 17 | 18 | /// This function is called to write a message. Implementations can call the 19 | /// GetFormattedMessage function and write it wherever it needs to go, or 20 | /// do something else entirely. 21 | /// @param message The message to write. 22 | virtual void WriteMessage(const Message& message) = 0; 23 | 24 | /// Formats the message into a single string suitable for writing. This 25 | /// implementation returns a string that has the format 26 | /// :text 27 | /// @param message The message for which a formatted string is wanted. 28 | /// @return A string describing the message. 29 | virtual std::string GetFormattedMessage(const Message& message) const; 30 | 31 | /// @param type The type of message to get the category of. 32 | /// @return A string describing the type category; this implementation returns 33 | /// (the obviously nonlocalized strings) "STATUS" or "ERROR" 34 | virtual std::string GetTypeCategory(Message::Type type) const; 35 | 36 | /// @param type The type of message to get the description of. 37 | /// @param system_errno Used for kStdLibError type messages. 38 | /// @return A (non-localized) string description of the type. 39 | virtual std::string GetTypeDescription(Message::Type type, 40 | int system_errno) const; 41 | }; 42 | 43 | } // namespace image_io 44 | } // namespace photos_editing_formats 45 | 46 | #endif // IMAGE_IO_BASE_MESSAGE_WRITER_H_ // NOLINT 47 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/base/ostream_data_destination.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_BASE_OSTREAM_DATA_DESTINATION_H_ // NOLINT 2 | #define IMAGE_IO_BASE_OSTREAM_DATA_DESTINATION_H_ // NOLINT 3 | 4 | #include 5 | #include 6 | 7 | #include "image_io/base/ostream_ref_data_destination.h" 8 | 9 | namespace photos_editing_formats { 10 | namespace image_io { 11 | 12 | /// A DataDestination that writes its output to an ostream. 13 | class OStreamDataDestination : public OStreamRefDataDestination { 14 | public: 15 | /// Constructs an OStreamDataDestination using the given ostream. 16 | /// @param ostream_ptr The ostream to which data is written. 17 | /// @param message_handler An option message handler for writing messages. 18 | OStreamDataDestination(std::unique_ptr ostream_ptr, 19 | MessageHandler* message_handler) 20 | : OStreamRefDataDestination(*ostream_ptr, message_handler), 21 | ostream_(std::move(ostream_ptr)) {} 22 | 23 | private: 24 | /// The ostream that is owned by this data destination. 25 | std::unique_ptr ostream_; 26 | }; 27 | 28 | } // namespace image_io 29 | } // namespace photos_editing_formats 30 | 31 | #endif // IMAGE_IO_BASE_OSTREAM_DATA_DESTINATION_H_ // NOLINT 32 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/base/ostream_ref_data_destination.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_BASE_OSTREAM_REF_DATA_DESTINATION_H_ // NOLINT 2 | #define IMAGE_IO_BASE_OSTREAM_REF_DATA_DESTINATION_H_ // NOLINT 3 | 4 | #include 5 | #include 6 | 7 | #include "image_io/base/data_destination.h" 8 | #include "image_io/base/message_handler.h" 9 | 10 | namespace photos_editing_formats { 11 | namespace image_io { 12 | 13 | /// A DataDestination that writes its output to an ostream held as a reference. 14 | class OStreamRefDataDestination : public DataDestination { 15 | public: 16 | /// Constructs an OStreamDataDestination using the given ostream. 17 | /// @param ostream_ref The ostream to which data is written. 18 | /// @param message_handler An option message handler for writing messages. 19 | OStreamRefDataDestination(std::ostream& ostream_ref, 20 | MessageHandler* message_handler) 21 | : ostream_ref_(ostream_ref), 22 | message_handler_(message_handler), 23 | bytes_transferred_(0), 24 | has_error_(false) {} 25 | OStreamRefDataDestination(const OStreamRefDataDestination&) = delete; 26 | OStreamRefDataDestination& operator=(const OStreamRefDataDestination&) = 27 | delete; 28 | 29 | /// @param name A name to associate with the ostream. Used for error messages. 30 | void SetName(const std::string& name) { name_ = name; } 31 | 32 | /// @return The name associated with the ostream. 33 | const std::string& GetName() const { return name_; } 34 | 35 | /// @return The number of bytes written to the ostream. 36 | size_t GetBytesTransferred() const override { return bytes_transferred_; } 37 | 38 | /// @return True if errors were encountered while writing to the ostream. 39 | bool HasError() const { return has_error_; } 40 | 41 | void StartTransfer() override; 42 | TransferStatus Transfer(const DataRange& transfer_range, 43 | const DataSegment& data_segment) override; 44 | void FinishTransfer() override; 45 | 46 | private: 47 | /// The ostream written to. 48 | std::ostream& ostream_ref_; 49 | 50 | /// An optional message handler to write messages to. 51 | MessageHandler* message_handler_; 52 | 53 | /// The number of bytes written so far. 54 | size_t bytes_transferred_; 55 | 56 | /// A (file) name to associate with the ostream, used with error messages. 57 | std::string name_; 58 | 59 | /// If true indicates an error has occurred writing to the ostream. 60 | bool has_error_; 61 | }; 62 | 63 | } // namespace image_io 64 | } // namespace photos_editing_formats 65 | 66 | #endif // IMAGE_IO_BASE_OSTREAM_REF_DATA_DESTINATION_H_ // NOLINT 67 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/base/string_ref_data_source.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_BASE_STRING_REF_DATA_SOURCE_H_ // NOLINT 2 | #define IMAGE_IO_BASE_STRING_REF_DATA_SOURCE_H_ // NOLINT 3 | 4 | #include 5 | 6 | #include "image_io/base/data_segment_data_source.h" 7 | 8 | namespace photos_editing_formats { 9 | namespace image_io { 10 | 11 | /// A DataSource that reads bytes from a string held by ref. The underlying 12 | /// string must have a lifetime that exceeds the lifetime of this data source, 13 | /// and the string contents must not change while the data source is referencing 14 | /// it. 15 | class StringRefDataSource : public DataSegmentDataSource { 16 | public: 17 | /// Constructs a StringRefDataSource using the given string. 18 | /// @param string_refg The string to read from. 19 | explicit StringRefDataSource(const std::string& string_ref); 20 | 21 | /// Returns the string being used as the data source. 22 | const std::string& GetStringRef() const { return string_ref_; } 23 | 24 | private: 25 | /// The string to read from. 26 | const std::string& string_ref_; 27 | }; 28 | 29 | } // namespace image_io 30 | } // namespace photos_editing_formats 31 | 32 | #endif // IMAGE_IO_BASE_STRING_REF_DATA_SOURCE_H_ // NOLINT 33 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/base/types.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_BASE_TYPES_H_ // NOLINT 2 | #define IMAGE_IO_BASE_TYPES_H_ // NOLINT 3 | 4 | #include 5 | #include 6 | 7 | namespace photos_editing_formats { 8 | namespace image_io { 9 | 10 | /// The various integer and byte types used in this package. 11 | using Byte = std::uint8_t; 12 | using Int32 = std::int32_t; 13 | using Int64 = std::int64_t; 14 | using UInt8 = std::uint8_t; 15 | using UInt16 = std::uint16_t; 16 | using UInt32 = std::uint32_t; 17 | using UInt64 = std::uint64_t; 18 | 19 | /// A Byte value and a validity flag. 20 | struct ValidatedByte { 21 | explicit ValidatedByte(Byte value_arg) : value(value_arg), is_valid(true) {} 22 | ValidatedByte(const ValidatedByte&) = default; 23 | ValidatedByte& operator=(const ValidatedByte&) = default; 24 | Byte value; 25 | bool is_valid; 26 | }; 27 | 28 | /// Equality operator for ValidatedByte 29 | inline bool operator==(const ValidatedByte& lhs, const ValidatedByte& rhs) { 30 | return lhs.value == rhs.value && lhs.is_valid == rhs.is_valid; 31 | } 32 | 33 | /// Inquality operator for ValidatedByte 34 | inline bool operator!=(const ValidatedByte& lhs, const ValidatedByte& rhs) { 35 | return lhs.value != rhs.value || lhs.is_valid != rhs.is_valid; 36 | } 37 | 38 | /// @return a validated byte that has a false is_valid value. 39 | inline ValidatedByte InvalidByte() { 40 | ValidatedByte invalid_byte(0); 41 | invalid_byte.is_valid = false; 42 | return invalid_byte; 43 | } 44 | 45 | } // namespace image_io 46 | } // namespace photos_editing_formats 47 | 48 | #endif // IMAGE_IO_BASE_TYPES_H_ // NOLINT 49 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/base/validated_number.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_BASE_VALIDATED_NUMBER_H_ // NOLINT 2 | #define IMAGE_IO_BASE_VALIDATED_NUMBER_H_ // NOLINT 3 | 4 | #include 5 | #include 6 | 7 | namespace photos_editing_formats { 8 | namespace image_io { 9 | 10 | template 11 | struct ValidatedNumber { 12 | ValidatedNumber() : ValidatedNumber(T(), false) {} 13 | ValidatedNumber(const T& value_, bool is_valid_) 14 | : value(value_), is_valid(is_valid_) {} 15 | using value_type = T; 16 | T value; 17 | bool is_valid; 18 | }; 19 | 20 | template 21 | ValidatedNumber GetValidatedNumber(const std::string& str) { 22 | std::stringstream ss(str); 23 | ValidatedNumber result; 24 | ss >> result.value; 25 | if (!ss.fail()) { 26 | std::string extra; 27 | ss >> extra; 28 | if (extra.empty()) { 29 | result.is_valid = true; 30 | } 31 | } 32 | return result; 33 | } 34 | 35 | } // namespace image_io 36 | } // namespace photos_editing_formats 37 | 38 | #endif // IMAGE_IO_BASE_VALIDATED_NUMBER_H_ // NOLINT 39 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/extras/base64_decoder_data_destination.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_EXTRAS_BASE64_DECODER_DATA_DESTINATION_H_ // NOLINT 2 | #define IMAGE_IO_EXTRAS_BASE64_DECODER_DATA_DESTINATION_H_ // NOLINT 3 | #define IMAGE_IO_noumenon_base64_h 4 | 5 | #include 6 | 7 | #include "image_io/base/data_destination.h" 8 | #include "image_io/base/message_handler.h" 9 | 10 | namespace photos_editing_formats { 11 | namespace image_io { 12 | 13 | /// Base64DecoderDataDestination is typically used in a chain of DataDestination 14 | /// instances. For example, it can be used to decode base64 encoded JPEG data in 15 | /// APP1/XMP data segments. 16 | class Base64DecoderDataDestination : public DataDestination { 17 | public: 18 | /// @param next_destination The next DataDestination in the chain which will 19 | /// be sent the decoded bytes received by the Transfer() function. 20 | /// @param message_handler An optional message handler to write messages to. 21 | Base64DecoderDataDestination(DataDestination* next_destination, 22 | MessageHandler* message_handler) 23 | : next_destination_(next_destination), 24 | message_handler_(message_handler), 25 | next_decoded_location_(0), 26 | has_error_(false) {} 27 | 28 | /// @return True if there was an error in the decoding process. 29 | bool HasError() const { return has_error_; } 30 | 31 | void StartTransfer() override; 32 | TransferStatus Transfer(const DataRange& transfer_range, 33 | const DataSegment& data_segment) override; 34 | void FinishTransfer() override; 35 | 36 | /// @return The number of bytes written not to this decoder destination, but 37 | /// to the next destination. Returns zero if the next destination is null. 38 | size_t GetBytesTransferred() const override { 39 | return next_destination_ ? next_destination_->GetBytesTransferred() : 0; 40 | } 41 | 42 | private: 43 | /// The destination that the decoded data is sent to. 44 | DataDestination* next_destination_; 45 | 46 | /// An optional message handler to write messages to. 47 | MessageHandler* message_handler_; 48 | 49 | /// If the transfer_range parameter of the Transfer function does not have a 50 | /// length that is a multiple of 4, then the leftover bytes are placed in this 51 | /// vector and are prepended to the data in the next call to Transfer. 52 | std::vector leftover_bytes_; 53 | 54 | /// The DataRanges supplied to the Transfer function can't be sent down the 55 | /// chain to the next destination because the number of bytes differ (by 4/3). 56 | /// This value records the number of bytes decoded so far, and the beginning 57 | /// of the DataRange sent to the destination's Transfer function. 58 | size_t next_decoded_location_; 59 | 60 | /// A true value indicates that an error occurred in the decoding process. 61 | bool has_error_; 62 | }; 63 | 64 | } // namespace image_io 65 | } // namespace photos_editing_formats 66 | 67 | #endif // IMAGE_IO_EXTRAS_BASE64_DECODER_DATA_DESTINATION_H_ // NOLINT 68 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/gcontainer/gcontainer.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_GCONTAINER_GCONTAINER_H_ // NOLINT 2 | #define IMAGE_IO_GCONTAINER_GCONTAINER_H_ // NOLINT 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace photos_editing_formats { 9 | namespace image_io { 10 | namespace gcontainer { 11 | 12 | // Writes an image to a output_file_name, appending other_files (if they each 13 | // exist) after the image's EOI marker. 14 | // input_file_name must be a JPEG file. 15 | bool WriteImageAndFiles(const std::string& input_file_name, 16 | const std::vector& other_files, 17 | const std::string& output_file_name); 18 | 19 | // Retrieves the bytes (of size file_length) starting at file_starT_offset 20 | // bytes after the EOI marker in input_file_name. Returns true if parsing was 21 | // successful, false otherwise. GContainer callers are expected to have 22 | // file_start_offset and file_length from the image metadata. 23 | // 24 | // input_file_name must be a JPEG. 25 | // file_start_offset is the nth byte after (and excluding) the EOI marker in 26 | // input_file_name. file_length is the size (in bytes) of content to parse. 27 | // out_file_contents is populated with the requsted contents only if parsing is 28 | // successful. 29 | bool ParseFileAfterImage(const std::string& input_file_name, 30 | size_t file_start_offset, size_t file_length, 31 | std::string* out_file_contents); 32 | 33 | // Used by AOSP. 34 | bool ParseFileAfterImageFromStream(size_t start_offset, size_t length, 35 | std::istream& input_jpeg_stream, 36 | std::string* out_contents); 37 | 38 | } // namespace gcontainer 39 | } // namespace image_io 40 | } // namespace photos_editing_formats 41 | 42 | #endif // IMAGE_IO_GCONTAINER_GCONTAINER_H_ // NOLINT 43 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/jpeg/jpeg_image_extractor.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_JPEG_JPEG_IMAGE_EXTRACTOR_H_ // NOLINT 2 | #define IMAGE_IO_JPEG_JPEG_IMAGE_EXTRACTOR_H_ // NOLINT 3 | 4 | #include "image_io/base/data_destination.h" 5 | #include "image_io/base/data_source.h" 6 | #include "image_io/base/message_handler.h" 7 | #include "image_io/jpeg/jpeg_info.h" 8 | 9 | namespace photos_editing_formats { 10 | namespace image_io { 11 | 12 | /// A class that can make use of the data in a JpegInfo instance to transfer 13 | /// Apple depth and GDepth/GImage images from a DataSource and ship it to a 14 | /// DataDestination. 15 | class JpegImageExtractor { 16 | public: 17 | /// @param jpeg_info The JpegInfo instance containing depth/image data. 18 | /// @param data_source The DataSource from which to transfer depth/image data. 19 | /// @param message_handler An optional message handler to write messages to. 20 | JpegImageExtractor(const JpegInfo& jpeg_info, DataSource* data_source, 21 | MessageHandler* message_handler) 22 | : jpeg_info_(jpeg_info), 23 | data_source_(data_source), 24 | message_handler_(message_handler) {} 25 | 26 | /// This function extracts the Apple depth image from the DataSource and sends 27 | /// the bytes to the DataDestination. 28 | /// @param image_destination The DataDestination to receive the image data. 29 | /// @return True if an image was extracted. 30 | bool ExtractAppleDepthImage(DataDestination* image_destination); 31 | 32 | /// This function extracts the Apple matte image from the DataSource and sends 33 | /// the bytes to the DataDestination. 34 | /// @param image_destination The DataDestination to receive the image data. 35 | /// @return True if an image was extracted. 36 | bool ExtractAppleMatteImage(DataDestination* image_destination); 37 | 38 | /// This function extracts the GDepth type image from the DataSource and 39 | /// sends the bytes to the DataDestination. 40 | /// @param image_destination The DataDestination to receive the image data. 41 | /// @return True if an image was extracted. 42 | bool ExtractGDepthImage(DataDestination* image_destination); 43 | 44 | /// This function extracts the GImage type image from the DataSource and 45 | /// sends the bytes to the DataDestination. 46 | /// @param image_destination The DataDestination to receive the image data. 47 | /// @return True if an image was extracted. 48 | bool ExtractGImageImage(DataDestination* image_destination); 49 | 50 | private: 51 | /// Worker function called for GDepth/GImage type image extraction. 52 | /// @param xmp_info_type The type of image to extract. 53 | /// @param image_destination The DataDestination to receive the image data. 54 | /// @return True if an image was extracted. 55 | bool ExtractImage(JpegXmpInfo::Type xmp_info_type, 56 | DataDestination* image_destination); 57 | 58 | /// Worker function called for Apple depth/matte type image extraction. 59 | /// @param image_range The range of the image data to extract. If invalid, 60 | /// the image_destination's StartTransfer/FinishTransfer functions are 61 | /// still called, and this function will return true (i.e., zero bytes 62 | /// "successfully" transferred). 63 | /// @param image_destination The DataDestination to receive the image data. 64 | /// @return True if the transfer succeeded. 65 | bool ExtractImage(const DataRange& image_range, 66 | DataDestination* image_destination); 67 | 68 | /// The jpeg info object contains the location of the Apple and Google images. 69 | JpegInfo jpeg_info_; 70 | 71 | /// The data source from which the images are extracted. 72 | DataSource* data_source_; 73 | 74 | /// An optional message handler to write messages to. 75 | MessageHandler* message_handler_; 76 | }; 77 | 78 | } // namespace image_io 79 | } // namespace photos_editing_formats 80 | 81 | #endif // IMAGE_IO_JPEG_JPEG_IMAGE_EXTRACTOR_H_ // NOLINT 82 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/jpeg/jpeg_marker.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_JPEG_JPEG_MARKER_H_ // NOLINT 2 | #define IMAGE_IO_JPEG_JPEG_MARKER_H_ // NOLINT 3 | 4 | #include 5 | #include 6 | 7 | #include "image_io/base/types.h" 8 | 9 | namespace photos_editing_formats { 10 | namespace image_io { 11 | 12 | /// The size of the array that would be needed to reference all marker types. 13 | const size_t kJpegMarkerArraySize = 256; 14 | 15 | /// A JpegMarker begins each JpegSegment in a JPEG file. The first byte of a 16 | /// marker is 0xFF, and the second byte is the marker type value. Bytes with 17 | /// values 0x00 and 0xFF indicate not a JpegMarker, but a zero byte or fill 18 | /// byte, respectively. That is the sequence FF00 must be interpreted as a 19 | /// single byte with a 0 value. The specification says that multiple fill bytes 20 | /// may appear before a valid marker start: FFFFFFDA - the leading FFFF should 21 | /// be ignored. 22 | class JpegMarker { 23 | public: 24 | /// The length of the marker in the JPEG file. One byte for the 0xFF value, 25 | /// and one byte for the marker type. 26 | static const size_t kLength = 2; 27 | 28 | /// The offset from the start of the JpegMarker that contains the marker type. 29 | static const size_t kTypeOffset = 1; 30 | 31 | /// The special byte value that may start a marker. 32 | static const Byte kStart = 0xFF; 33 | 34 | /// Special marker type values referenced elsewhere in the code. 35 | static const Byte kZERO = 0; 36 | static const Byte kSOS = 0xDA; 37 | static const Byte kSOI = 0xD8; 38 | static const Byte kEOI = 0xD9; 39 | static const Byte kAPP0 = 0xE0; 40 | static const Byte kAPP1 = 0xE1; 41 | static const Byte kAPP2 = 0xE2; 42 | static const Byte kFILL = 0xFF; 43 | 44 | /// A set of bits, one for each type of marker. 45 | using Flags = std::bitset; 46 | 47 | /// Creates a JpegMarker with the given type value. 48 | explicit JpegMarker(Byte type) : type_(type) {} 49 | 50 | JpegMarker() = delete; 51 | 52 | /// Not all byte values are used to represent markers. Bytes with values 0x00 53 | /// and 0xFF indicate a zero byte or fill byte, respectively. 54 | /// @return Whether this is a valid marker. 55 | bool IsValid() const { return type_ != kZERO && type_ != kFILL; } 56 | 57 | /// @return The type of the marker. 58 | Byte GetType() const { return type_; } 59 | 60 | /// @return The name of the marker type. 61 | const std::string GetName() const; 62 | 63 | /// @param prefix A prefix for the returned string. 64 | /// @return The XX hex string representation of the type. 65 | const std::string GetHexString(const std::string& prefix) const; 66 | 67 | /// Some markers have two extra bytes that indicate the size of the segment's 68 | /// data payload. See https://www.w3.org/Graphics/JPEG/itu-t81.pdf, Table B-2. 69 | /// @return Whether this marker type has such a variable length payload. 70 | bool HasVariablePayloadSize() const; 71 | 72 | /// Some markers are delimiters in an otherwise continuous stream of bytes in 73 | /// the JPEG file. See https://www.w3.org/Graphics/JPEG/itu-t81.pdf, Section 74 | /// B.2.1. 75 | /// @return Whether this is an entropy segment delimiter marker. 76 | bool IsEntropySegmentDelimiter() const; 77 | 78 | private: 79 | /// The type value of the marker. 80 | Byte type_; 81 | }; 82 | 83 | } // namespace image_io 84 | } // namespace photos_editing_formats 85 | 86 | #endif // IMAGE_IO_JPEG_JPEG_MARKER_H_ // NOLINT 87 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/jpeg/jpeg_scanner.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_JPEG_JPEG_SCANNER_H_ // NOLINT 2 | #define IMAGE_IO_JPEG_JPEG_SCANNER_H_ // NOLINT 3 | 4 | #include 5 | 6 | #include "image_io/base/data_segment.h" 7 | #include "image_io/base/data_source.h" 8 | #include "image_io/base/message_handler.h" 9 | #include "image_io/jpeg/jpeg_marker.h" 10 | #include "image_io/jpeg/jpeg_segment_processor.h" 11 | 12 | namespace photos_editing_formats { 13 | namespace image_io { 14 | 15 | /// JpegScanner reads DataSegments from a DataSource, finds interesting 16 | /// JpegSegments and passes them on to a JpegSegmentProcessor for further 17 | /// examination. 18 | class JpegScanner { 19 | public: 20 | explicit JpegScanner(MessageHandler* message_handler) 21 | : message_handler_(message_handler), 22 | data_source_(nullptr), 23 | segment_processor_(nullptr), 24 | current_location_(0), 25 | done_(false), 26 | has_error_(false) {} 27 | 28 | /// Called to start and run the scanner. 29 | /// @param data_source The DataSource from which to obtain DataSegments. 30 | /// @param segment_processor The processor of the JpegSegment instances. 31 | void Run(DataSource* data_source, JpegSegmentProcessor* segment_processor); 32 | 33 | /// If the JpegSegmentProcessor determines that it has seen enough JpegSegment 34 | /// instances, it can call this function to terminate the scanner prematurely. 35 | void SetDone() { done_ = true; } 36 | 37 | /// @return True if the done flag was set by SetDone(), else false. 38 | bool IsDone() const { return done_; } 39 | 40 | /// @return True if the scanner encountered errors. 41 | bool HasError() const { return has_error_; } 42 | 43 | /// @return The DataSource from which DataSegments are being read. 44 | DataSource* GetDataSource() const { return data_source_; } 45 | 46 | /// JpegSegmentProcessor instances can call this function to inform the 47 | /// scanner about the types of JpegSegment instances it is interested in. 48 | /// The JpegScanner will not send any uninteresting segments to the processor. 49 | void UpdateInterestingMarkerFlags(const JpegMarker::Flags& marker_flags) { 50 | interesting_marker_flags_ = marker_flags; 51 | } 52 | 53 | private: 54 | /// Called from the Run() function to do the heavy lifting. 55 | void FindAndProcessSegments(); 56 | 57 | /// @param marker The marker of the JpegSegment under construction. 58 | /// @param begin_location The start of the JpegSegment under construction. 59 | /// @return The size of the segment payload of given marker type that starts 60 | /// at the specified location. 61 | size_t GetPayloadSize(const JpegMarker& marker, size_t begin_location); 62 | 63 | /// @return The validated byte value at the given location. 64 | ValidatedByte GetValidatedByte(size_t location); 65 | 66 | /// Calls GetValidatedByte() and returns its value if the byte is valid, else 67 | /// sets the get_byte_error_ flag. 68 | /// @return the byte value at the given location, or 0 if the byte is invalid. 69 | Byte GetByte(size_t location); 70 | 71 | /// Asks the DataSource for the next DataSegment. 72 | void GetNextSegment(); 73 | 74 | private: 75 | /// An optional message handler to write messages to. 76 | MessageHandler* message_handler_; 77 | 78 | /// The DataSource from which DataSegments are obtained. 79 | DataSource* data_source_; 80 | 81 | /// The JpegSegmentProcessor to which JpegSegments are sent. 82 | JpegSegmentProcessor* segment_processor_; 83 | 84 | /// The JpegSegment types of interest to the JpegSegmentProcessor. 85 | JpegMarker::Flags interesting_marker_flags_; 86 | 87 | /// Depending on the DataSource, a given JpegSegment may span up to two 88 | /// DataSegments. These are they. 89 | std::shared_ptr current_segment_; 90 | std::shared_ptr next_segment_; 91 | 92 | /// The current location of the scanner in the DataSource. 93 | size_t current_location_; 94 | 95 | /// A flag that indicates the scanner is done, naturally or prematurely. 96 | bool done_; 97 | 98 | /// A flag that indicates an error occurred while getting Byte data. 99 | bool has_error_; 100 | }; 101 | 102 | } // namespace image_io 103 | } // namespace photos_editing_formats 104 | 105 | #endif // IMAGE_IO_JPEG_JPEG_SCANNER_H_ // NOLINT 106 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/jpeg/jpeg_segment_info.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_JPEG_JPEG_SEGMENT_INFO_H_ // NOLINT 2 | #define IMAGE_IO_JPEG_JPEG_SEGMENT_INFO_H_ // NOLINT 3 | 4 | #include 5 | #include 6 | 7 | #include "image_io/base/data_range.h" 8 | #include "image_io/base/types.h" 9 | 10 | namespace photos_editing_formats { 11 | namespace image_io { 12 | 13 | /// Interesting segment types. 14 | const char kExif[] = "Exif"; 15 | const char kJfif[] = "JFIF"; 16 | const char kMpf[] = "MPF"; 17 | 18 | /// A class that holds interesting information about a JpegSegment. 19 | class JpegSegmentInfo { 20 | public: 21 | /// @param image_index The index of the image in a @c DataSource that contains 22 | /// the segment. 23 | /// @param data_range The range in the segment in the @c DataSource. 24 | /// @param type The type of segment. 25 | JpegSegmentInfo(size_t image_index, const DataRange& data_range, 26 | const std::string& type) 27 | : image_index_(image_index), data_range_(data_range), type_(type) {} 28 | 29 | /// Constructs an empty, invalid segment info. 30 | JpegSegmentInfo() : image_index_(0) {} 31 | 32 | JpegSegmentInfo(const JpegSegmentInfo&) = default; 33 | JpegSegmentInfo& operator=(const JpegSegmentInfo&) = default; 34 | 35 | /// @param rhs The segment info to compare with this one. 36 | /// @return Whether the segment infos are equal 37 | bool operator==(const JpegSegmentInfo& rhs) const { 38 | return image_index_ == rhs.image_index_ && data_range_ == rhs.data_range_ && 39 | type_ == rhs.type_ && bytes_ == rhs.bytes_; 40 | } 41 | 42 | /// @param rhs The segment info to compare with this one. 43 | /// @return Whether the segment infos are not equal 44 | bool operator!=(const JpegSegmentInfo& rhs) const { 45 | return !(*this == rhs); 46 | } 47 | 48 | /// @return Whether the segment info is valid. 49 | bool IsValid() const { return !type_.empty() && data_range_.IsValid(); } 50 | 51 | /// @return The image index of the segment info. 52 | size_t GetImageIndex() const { return image_index_; } 53 | 54 | /// @return The data range of the segment info. 55 | const DataRange& GetDataRange() const { return data_range_; } 56 | 57 | /// @return The type of the segment info. 58 | const std::string& GetType() const { return type_; } 59 | 60 | /// @return The (optional) bytes of the segment to which the info refers. The 61 | /// vector will be empty unless the GetMutableBytes() function has been 62 | /// and the vector filled with the segment contents. 63 | const std::vector& GetBytes() const { return bytes_; } 64 | 65 | /// @return A non-const pointer to the bytes vector. 66 | std::vector* GetMutableBytes() { return &bytes_; } 67 | 68 | private: 69 | // The image index where the segment is located. 70 | size_t image_index_; 71 | 72 | // The data range of the segment. 73 | DataRange data_range_; 74 | 75 | // The type of segment. 76 | std::string type_; 77 | 78 | // The (optional) bytes of the segment. 79 | std::vector bytes_; 80 | }; 81 | 82 | } // namespace image_io 83 | } // namespace photos_editing_formats 84 | 85 | #endif // IMAGE_IO_JPEG_JPEG_SEGMENT_INFO_H_ // NOLINT 86 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/jpeg/jpeg_segment_lister.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_JPEG_JPEG_SEGMENT_LISTER_H_ // NOLINT 2 | #define IMAGE_IO_JPEG_JPEG_SEGMENT_LISTER_H_ // NOLINT 3 | 4 | #include 5 | #include 6 | 7 | #include "image_io/jpeg/jpeg_segment_processor.h" 8 | 9 | namespace photos_editing_formats { 10 | namespace image_io { 11 | 12 | /// JpegSegmentLister is an implementation of JpegSegmentProcesor that creates 13 | /// a listing (in the form of a vector of strings) describing the segments. 14 | class JpegSegmentLister : public JpegSegmentProcessor { 15 | public: 16 | JpegSegmentLister(); 17 | void Start(JpegScanner* scanner) override; 18 | void Process(JpegScanner* scanner, const JpegSegment& segment) override; 19 | void Finish(JpegScanner* scanner) override; 20 | 21 | /// @return The lines representing the listing of the segments. 22 | const std::vector& GetLines() const { return lines_; } 23 | 24 | private: 25 | /// The number of occurences of the various segment types. 26 | std::vector marker_type_counts_; 27 | 28 | /// The lines representing the listing output. 29 | std::vector lines_; 30 | }; 31 | 32 | } // namespace image_io 33 | } // namespace photos_editing_formats 34 | 35 | #endif // IMAGE_IO_JPEG_JPEG_SEGMENT_LISTER_H_ // NOLINT 36 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/jpeg/jpeg_segment_processor.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_JPEG_JPEG_SEGMENT_PROCESSOR_H_ // NOLINT 2 | #define IMAGE_IO_JPEG_JPEG_SEGMENT_PROCESSOR_H_ // NOLINT 3 | 4 | #include "image_io/jpeg/jpeg_segment.h" 5 | 6 | namespace photos_editing_formats { 7 | namespace image_io { 8 | 9 | class JpegScanner; 10 | 11 | /// JpegSegmentProcessor is the abstract base class for implementations that do 12 | /// something with the JPEG segments that the JpegScanner identifies. 13 | class JpegSegmentProcessor { 14 | public: 15 | virtual ~JpegSegmentProcessor() = default; 16 | 17 | /// This function is called at the start of the JPegScanner::Run() function to 18 | /// allow this JpegProcessor to initialize its data structures. It can also 19 | /// inform the JpegScanner about preferences for the types of segments it is 20 | /// interested in by calling the JpegScanner::UpdateInterestingMarkerFlags() 21 | /// function. 22 | /// @param scanner The scanner that is starting the JpegProcessor. 23 | virtual void Start(JpegScanner* scanner) = 0; 24 | 25 | /// This function is called repeatedly by the JpegScanner as it identifies 26 | /// segments in the JPEG file. The JpegProcessor can access the data in the 27 | /// segment to do interesting things, or can update the scanner's preferences 28 | /// like in the Start() function. 29 | /// @param scanner The scanner that is providing the segment to the processor. 30 | /// @param segment The segment provided by the scanner to the processor. 31 | virtual void Process(JpegScanner* scanner, const JpegSegment& segment) = 0; 32 | 33 | /// This function is called after the JpegScanner has provided all the 34 | /// segments to the JpegProcessor to allow the processor to finish its work 35 | /// processing the segments. 36 | /// @param scanner The scanner that is informing the processor that it is done 37 | /// finding segments. 38 | virtual void Finish(JpegScanner* scanner) = 0; 39 | }; 40 | 41 | } // namespace image_io 42 | } // namespace photos_editing_formats 43 | 44 | #endif // IMAGE_IO_JPEG_JPEG_SEGMENT_PROCESSOR_H_ // NOLINT 45 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/jpeg/jpeg_xmp_data_extractor.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_JPEG_JPEG_XMP_DATA_EXTRACTOR_H_ // NOLINT 2 | #define IMAGE_IO_JPEG_JPEG_XMP_DATA_EXTRACTOR_H_ // NOLINT 3 | 4 | #include "image_io/base/data_destination.h" 5 | #include "image_io/base/message_handler.h" 6 | #include "image_io/jpeg/jpeg_info.h" 7 | 8 | namespace photos_editing_formats { 9 | namespace image_io { 10 | 11 | /// A class that can make use of the data in a JpegInfo instance to extract 12 | /// the xmp data JpegSegments passed to it and forward it to a DataDestination. 13 | class JpegXmpDataExtractor : public DataDestination { 14 | public: 15 | /// @param xmp_info_type The type of xmp data being extracted. 16 | /// @param segment_count The number of segment ranges over which the xmp 17 | /// data is spread. 18 | /// @param data_destination The destination to which the extracted xmp data 19 | /// is to be sent. 20 | JpegXmpDataExtractor(JpegXmpInfo::Type xmp_info_type, size_t segment_count, 21 | DataDestination* data_destination, 22 | MessageHandler* message_handler) 23 | : xmp_info_type_(xmp_info_type), 24 | last_segment_index_(segment_count - 1), 25 | data_destination_(data_destination), 26 | message_handler_(message_handler), 27 | segment_index_(0), 28 | has_error_(false) {} 29 | 30 | /// Set the current segment index to the given value. 31 | /// @param segment_index The index of the segment currently being processed. 32 | void SetSegmentIndex(size_t segment_index) { segment_index_ = segment_index; } 33 | 34 | /// @return True if there was an error in the extraction process. 35 | bool HasError() const { return has_error_; } 36 | 37 | void StartTransfer() override; 38 | TransferStatus Transfer(const DataRange& transfer_range, 39 | const DataSegment& data_segment) override; 40 | void FinishTransfer() override; 41 | 42 | /// @return The number of bytes written not to this extractor destination, but 43 | /// to the next destination. Returns zero if the next destination is null. 44 | size_t GetBytesTransferred() const override { 45 | return data_destination_ ? data_destination_->GetBytesTransferred() : 0; 46 | } 47 | 48 | private: 49 | /// The type of xmp data being extracted. 50 | JpegXmpInfo::Type xmp_info_type_; 51 | 52 | /// The xmp data require special processing when the last segment is being 53 | /// transferred. This value is the index of the last segment. 54 | size_t last_segment_index_; 55 | 56 | /// The DataDestination that the extracted xmp data is sent to. 57 | DataDestination* data_destination_; 58 | 59 | /// An optional message handler to write messages to. 60 | MessageHandler* message_handler_; 61 | 62 | /// The xmp data is spread over one or more segments in the DataSource. This 63 | /// index tracks which one is being transferred. 64 | size_t segment_index_; 65 | 66 | /// A true value indicates that an error occurred in the decoding process. 67 | bool has_error_; 68 | }; 69 | 70 | } // namespace image_io 71 | } // namespace photos_editing_formats 72 | 73 | #endif // IMAGE_IO_JPEG_JPEG_XMP_DATA_EXTRACTOR_H_ // NOLINT 74 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/jpeg/jpeg_xmp_info.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_JPEG_JPEG_XMP_INFO_H_ // NOLINT 2 | #define IMAGE_IO_JPEG_JPEG_XMP_INFO_H_ // NOLINT 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "image_io/base/data_range.h" 9 | 10 | namespace photos_editing_formats { 11 | namespace image_io { 12 | 13 | const size_t kXmpGuidSize = 32; 14 | const char kXmpId[] = "http://ns.adobe.com/xap/1.0/"; 15 | const char kXmpExtendedId[] = "http://ns.adobe.com/xmp/extension/"; 16 | const size_t kXmpExtendedHeaderSize = 17 | sizeof(kXmpExtendedId) + kXmpGuidSize + 2 * sizeof(std::uint32_t); 18 | 19 | /// Constants used to find and process information in APP1/XMP type segments. 20 | const char kXmpAppleDepthId[] = "http://ns.apple.com/depthData/1.0"; 21 | const char kXmpAppleMatteId[] = "http://ns.apple.com/portraitEffectsMatte/1.0/"; 22 | const char kXmpGDepthV1Id[] = "http://ns.google.com/photos/1.0/depthmap/"; 23 | const char kXmpGImageV1Id[] = "http://ns.google.com/photos/1.0/image/"; 24 | const char kXmpHasExtendedId[] = "xmpNote:HasExtendedXMP"; 25 | 26 | /// JpegXmpInfo maintains information about the data in an Xmp property, such as 27 | /// are used to store the GDepth and GImage data. 28 | class JpegXmpInfo { 29 | public: 30 | /// The possible types of Xmp information. 31 | enum Type { 32 | /// GDepth:Data type information. 33 | kGDepthInfoType, 34 | 35 | /// GImage:Data type information. 36 | kGImageInfoType, 37 | }; 38 | 39 | /// Initializes a vector of JpegXmpinfo instances, indexed by their type. 40 | /// @param xmp_info_vector The vector to initialize. 41 | static void InitializeVector(std::vector* xmp_info_vector); 42 | 43 | /// @param xmp_info_type The type to get the identifier of. 44 | /// @return The identfier that appears at the start of the Xmp segment. 45 | static std::string GetIdentifier(Type jpeg_xmp_info_type); 46 | 47 | /// @param xmp_info_type The type to get the data property name of. 48 | /// @return The name of the data property that appears in the Xmp segment. 49 | static std::string GetDataPropertyName(Type jpeg_xmp_info_type); 50 | 51 | /// @param xmp_info_type The type to get the mime property name of. 52 | /// @return The name of the mime property that appears in the primary 53 | /// Xmp segment. 54 | static std::string GetMimePropertyName(Type jpeg_xmp_info_type); 55 | 56 | explicit JpegXmpInfo(Type type) : type_(type) {} 57 | JpegXmpInfo(const JpegXmpInfo&) = default; 58 | JpegXmpInfo& operator=(const JpegXmpInfo&) = default; 59 | 60 | /// @return The type of the Xmp property information. 61 | Type GetType() const { return type_; } 62 | 63 | /// @return The mime type of the Xmp data. 64 | std::string GetMimeType() const { return mime_type_; } 65 | 66 | /// @param mime_type The mime type to assign to this instance. 67 | void SetMimeType(const std::string& mime_type) { mime_type_ = mime_type; } 68 | 69 | /// @return The segment's data ranges where this Xmp data occurs. 70 | const std::vector& GetSegmentDataRanges() const { 71 | return segment_data_ranges_; 72 | } 73 | 74 | /// @param The segment data ranges to assign to this instance. 75 | void SetSegmentDataRanges(const std::vector& segment_data_ranges) { 76 | segment_data_ranges_ = segment_data_ranges; 77 | } 78 | 79 | private: 80 | /// The type of the Xmp information. 81 | Type type_; 82 | 83 | /// The mime type of the Xmp data. 84 | std::string mime_type_; 85 | 86 | /// The segment data ranges that contain the Xmp data. 87 | std::vector segment_data_ranges_; 88 | }; 89 | 90 | } // namespace image_io 91 | } // namespace photos_editing_formats 92 | 93 | #endif // IMAGE_IO_JPEG_JPEG_XMP_INFO_H_ // NOLINT 94 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/jpeg/jpeg_xmp_info_builder.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_JPEG_JPEG_XMP_INFO_BUILDER_H_ // NOLINT 2 | #define IMAGE_IO_JPEG_JPEG_XMP_INFO_BUILDER_H_ // NOLINT 3 | 4 | #include 5 | 6 | #include "image_io/jpeg/jpeg_segment.h" 7 | #include "image_io/jpeg/jpeg_xmp_info.h" 8 | 9 | namespace photos_editing_formats { 10 | namespace image_io { 11 | 12 | /// A helper class for building information about the segments that contain 13 | /// extended xmp data of various types. 14 | class JpegXmpInfoBuilder { 15 | public: 16 | /// @param xmp_info_type The type of xmp information to build. 17 | explicit JpegXmpInfoBuilder(JpegXmpInfo::Type xmp_info_type) 18 | : xmp_info_type_(xmp_info_type) {} 19 | 20 | /// @param segment The segment to examine for xmp data. 21 | void ProcessSegment(const JpegSegment& segment); 22 | 23 | /// @return The vector of segment data ranges that contains xmp property data. 24 | const std::vector& GetPropertySegmentRanges() const { 25 | return property_segment_ranges_; 26 | } 27 | 28 | private: 29 | /// The type of xmp data to collect. 30 | JpegXmpInfo::Type xmp_info_type_; 31 | 32 | /// The vector of segment data ranges that contains xmp property data. 33 | std::vector property_segment_ranges_; 34 | 35 | /// The segment data range that contains the xmp property data end. 36 | DataRange property_end_segment_range_; 37 | }; 38 | 39 | } // namespace image_io 40 | } // namespace photos_editing_formats 41 | 42 | #endif // IMAGE_IO_JPEG_JPEG_XMP_INFO_BUILDER_H_ // NOLINT 43 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/utils/file_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_UTILS_FILE_UTILS_H_ // NOLINT 2 | #define IMAGE_IO_UTILS_FILE_UTILS_H_ // NOLINT 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "image_io/base/data_segment.h" 9 | #include "image_io/base/message_handler.h" 10 | 11 | namespace photos_editing_formats { 12 | namespace image_io { 13 | 14 | /// @param file_name The name of the file to get the size in bytes of. 15 | /// @param size A pointer to a variable to receive the size. 16 | /// @return Whether file size was obtained properly. 17 | bool GetFileSize(const std::string& file_name, size_t* size); 18 | 19 | /// @param file_name The name of the file to open for output. 20 | /// @param message_handler Optional message handler to write messages to. 21 | /// @return An ostream pointer or nullptr if the open failed. 22 | std::unique_ptr OpenOutputFile(const std::string& file_name, 23 | MessageHandler* message_handler); 24 | 25 | /// @param file_name The name of the file to open for input. 26 | /// @param message_handler Optional message handler to write messages to. 27 | /// @return An istream pointer or nullptr if the open failed. 28 | std::unique_ptr OpenInputFile(const std::string& file_name, 29 | MessageHandler* message_handler); 30 | 31 | /// Opens the named file for input, gets its size, and reads the entire contents 32 | /// into a data segment that is returned to the caller. 33 | /// @param file_name The name of the file to open for input. 34 | /// @param message_handler Optional message handler to write messages to. 35 | /// @return A DataSegment pointer or nullptr if the open and reading failed. 36 | std::shared_ptr ReadEntireFile(const std::string& file_name, 37 | MessageHandler* message_handler); 38 | 39 | } // namespace image_io 40 | } // namespace photos_editing_formats 41 | 42 | #endif // IMAGE_IO_UTILS_FILE_UTILS_H_ // NOLINT 43 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/utils/message_stats_writer.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_UTILS_MESSAGE_STATS_WRITER_H_ // NOLINT 2 | #define IMAGE_IO_UTILS_MESSAGE_STATS_WRITER_H_ // NOLINT 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "image_io/base/message_stats.h" 9 | #include "image_io/utils/string_outputter.h" 10 | 11 | namespace photos_editing_formats { 12 | namespace image_io { 13 | 14 | /// A class to write the message stats for error and warning counts. The output 15 | /// is written when the writer object is destroyed, making this a conveneient 16 | /// class to use in functions that have multiple return points and for which 17 | /// such output is desired at all return points. 18 | class MessageStatsWriter { 19 | public: 20 | /// @param message_stats The message stats object holding the counts. 21 | /// @param outputter The outputter function to write the stats to. 22 | /// @param name The name of the tool or function that is "finished". 23 | MessageStatsWriter(const std::shared_ptr& message_stats, 24 | const std::string& name, const StringOutputter& outputter) 25 | : stats_(message_stats), outputter_(outputter), name_(name) {} 26 | 27 | /// Writes the finished message with the stats to the outputter function. 28 | ~MessageStatsWriter() { 29 | const string kError = stats_->error_count == 1 ? "error" : "errors"; 30 | const string kWarning = stats_->warning_count == 1 ? "warning" : "warnings"; 31 | std::stringstream ss; 32 | ss << std::endl 33 | << name_ << " finished, " << stats_->error_count << " " << kError << ", " 34 | << stats_->warning_count << " " << kWarning << std::endl; 35 | outputter_(ss.str()); 36 | } 37 | 38 | private: 39 | std::shared_ptr stats_; 40 | StringOutputter outputter_; 41 | std::string name_; 42 | }; 43 | 44 | } // namespace image_io 45 | } // namespace photos_editing_formats 46 | 47 | #endif // IMAGE_IO_UTILS_MESSAGE_STATS_WRITER_H_ // NOLINT 48 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/utils/string_outputter.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_UTILS_STRING_OUTPUTTER_H_ // NOLINT 2 | #define IMAGE_IO_UTILS_STRING_OUTPUTTER_H_ // NOLINT 3 | 4 | #include 5 | #include 6 | 7 | namespace photos_editing_formats { 8 | namespace image_io { 9 | 10 | /// A typedef for a function that accepts a string and writes it somewhere. 11 | /// These types of functions are typically used in command line tools to write 12 | /// the output of the tool to stdout or some other location. The function 13 | /// should not write its own new line at the end of the str. 14 | using StringOutputter = std::function; 15 | 16 | } // namespace image_io 17 | } // namespace photos_editing_formats 18 | 19 | #endif // IMAGE_IO_UTILS_STRING_OUTPUTTER_H_ // NOLINT 20 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/utils/string_outputter_message_writer.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_UTILS_STRING_OUTPUTTER_MESSAGE_WRITER_H_ // NOLINT 2 | #define IMAGE_IO_UTILS_STRING_OUTPUTTER_MESSAGE_WRITER_H_ // NOLINT 3 | 4 | #include "image_io/base/message_writer.h" 5 | #include "image_io/utils/string_outputter.h" 6 | 7 | namespace photos_editing_formats { 8 | namespace image_io { 9 | 10 | /// A MessageWriter that writes the messages to the StringOutputter function. 11 | class StringOutputterMessageWriter : public MessageWriter { 12 | public: 13 | /// @param outputter The outputter function to write messages to. 14 | explicit StringOutputterMessageWriter(const StringOutputter& outputter) 15 | : outputter_(outputter) {} 16 | void WriteMessage(const Message& message) override { 17 | outputter_(GetFormattedMessage(message)); 18 | outputter_("\n"); 19 | } 20 | 21 | private: 22 | StringOutputter outputter_; 23 | }; 24 | 25 | } // namespace image_io 26 | } // namespace photos_editing_formats 27 | 28 | #endif // IMAGE_IO_UTILS_STRING_OUTPUTTER_MESSAGE_WRITER_H_ // NOLINT 29 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/xml/xml_action.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_XML_XML_ACTION_H_ // NOLINT 2 | #define IMAGE_IO_XML_XML_ACTION_H_ // NOLINT 3 | 4 | #include 5 | 6 | #include "image_io/base/data_match_result.h" 7 | #include "image_io/xml/xml_handler_context.h" 8 | 9 | namespace photos_editing_formats { 10 | namespace image_io { 11 | 12 | class XmlActionContext; 13 | class XmlTerminal; 14 | 15 | /// The definition for an action function associated with an XmlTerminal. 16 | /// If the action does not need to change the result of the terminal, it can 17 | /// simply return the value from XmlActionContext::GetResult(). 18 | using XmlAction = 19 | std::function; 20 | 21 | /// The data context passed from an XmlTerminal to its action function. 22 | class XmlActionContext : public XmlHandlerContext { 23 | public: 24 | XmlActionContext(const XmlHandlerContext& context, XmlTerminal* terminal, 25 | const DataMatchResult& result) 26 | : XmlHandlerContext(context), terminal_(terminal), result_(result) {} 27 | XmlActionContext(size_t location, const DataRange& range, 28 | const DataSegment& segment, const DataLineMap& data_line_map, 29 | XmlHandler* handler, XmlTerminal* terminal, 30 | const DataMatchResult& result) 31 | : XmlHandlerContext(location, range, segment, data_line_map, handler), 32 | terminal_(terminal), 33 | result_(result) {} 34 | 35 | /// @return The terminal associated with the context. 36 | XmlTerminal* GetTerminal() const { return terminal_; } 37 | 38 | /// @return The result associated with the constext. 39 | const DataMatchResult& GetResult() const { return result_; } 40 | 41 | /// @param bytes_consumed The value to set in the returned result. 42 | /// @return A result based on the context's action, but with its bytes 43 | /// consumed value set to the given value. 44 | DataMatchResult GetResultWithBytesConsumed(size_t bytes_consumed) const { 45 | auto result = result_; 46 | return result.SetBytesConsumed(bytes_consumed); 47 | } 48 | 49 | private: 50 | XmlTerminal* terminal_; 51 | DataMatchResult result_; 52 | }; 53 | 54 | } // namespace image_io 55 | } // namespace photos_editing_formats 56 | 57 | #endif // IMAGE_IO_XML_XML_ACTION_H_ // NOLINT 58 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/xml/xml_attribute_rule.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_XML_XML_ATTRIBUTE_RULE_H_ // NOLINT 2 | #define IMAGE_IO_XML_XML_ATTRIBUTE_RULE_H_ // NOLINT 3 | 4 | #include "image_io/xml/xml_rule.h" 5 | 6 | namespace photos_editing_formats { 7 | namespace image_io { 8 | 9 | /// The XmlAttributeRule parses the following syntax: 10 | /// S? Name S? = S? 'Value' 11 | /// S? Name S? = S? "Value" 12 | class XmlAttributeRule : public XmlRule { 13 | public: 14 | XmlAttributeRule(); 15 | 16 | private: 17 | /// Builds an XmlTokenContext from the XmlActionContext and calls the 18 | /// handler's AttributeName() function. 19 | /// @param context The action context from the name terminal. 20 | /// @return The result value from the handler's function. 21 | DataMatchResult HandleName(const XmlActionContext& context); 22 | 23 | /// Builds an XmlTokenContext from the XmlActionContext and calls the 24 | /// handler's AttributeValue() function. 25 | /// @param context The action context from the quoted string terminal. 26 | /// @return The result value from the handler's function. 27 | DataMatchResult HandleValue(const XmlActionContext& context); 28 | }; 29 | 30 | } // namespace image_io 31 | } // namespace photos_editing_formats 32 | 33 | #endif // IMAGE_IO_XML_XML_ATTRIBUTE_RULE_H_ // NOLINT 34 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/xml/xml_cdata_and_comment_rules.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_XML_XML_CDATA_AND_COMMENT_RULES_H_ // NOLINT 2 | #define IMAGE_IO_XML_XML_CDATA_AND_COMMENT_RULES_H_ // NOLINT 3 | 4 | #include "image_io/xml/xml_rule.h" 5 | 6 | namespace photos_editing_formats { 7 | namespace image_io { 8 | 9 | /// The XmlCdataRule parses the following syntax "". 10 | /// As mentioned in the comments for the XmlHandler::Cdata() function, the token 11 | /// value that is passed to the handler never includes the leading "" syntax. This considerably 13 | /// simplifies the parsing task. The alternate start point constructor is used 14 | /// by the XmlCdataOrCommentRule. 15 | class XmlCdataRule : public XmlRule { 16 | public: 17 | XmlCdataRule(); 18 | explicit XmlCdataRule(StartPoint start_point); 19 | 20 | private: 21 | /// Builds an XmlTokenContext from the XmlActionContext and calls the 22 | /// handler's Cdata() function. 23 | /// @param context The action context from the rule's terminal. 24 | /// @return The result value from the handler's function. 25 | DataMatchResult HandleCdataValue(const XmlActionContext& context); 26 | }; 27 | 28 | /// The XmlCommentRule parses the following syntax "". 29 | /// As mentioned in the comments for the XmlHandler::Comment() function, the 30 | /// token value that is passed to the handler never includes the leading "" syntax. This considerably 32 | /// simplifies the parsing task. The alternate start point constructor is used 33 | /// by the XmlCdataOrCommentRule. 34 | class XmlCommentRule : public XmlRule { 35 | public: 36 | XmlCommentRule(); 37 | explicit XmlCommentRule(StartPoint start_point); 38 | 39 | private: 40 | /// Builds an XmlTokenContext from the XmlActionContext and calls the 41 | /// handler's Comment() function. 42 | /// @param context The action context from the rule's terminal. 43 | /// @return The result value from the handler's function. 44 | DataMatchResult HandleCommentValue(const XmlActionContext& context); 45 | }; 46 | 47 | /// This rule will use chain delegation to start either the XmlCdataRule or the 48 | /// XmlCommentRule, depending on the text being parsed. The syntax for XML is 49 | /// pretty poor here - the parser needs to look ahead two characters from the < 50 | /// character to determine what to do. The alternate start point constructor is 51 | /// used by the XmlElementContentRule. 52 | class XmlCdataOrCommentRule : public XmlRule { 53 | public: 54 | XmlCdataOrCommentRule(); 55 | explicit XmlCdataOrCommentRule(StartPoint start_point); 56 | 57 | private: 58 | /// Builds an XmlTokenContext from the XmlActionContext and creates the 59 | /// XmlCdataRule or XmlCommentRule to chain to depending on what character 60 | /// follows the exclamation point of the "". This 10 | /// syntax is considerably simplified from the official XML specification. As 11 | /// documented in the comments for the XmlHandler Pi() function, The leading 12 | /// "" literal 13 | /// is always sent as part of the processing content token. This approach makes 14 | /// it much easier to parse XML syntax. The alternate start point constructor 15 | /// is used by the XmlElementContentRule. 16 | class XmlPiRule : public XmlRule { 17 | public: 18 | XmlPiRule(); 19 | explicit XmlPiRule(StartPoint start_point); 20 | 21 | private: 22 | /// Builds an XmlTokenContext from the XmlActionContext and calls the 23 | /// handler's Pi() function. 24 | /// @param context The action context from the rule's terminal. 25 | /// @return The result value from the handler's function. 26 | DataMatchResult HandlePiValue(const XmlActionContext& context); 27 | }; 28 | 29 | } // namespace image_io 30 | } // namespace photos_editing_formats 31 | 32 | #endif // IMAGE_IO_XML_XML_PI_RULE_H_ // NOLINT 33 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/xml/xml_portion.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_XML_XML_PORTION_H_ // NOLINT 2 | #define IMAGE_IO_XML_XML_PORTION_H_ // NOLINT 3 | 4 | namespace photos_editing_formats { 5 | namespace image_io { 6 | 7 | /// An bit-type enum for indicating what part of an entity is defined: the 8 | /// begin, middle and or end. Bitwise "and" and "or" operators are defined to 9 | /// combine and test values. 10 | enum class XmlPortion { 11 | kNone = 0, 12 | kBegin = 1, 13 | kMiddle = 2, 14 | kEnd = 4, 15 | }; 16 | 17 | /// @return The value that results from the bitwise "and" of given portions. 18 | inline XmlPortion operator&(XmlPortion lhs, XmlPortion rhs) { 19 | int lhs_value = static_cast(lhs); 20 | int rhs_value = static_cast(rhs); 21 | return static_cast(lhs_value & rhs_value); 22 | } 23 | 24 | /// @return The value that results from the bitwise "or" of given portions. 25 | inline XmlPortion operator|(XmlPortion lhs, XmlPortion rhs) { 26 | int lhs_value = static_cast(lhs); 27 | int rhs_value = static_cast(rhs); 28 | return static_cast(lhs_value | rhs_value); 29 | } 30 | 31 | /// @param value The value to use for the test. 32 | /// @param mask The mask to use for the test. 33 | /// @return Whether any of the bits in the mask are set in the value. 34 | inline bool ContainsAny(XmlPortion value, XmlPortion mask) { 35 | return (value & mask) != XmlPortion::kNone; 36 | } 37 | 38 | /// @param value The value to use for the test. 39 | /// @param mask The mask to use for the test. 40 | /// @return Whether all of the bits in the mask are set in the value. 41 | inline bool ContainsAll(XmlPortion value, XmlPortion mask) { 42 | return (value & mask) == mask; 43 | } 44 | 45 | } // namespace image_io 46 | } // namespace photos_editing_formats 47 | 48 | #endif // IMAGE_IO_XML_XML_PORTION_H_ // NOLINT 49 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/xml/xml_terminal.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_XML_XML_TERMINAL_H_ // NOLINT 2 | #define IMAGE_IO_XML_XML_TERMINAL_H_ // NOLINT 3 | 4 | #include 5 | 6 | #include "image_io/base/data_scanner.h" 7 | #include "image_io/xml/xml_action.h" 8 | #include "image_io/xml/xml_token_context.h" 9 | 10 | namespace photos_editing_formats { 11 | namespace image_io { 12 | 13 | /// A terminal represents a part of a rule that uses a DataScanner to match 14 | /// zero or more characters from a DataSource. A terminal can also have a name 15 | /// that can be be used in error messages and also used to identify it in a 16 | /// rule. A terminal can also have an action function associated with it that it 17 | /// can use to validate the token produced by the terminal/scanner, and do 18 | /// further processing with the token. Finally, the terminal's action function 19 | /// can manipulate the DataMatchResult that was produced by the terminal's 20 | /// scanner and accessible via the action function's XmlActionContext param. 21 | class XmlTerminal { 22 | public: 23 | explicit XmlTerminal(const DataScanner& scanner) : scanner_(scanner) {} 24 | 25 | /// Sets the name of the terminal. Looks best with an XmlRule::AddTerminal 26 | /// function: AddWhitespaceTerminal().WithName("SomeName"); 27 | /// @param name The name to give to the terminal. 28 | /// @return A reference to the terminal. 29 | XmlTerminal& WithName(const std::string& name) { 30 | name_ = name; 31 | return *this; 32 | } 33 | 34 | /// Sets the description of the terminal's scanner used for errors. 35 | /// Looks best with an XmlRule::AddTerminal function: 36 | /// AddWhitespaceTerminal().WithDescription("intra element whitespace") 37 | /// @param description The description to give to the terminal's scanner. 38 | /// @return A reference to the terminal. 39 | XmlTerminal& WithDescription(const std::string& description) { 40 | scanner_.SetDescription(description); 41 | return *this; 42 | } 43 | 44 | /// Sets the action of the terminal. Looks best with an XmlRule::AddTerminal 45 | /// function: AddWhitespaceTerminal().WithAction(SomeAction); 46 | /// @param action The action to give to the terminal. 47 | /// @return A reference to the terminal. 48 | XmlTerminal& WithAction(const XmlAction& action) { 49 | action_ = action; 50 | return *this; 51 | } 52 | 53 | /// @return The terminal's scanner. 54 | DataScanner* GetScanner() { return &scanner_; } 55 | 56 | /// @return The terminal's name. 57 | const std::string& GetName() const { return name_; } 58 | 59 | /// @return The terminal's scanner's description. 60 | std::string GetDescription() const { return scanner_.GetDescription(); } 61 | 62 | /// @return The terminal's action function. 63 | const XmlAction& GetAction() const { return action_; } 64 | 65 | private: 66 | DataScanner scanner_; 67 | XmlAction action_; 68 | std::string name_; 69 | }; 70 | 71 | } // namespace image_io 72 | } // namespace photos_editing_formats 73 | 74 | #endif // IMAGE_IO_XML_XML_TERMINAL_H_ // NOLINT 75 | -------------------------------------------------------------------------------- /third_party/image_io/includes/image_io/xml/xml_token_context.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_IO_XML_XML_TOKEN_CONTEXT_H_ // NOLINT 2 | #define IMAGE_IO_XML_XML_TOKEN_CONTEXT_H_ // NOLINT 3 | 4 | #include 5 | #include 6 | 7 | #include "image_io/base/data_context.h" 8 | #include "image_io/base/data_match_result.h" 9 | #include "image_io/base/data_range.h" 10 | #include "image_io/xml/xml_portion.h" 11 | 12 | namespace photos_editing_formats { 13 | namespace image_io { 14 | 15 | class XmlActionContext; 16 | 17 | /// A token context is passed from the action of an XmlTerminal to an XmlHandler 18 | /// associated with the XmlActionContext used to call the action function. 19 | class XmlTokenContext : public DataContext { 20 | public: 21 | explicit XmlTokenContext(const XmlActionContext& context); 22 | XmlTokenContext(size_t location, const DataRange& range, 23 | const DataSegment& segment, const DataLineMap& data_line_map, 24 | const DataMatchResult& result, const DataRange& token_range, 25 | const XmlPortion& token_portion); 26 | 27 | /// @return The result associated with the context. 28 | const DataMatchResult& GetResult() const { return result_; } 29 | 30 | /// @return The token range for the token. Note that the token range may not 31 | /// be a subrange of the context's GetRange() or even the context's segment's 32 | /// data range. Such would be the case when a token's value is split across 33 | /// two or more data segments. 34 | const DataRange& GetTokenRange() const { return token_range_; } 35 | 36 | /// @return The portion of the token that this context represents. This 37 | /// portion value can be the bitwise or of any of the XmlPortion bit values. 38 | const XmlPortion& GetTokenPortion() const { return token_portion_; } 39 | 40 | /// Builds the string value of the token. If the context's token portion has 41 | /// the XmlPortion::kBegin bit set, the string value is first cleared. Then 42 | /// the string is extracted from the context's data source and appended onto 43 | /// the value. Remember that some token values (especially attribute values) 44 | /// can be quite long so care should be excercised when obtaining values with 45 | /// this function. 46 | /// @param value The value of the token being built. 47 | /// @param trim_first_and_last_chars Whether to remove the first and last 48 | /// characters of the token. This is nice to use when the token value is a 49 | /// quoted string and the value itself is wanted without the quote marks. 50 | /// @return Whether the token value is complete (i.e., the context's portion 51 | /// had the XmlPortion::kEnd bit set). 52 | bool BuildTokenValue(std::string* value, 53 | bool trim_first_and_last_chars = false) const; 54 | 55 | /// Builds the complete range of the token, which may need to be represented 56 | /// by multiple disjoint ranges. If the token portion indicates all portions 57 | /// of the token are present, then this simply clears the vector and pushes 58 | /// copies the value returned by the GetTokenRange() into it. Otherwise, it 59 | /// does the heavy lifting to build the vector of ranges. 60 | /// @param value_ranges The vector of ranges of the token being built. 61 | /// @param trim_first_and_last_chars Whether to remove the first and last 62 | /// characters of the token. This is nice to use when the token value is a 63 | /// If this parameter is true, the effect will be to increase the begin value 64 | /// of the first range by 1 and decrease the last range's end by 1. 65 | /// @return Whether the token range value is complete (i.e., the context's 66 | /// portion had the XmlPortion::kEnd bit set). 67 | bool BuildTokenValueRanges(std::vector* value_ranges, 68 | bool trim_first_and_last_chars = false) const; 69 | 70 | static XmlPortion ComputeTokenPortion(size_t token_scan_count, 71 | DataMatchResult::Type result_type); 72 | 73 | private: 74 | DataMatchResult result_; 75 | DataRange token_range_; 76 | XmlPortion token_portion_; 77 | }; 78 | 79 | } // namespace image_io 80 | } // namespace photos_editing_formats 81 | 82 | #endif // IMAGE_IO_XML_XML_TOKEN_CONTEXT_H_ // NOLINT 83 | -------------------------------------------------------------------------------- /third_party/image_io/src/base/byte_buffer.cc: -------------------------------------------------------------------------------- 1 | #include "image_io/base/byte_buffer.h" 2 | 3 | #include 4 | #include 5 | 6 | namespace photos_editing_formats { 7 | namespace image_io { 8 | 9 | using std::string; 10 | using std::unique_ptr; 11 | 12 | /// @param byte_data The byte data to write to the buffer at pos. 13 | /// @param pos The location in a buffer to write the byte data to. 14 | /// @return The number of bytes written to the buffer at pos. 15 | static size_t WriteBytes(const ByteData& byte_data, Byte* pos) { 16 | size_t byte_count = byte_data.GetByteCount(); 17 | if (!byte_count) { 18 | return 0; 19 | } 20 | if (byte_data.GetType() == ByteData::kHex) { 21 | const string& value = byte_data.GetValue(); 22 | for (size_t index = 0; index < byte_count; ++index) { 23 | if (!ByteData::Hex2Byte(value[2 * index], value[2 * index + 1], pos++)) { 24 | return 0; 25 | } 26 | } 27 | } else { 28 | std::memcpy(pos, byte_data.GetValue().c_str(), byte_count); 29 | } 30 | return byte_count; 31 | } 32 | 33 | ByteBuffer::ByteBuffer(size_t size, std::unique_ptr buffer) 34 | : buffer_(std::move(buffer)), size_(size) { 35 | if (!buffer_) { 36 | size_ = 0; 37 | } 38 | if (!size_) { 39 | buffer_.reset(); 40 | } 41 | } 42 | 43 | ByteBuffer::ByteBuffer(const std::vector& byte_data_vector) { 44 | size_ = 0; 45 | for (const auto& byte_data : byte_data_vector) { 46 | size_ += byte_data.GetByteCount(); 47 | } 48 | if (!size_) { 49 | return; 50 | } 51 | // Note that within google3, std::make_unique is not available, and clangtidy 52 | // says use absl::make_unique. This library attempts to minimize the number of 53 | // dependencies on google3, hence the no lint on the next line. 54 | buffer_.reset(new Byte[size_]); // NOLINT 55 | Byte* pos = buffer_.get(); 56 | for (const auto& byte_data : byte_data_vector) { 57 | size_t bytes_written = WriteBytes(byte_data, pos); 58 | if (bytes_written == 0 && byte_data.GetByteCount() != 0) { 59 | size_ = 0; 60 | buffer_.reset(nullptr); 61 | } 62 | pos += bytes_written; 63 | } 64 | } 65 | 66 | bool ByteBuffer::SetBigEndianValue(size_t location, std::uint16_t value) { 67 | if (location + 1 >= size_) { 68 | return false; 69 | } 70 | buffer_[location] = static_cast(value >> 8); 71 | buffer_[location + 1] = static_cast(value & 0xFF); 72 | return true; 73 | } 74 | 75 | Byte* ByteBuffer::Release() { 76 | size_ = 0; 77 | return buffer_.release(); 78 | } 79 | 80 | } // namespace image_io 81 | } // namespace photos_editing_formats 82 | -------------------------------------------------------------------------------- /third_party/image_io/src/base/byte_pointer_data_destination.cc: -------------------------------------------------------------------------------- 1 | #include "image_io/base/byte_pointer_data_destination.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "image_io/base/data_range.h" 7 | #include "image_io/base/data_segment.h" 8 | 9 | namespace photos_editing_formats { 10 | namespace image_io { 11 | 12 | void BytePointerDataDestination::StartTransfer() {} 13 | 14 | DataDestination::TransferStatus BytePointerDataDestination::Transfer( 15 | const DataRange& transfer_range, const DataSegment& data_segment) { 16 | if (transfer_range.IsValid()) { 17 | size_t size_remaining = size_ - bytes_transferred_; 18 | size_t bytes_to_copy = std::min(size_remaining, transfer_range.GetLength()); 19 | const Byte* buffer = data_segment.GetBuffer(transfer_range.GetBegin()); 20 | if (buffer) { 21 | std::memcpy(bytes_ + bytes_transferred_, buffer, bytes_to_copy); 22 | bytes_transferred_ += bytes_to_copy; 23 | return bytes_transferred_ == size_ ? kTransferDone : kTransferOk; 24 | } 25 | } 26 | return kTransferError; 27 | } 28 | 29 | void BytePointerDataDestination::FinishTransfer() {} 30 | 31 | } // namespace image_io 32 | } // namespace photos_editing_formats 33 | -------------------------------------------------------------------------------- /third_party/image_io/src/base/data_line_map.cc: -------------------------------------------------------------------------------- 1 | #include "image_io/base/data_line_map.h" 2 | 3 | #include 4 | 5 | namespace photos_editing_formats { 6 | namespace image_io { 7 | 8 | DataLine DataLineMap::GetDataLine(size_t location) const { 9 | if (data_lines_.empty()) { 10 | return DataLine(); 11 | } 12 | DataLine key(0, DataRange(location, location)); 13 | auto not_less_pos = 14 | std::lower_bound(data_lines_.begin(), data_lines_.end(), key, 15 | [](const DataLine& lhs, const DataLine& rhs) { 16 | return lhs.range.GetBegin() < rhs.range.GetBegin(); 17 | }); 18 | if (not_less_pos == data_lines_.end()) { 19 | --not_less_pos; 20 | } else if (not_less_pos != data_lines_.begin()) { 21 | auto prev_pos = not_less_pos - 1; 22 | if (location < prev_pos->range.GetEnd()) { 23 | not_less_pos = prev_pos; 24 | } 25 | } 26 | if (not_less_pos->range.Contains(location)) { 27 | return *not_less_pos; 28 | } 29 | return DataLine(); 30 | } 31 | 32 | void DataLineMap::FindDataLines(const DataRange& range, 33 | const DataSegment& segment) { 34 | size_t line_end; 35 | size_t range_end = range.GetEnd(); 36 | size_t line_begin = range.GetBegin(); 37 | size_t next_number = GetDataLineCount() + 1; 38 | while (line_begin < range_end) { 39 | line_end = std::min(range_end, segment.Find(line_begin, '\n')); 40 | if (last_line_incomplete_ && !data_lines_.empty()) { 41 | line_begin = data_lines_.back().range.GetBegin(); 42 | data_lines_.back().range = DataRange(line_begin, line_end); 43 | if (line_end < range_end && 44 | segment.GetValidatedByte(line_end).value == '\n') { 45 | last_line_incomplete_ = false; 46 | } 47 | } else { 48 | data_lines_.emplace_back(next_number++, DataRange(line_begin, line_end)); 49 | } 50 | line_begin = line_end + 1; 51 | } 52 | last_line_incomplete_ = 53 | line_end == range_end || segment.GetValidatedByte(line_end).value != '\n'; 54 | } 55 | 56 | void DataLineMap::Clear() { 57 | data_lines_.clear(); 58 | last_line_incomplete_ = false; 59 | } 60 | 61 | } // namespace image_io 62 | } // namespace photos_editing_formats 63 | -------------------------------------------------------------------------------- /third_party/image_io/src/base/data_range_tracking_destination.cc: -------------------------------------------------------------------------------- 1 | #include "image_io/base/data_range_tracking_destination.h" 2 | 3 | namespace photos_editing_formats { 4 | namespace image_io { 5 | 6 | void DataRangeTrackingDestination::StartTransfer() { 7 | tracked_data_range_ = DataRange(); 8 | bytes_transferred_ = 0; 9 | has_disjoint_transfer_ranges_ = false; 10 | if (destination_ != nullptr) { 11 | destination_->StartTransfer(); 12 | } 13 | } 14 | 15 | DataDestination::TransferStatus DataRangeTrackingDestination::Transfer( 16 | const DataRange& transfer_range, const DataSegment& data_segment) { 17 | DataDestination::TransferStatus transfer_status = 18 | destination_ ? destination_->Transfer(transfer_range, data_segment) 19 | : DataDestination::kTransferOk; 20 | if (transfer_status != kTransferError) { 21 | bytes_transferred_ += transfer_range.GetLength(); 22 | } 23 | if (has_disjoint_transfer_ranges_) { 24 | return transfer_status; 25 | } 26 | if (!tracked_data_range_.IsValid()) { 27 | tracked_data_range_ = transfer_range; 28 | return transfer_status; 29 | } 30 | if (tracked_data_range_.GetEnd() == transfer_range.GetBegin()) { 31 | tracked_data_range_ = 32 | DataRange(tracked_data_range_.GetBegin(), transfer_range.GetEnd()); 33 | return transfer_status; 34 | } else { 35 | has_disjoint_transfer_ranges_ = true; 36 | return transfer_status; 37 | } 38 | } 39 | 40 | void DataRangeTrackingDestination::FinishTransfer() { 41 | if (destination_ != nullptr) { 42 | destination_->FinishTransfer(); 43 | } 44 | } 45 | 46 | } // namespace image_io 47 | } // namespace photos_editing_formats 48 | -------------------------------------------------------------------------------- /third_party/image_io/src/base/data_segment.cc: -------------------------------------------------------------------------------- 1 | #include "image_io/base/data_segment.h" 2 | 3 | #include 4 | #include 5 | 6 | namespace photos_editing_formats { 7 | namespace image_io { 8 | 9 | using std::default_delete; 10 | using std::shared_ptr; 11 | 12 | shared_ptr DataSegment::Create( 13 | const DataRange& data_range, const Byte* buffer, 14 | DataSegment::BufferDispositionPolicy buffer_policy) { 15 | return shared_ptr( 16 | new DataSegment(data_range, buffer, buffer_policy), 17 | default_delete()); 18 | } 19 | 20 | size_t DataSegment::Find(size_t start_location, Byte value) const { 21 | if (!Contains(start_location)) { 22 | return GetEnd(); 23 | } 24 | const Byte* location = reinterpret_cast( 25 | memchr((buffer_ + start_location) - GetBegin(), value, 26 | GetEnd() - start_location)); 27 | return location ? (location - buffer_) + GetBegin() : GetEnd(); 28 | } 29 | 30 | size_t DataSegment::Find(size_t location, const char* str, 31 | size_t str_length) const { 32 | char char0 = *str; 33 | while (Contains(location)) { 34 | size_t memchr_count = GetEnd() - location; 35 | const void* void0_ptr = memchr(GetBuffer(location), char0, memchr_count); 36 | if (void0_ptr) { 37 | const Byte* byte0_ptr = reinterpret_cast(void0_ptr); 38 | size_t byte0_location = (byte0_ptr - buffer_) + GetBegin(); 39 | if (byte0_location + str_length <= GetEnd()) { 40 | const char* char0_ptr = reinterpret_cast(void0_ptr); 41 | if (strncmp(char0_ptr, str, str_length) == 0) { 42 | return byte0_location; 43 | } 44 | } 45 | } 46 | ++location; 47 | } 48 | return GetEnd(); 49 | } 50 | 51 | ValidatedByte DataSegment::GetValidatedByte(size_t location, 52 | const DataSegment* segment1, 53 | const DataSegment* segment2) { 54 | for (const DataSegment* segment : {segment1, segment2}) { 55 | if (segment && segment->Contains(location)) { 56 | return segment->GetValidatedByte(location); 57 | } 58 | } 59 | return InvalidByte(); 60 | } 61 | 62 | size_t DataSegment::Find(size_t start_location, Byte value, 63 | const DataSegment* segment1, 64 | const DataSegment* segment2) { 65 | if (segment1 && segment2 && segment1->GetEnd() == segment2->GetBegin()) { 66 | size_t value_location = segment2->GetEnd(); 67 | if (segment1->Contains(start_location)) { 68 | value_location = segment1->Find(start_location, value); 69 | if (value_location == segment1->GetEnd()) { 70 | value_location = segment2->Find(segment2->GetBegin(), value); 71 | } 72 | } else { 73 | value_location = segment2->Find(start_location, value); 74 | } 75 | return value_location; 76 | } 77 | size_t segment1_end = segment1 ? segment1->GetEnd() : 0; 78 | return segment2 ? std::max(segment1_end, segment2->GetEnd()) : segment1_end; 79 | } 80 | 81 | } // namespace image_io 82 | } // namespace photos_editing_formats 83 | -------------------------------------------------------------------------------- /third_party/image_io/src/base/data_segment_data_source.cc: -------------------------------------------------------------------------------- 1 | #include "image_io/base/data_segment_data_source.h" 2 | 3 | #include "image_io/base/data_destination.h" 4 | #include "image_io/base/data_range.h" 5 | #include "image_io/base/data_segment.h" 6 | 7 | namespace photos_editing_formats { 8 | namespace image_io { 9 | 10 | void DataSegmentDataSource::Reset() {} 11 | 12 | std::shared_ptr DataSegmentDataSource::GetDataSegment( 13 | size_t begin, size_t min_size) { 14 | DataRange range(begin, begin + min_size); 15 | if (range.GetIntersection(shared_data_segment_->GetDataRange()).IsValid()) { 16 | return shared_data_segment_; 17 | } else { 18 | return std::shared_ptr(nullptr); 19 | } 20 | } 21 | 22 | DataSource::TransferDataResult DataSegmentDataSource::TransferData( 23 | const DataRange& data_range, size_t /*best_size*/, 24 | DataDestination* data_destination) { 25 | bool data_transferred = false; 26 | DataDestination::TransferStatus status = DataDestination::kTransferDone; 27 | DataRange transfer_range = 28 | shared_data_segment_->GetDataRange().GetIntersection(data_range); 29 | if (data_destination && transfer_range.IsValid()) { 30 | data_transferred = true; 31 | status = data_destination->Transfer(transfer_range, *shared_data_segment_); 32 | } 33 | if (data_transferred) { 34 | return status == DataDestination::kTransferError ? kTransferDataError 35 | : kTransferDataSuccess; 36 | } else { 37 | return data_destination ? kTransferDataNone : kTransferDataError; 38 | } 39 | } 40 | 41 | } // namespace image_io 42 | } // namespace photos_editing_formats 43 | -------------------------------------------------------------------------------- /third_party/image_io/src/base/istream_ref_data_source.cc: -------------------------------------------------------------------------------- 1 | #include "image_io/base/istream_ref_data_source.h" 2 | 3 | #include 4 | 5 | #include "image_io/base/data_destination.h" 6 | #include "image_io/base/data_segment.h" 7 | 8 | namespace photos_editing_formats { 9 | namespace image_io { 10 | 11 | void IStreamRefDataSource::Reset() { 12 | istream_ref_.clear(); 13 | istream_ref_.seekg(0); 14 | current_data_segment_.reset(); 15 | } 16 | 17 | std::shared_ptr IStreamRefDataSource::GetDataSegment( 18 | size_t begin, size_t min_size) { 19 | if (current_data_segment_ && current_data_segment_->Contains(begin)) { 20 | return current_data_segment_; 21 | } 22 | current_data_segment_ = Read(begin, min_size); 23 | return current_data_segment_; 24 | } 25 | 26 | DataSource::TransferDataResult IStreamRefDataSource::TransferData( 27 | const DataRange &data_range, size_t best_size, 28 | DataDestination *data_destination) { 29 | bool data_transferred = false; 30 | DataDestination::TransferStatus status = DataDestination::kTransferDone; 31 | if (data_destination && data_range.IsValid()) { 32 | size_t min_size = std::min(data_range.GetLength(), best_size); 33 | if (current_data_segment_ && 34 | current_data_segment_->GetLength() >= min_size && 35 | current_data_segment_->GetDataRange().Contains(data_range)) { 36 | status = data_destination->Transfer(data_range, *current_data_segment_); 37 | data_transferred = true; 38 | } else { 39 | istream_ref_.clear(); 40 | size_t chunk_size = min_size; 41 | for (size_t begin = data_range.GetBegin(); begin < data_range.GetEnd(); 42 | begin += chunk_size) { 43 | size_t segment_length = 0; 44 | size_t end = std::min(data_range.GetEnd(), begin + chunk_size); 45 | std::shared_ptr data_segment = Read(begin, end - begin); 46 | if (data_segment) { 47 | segment_length = data_segment->GetLength(); 48 | if (segment_length) { 49 | status = data_destination->Transfer(data_segment->GetDataRange(), 50 | *data_segment); 51 | data_transferred = true; 52 | } 53 | } 54 | if (status != DataDestination::kTransferOk || segment_length == 0) { 55 | break; 56 | } 57 | } 58 | } 59 | } 60 | if (data_transferred) { 61 | return status == DataDestination::kTransferError ? kTransferDataError 62 | : kTransferDataSuccess; 63 | } else { 64 | return data_destination ? kTransferDataNone : kTransferDataError; 65 | } 66 | } 67 | 68 | std::shared_ptr IStreamRefDataSource::Read(size_t begin, 69 | size_t count) { 70 | std::shared_ptr shared_data_segment; 71 | istream_ref_.seekg(begin); 72 | if (istream_ref_.rdstate() == std::ios_base::goodbit) { 73 | Byte *buffer = new Byte[count]; 74 | istream_ref_.read(reinterpret_cast(buffer), count); 75 | size_t bytes_read = istream_ref_.gcount(); 76 | shared_data_segment = 77 | DataSegment::Create(DataRange(begin, begin + bytes_read), buffer); 78 | } 79 | return shared_data_segment; 80 | } 81 | 82 | } // namespace image_io 83 | } // namespace photos_editing_formats 84 | -------------------------------------------------------------------------------- /third_party/image_io/src/base/message_handler.cc: -------------------------------------------------------------------------------- 1 | #include "image_io/base/message_handler.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "image_io/base/cout_message_writer.h" 8 | 9 | namespace photos_editing_formats { 10 | namespace image_io { 11 | 12 | using std::string; 13 | using std::unique_ptr; 14 | 15 | MessageHandler::MessageHandler() 16 | : message_writer_(new CoutMessageWriter), 17 | message_store_(new VectorMessageStore), 18 | message_stats_(new MessageStats) {} 19 | 20 | void MessageHandler::SetMessageWriter( 21 | std::unique_ptr message_writer) { 22 | message_writer_ = std::move(message_writer); 23 | } 24 | 25 | void MessageHandler::SetMessageStore( 26 | std::unique_ptr message_store) { 27 | message_store_ = std::move(message_store); 28 | } 29 | 30 | void MessageHandler::ReportMessage(Message::Type type, const string& text) { 31 | int system_errno = (type == Message::kStdLibError) ? errno : 0; 32 | ReportMessage(Message(type, system_errno, text)); 33 | } 34 | 35 | void MessageHandler::ReportMessage(const Message& message) { 36 | if (message.IsError()) { 37 | message_stats_->error_count++; 38 | } else if (message.IsWarning()) { 39 | message_stats_->warning_count++; 40 | } else { 41 | message_stats_->status_count++; 42 | } 43 | if (message_store_) { 44 | message_store_->AddMessage(message); 45 | } 46 | if (message_writer_) { 47 | message_writer_->WriteMessage(message); 48 | } 49 | } 50 | 51 | } // namespace image_io 52 | } // namespace photos_editing_formats 53 | -------------------------------------------------------------------------------- /third_party/image_io/src/base/message_writer.cc: -------------------------------------------------------------------------------- 1 | #include "image_io/base/message_writer.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace photos_editing_formats { 8 | namespace image_io { 9 | 10 | using std::string; 11 | using std::stringstream; 12 | 13 | string MessageWriter::GetFormattedMessage(const Message& message) const { 14 | stringstream message_stream; 15 | auto type = message.GetType(); 16 | if (type != Message::kStatus) { 17 | message_stream << GetTypeCategory(type) << ":"; 18 | } 19 | if (type == Message::kInternalError || type == Message::kStdLibError) { 20 | message_stream << GetTypeDescription(type, message.GetSystemErrno()) << ":"; 21 | } 22 | message_stream << message.GetText(); 23 | return message_stream.str(); 24 | } 25 | 26 | string MessageWriter::GetTypeCategory(Message::Type type) const { 27 | string category; 28 | switch (type) { 29 | case Message::kStatus: 30 | category = "STATUS"; 31 | break; 32 | case Message::kWarning: 33 | category = "WARNING"; 34 | break; 35 | case Message::kStdLibError: 36 | case Message::kPrematureEndOfDataError: 37 | case Message::kStringNotFoundError: 38 | case Message::kDecodingError: 39 | case Message::kSyntaxError: 40 | case Message::kValueError: 41 | case Message::kInternalError: 42 | category = "ERROR"; 43 | break; 44 | } 45 | return category; 46 | } 47 | 48 | string MessageWriter::GetTypeDescription(Message::Type type, 49 | int system_errno) const { 50 | string description; 51 | switch (type) { 52 | case Message::kStatus: 53 | break; 54 | case Message::kWarning: 55 | break; 56 | case Message::kStdLibError: 57 | description = system_errno > 0 ? std::strerror(system_errno) : "Unknown"; 58 | break; 59 | case Message::kPrematureEndOfDataError: 60 | description = "Premature end of data"; 61 | break; 62 | case Message::kStringNotFoundError: 63 | description = "String not found"; 64 | break; 65 | case Message::kDecodingError: 66 | description = "Decoding error"; 67 | break; 68 | case Message::kSyntaxError: 69 | description = "Syntax error"; 70 | break; 71 | case Message::kValueError: 72 | description = "Value error"; 73 | break; 74 | case Message::kInternalError: 75 | description = "Internal error"; 76 | break; 77 | } 78 | return description; 79 | } 80 | 81 | } // namespace image_io 82 | } // namespace photos_editing_formats 83 | -------------------------------------------------------------------------------- /third_party/image_io/src/base/ostream_ref_data_destination.cc: -------------------------------------------------------------------------------- 1 | #include "image_io/base/ostream_ref_data_destination.h" 2 | 3 | #include "image_io/base/data_range.h" 4 | #include "image_io/base/data_segment.h" 5 | 6 | namespace photos_editing_formats { 7 | namespace image_io { 8 | 9 | using std::ostream; 10 | 11 | void OStreamRefDataDestination::StartTransfer() {} 12 | 13 | DataDestination::TransferStatus OStreamRefDataDestination::Transfer( 14 | const DataRange& transfer_range, const DataSegment& data_segment) { 15 | if (transfer_range.IsValid() && !HasError()) { 16 | size_t bytes_written = 0; 17 | size_t bytes_to_write = transfer_range.GetLength(); 18 | const Byte* buffer = data_segment.GetBuffer(transfer_range.GetBegin()); 19 | if (buffer) { 20 | ostream::pos_type prewrite_pos = ostream_ref_.tellp(); 21 | ostream_ref_.write(reinterpret_cast(buffer), bytes_to_write); 22 | ostream::pos_type postwrite_pos = ostream_ref_.tellp(); 23 | if (postwrite_pos != EOF) { 24 | bytes_written = ostream_ref_.tellp() - prewrite_pos; 25 | bytes_transferred_ += bytes_written; 26 | } 27 | } 28 | if (bytes_written != bytes_to_write) { 29 | if (message_handler_) { 30 | message_handler_->ReportMessage(Message::kStdLibError, name_); 31 | } 32 | has_error_ = true; 33 | return kTransferError; 34 | } 35 | } 36 | return kTransferOk; 37 | } 38 | 39 | void OStreamRefDataDestination::FinishTransfer() { 40 | ostream_ref_.flush(); 41 | } 42 | 43 | } // namespace image_io 44 | } // namespace photos_editing_formats 45 | -------------------------------------------------------------------------------- /third_party/image_io/src/base/string_ref_data_source.cc: -------------------------------------------------------------------------------- 1 | #include "image_io/base/string_ref_data_source.h" 2 | 3 | #include 4 | 5 | namespace photos_editing_formats { 6 | namespace image_io { 7 | 8 | namespace { 9 | 10 | /// @param str The string from which to create a DataSegment. 11 | /// @return A DataSegment the byte pointer of which is taken from the str. 12 | std::shared_ptr CreateDataSegment(const std::string &str) { 13 | Byte *bytes = reinterpret_cast(const_cast(str.c_str())); 14 | return DataSegment::Create(DataRange(0, str.length()), bytes, 15 | DataSegment::BufferDispositionPolicy::kDontDelete); 16 | } 17 | 18 | } // namespace 19 | 20 | StringRefDataSource::StringRefDataSource(const std::string &string_ref) 21 | : DataSegmentDataSource(CreateDataSegment(string_ref)), 22 | string_ref_(string_ref) {} 23 | 24 | } // namespace image_io 25 | } // namespace photos_editing_formats 26 | -------------------------------------------------------------------------------- /third_party/image_io/src/jpeg/jpeg_marker.cc: -------------------------------------------------------------------------------- 1 | #include "image_io/jpeg/jpeg_marker.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace photos_editing_formats { 10 | namespace image_io { 11 | 12 | using std::string; 13 | using std::stringstream; 14 | using std::vector; 15 | 16 | // Storage for class (static) data members. 17 | const size_t JpegMarker::kLength; // = 2; 18 | const size_t JpegMarker::kTypeOffset; // = 1; 19 | const Byte JpegMarker::kZERO; // = 0x00; 20 | const Byte JpegMarker::kStart; // = 0xFF; 21 | const Byte JpegMarker::kSOS; // = 0xDA; 22 | const Byte JpegMarker::kSOI; // = 0xD8; 23 | const Byte JpegMarker::kEOI; // = 0xD9; 24 | const Byte JpegMarker::kAPP0; // = 0xE0; 25 | const Byte JpegMarker::kAPP1; // = 0xE1; 26 | const Byte JpegMarker::kAPP2; // = 0xE2; 27 | const Byte JpegMarker::kFILL; // = 0xFF; 28 | 29 | const std::string JpegMarker::GetName() const { 30 | switch (type_) { 31 | case 0x01: 32 | return "TEM"; 33 | case 0xC4: 34 | return "DHT"; 35 | case 0xC8: 36 | return "JPG"; 37 | case 0xCC: 38 | return "DAC"; 39 | case JpegMarker::kSOI: 40 | return"SOI"; 41 | case JpegMarker::kEOI: 42 | return "EOI"; 43 | case JpegMarker::kSOS: 44 | return "SOS"; 45 | case 0xDB: 46 | return "DQT"; 47 | case 0xDC: 48 | return "DNL"; 49 | case 0xDD: 50 | return "DRI"; 51 | case 0xDE: 52 | return "DHP"; 53 | case 0xDF: 54 | return "EXP"; 55 | case 0xFE: 56 | return "COM"; 57 | } 58 | 59 | stringstream name_stream; 60 | 61 | if (0xC0 <= type_ && type_ <= 0xC0+15) { 62 | name_stream << "SOF" << type_-0xC0; 63 | return name_stream.str(); 64 | } 65 | if (0xD0 <= type_ && type_ <= 0xD0+7) { 66 | name_stream << "RST" << type_-0xD0; 67 | return name_stream.str(); 68 | } 69 | if (JpegMarker::kAPP0 <= type_ && type_ <= JpegMarker::kAPP0+15) { 70 | name_stream << "APP" << type_-JpegMarker::kAPP0; 71 | return name_stream.str(); 72 | } 73 | if (0xF0 <= type_ && type_ <= 0xF0+13) { 74 | name_stream << "JPG" << type_-0xF0; 75 | return name_stream.str(); 76 | } 77 | return GetHexString("0x"); 78 | } 79 | 80 | const std::string JpegMarker::GetHexString(const std::string& prefix) const { 81 | stringstream name_stream; 82 | name_stream << prefix << std::hex << std::uppercase << std::setfill('0') 83 | << std::setw(2) << static_cast(type_); 84 | return name_stream.str(); 85 | } 86 | 87 | bool JpegMarker::HasVariablePayloadSize() const { 88 | return type_ != 0x00 && type_ != 0x01 && (type_ < 0xD0 || type_ > 0xD7) && 89 | type_ != JpegMarker::kSOI && type_ != JpegMarker::kEOI && 90 | type_ != 0xFF; 91 | } 92 | 93 | bool JpegMarker::IsEntropySegmentDelimiter() const { 94 | return (type_ == kSOS || (type_ >= 0xD0 && type_ <= 0xD7)); 95 | } 96 | 97 | } // namespace image_io 98 | } // namespace photos_editing_formats 99 | -------------------------------------------------------------------------------- /third_party/image_io/src/jpeg/jpeg_scanner.cc: -------------------------------------------------------------------------------- 1 | #include "image_io/jpeg/jpeg_scanner.h" 2 | 3 | #include 4 | 5 | #include "image_io/base/message_handler.h" 6 | #include "image_io/jpeg/jpeg_segment.h" 7 | 8 | namespace photos_editing_formats { 9 | namespace image_io { 10 | 11 | using std::stringstream; 12 | 13 | /// The minimum size for the DataSegments requested from the DataSource. Using 14 | /// this value will guarentee that a JpegSegment will occupy at most two 15 | /// DataSegments. 16 | const size_t kMinBufferDataRequestSize = 0x10000; 17 | 18 | void JpegScanner::Run(DataSource* data_source, 19 | JpegSegmentProcessor* segment_processor) { 20 | if (data_source_) { 21 | // The Run() function is already active. 22 | return; 23 | } 24 | data_source_ = data_source; 25 | segment_processor_ = segment_processor; 26 | current_location_ = 0; 27 | done_ = false; 28 | has_error_ = false; 29 | data_source_->Reset(); 30 | current_segment_ = data_source_->GetDataSegment(current_location_, 31 | kMinBufferDataRequestSize); 32 | segment_processor_->Start(this); 33 | FindAndProcessSegments(); 34 | segment_processor_->Finish(this); 35 | data_source_ = nullptr; 36 | segment_processor_ = nullptr; 37 | current_segment_.reset(); 38 | next_segment_.reset(); 39 | } 40 | 41 | void JpegScanner::FindAndProcessSegments() { 42 | while (!IsDone() && !HasError()) { 43 | size_t begin_segment_location = 44 | current_segment_->Find(current_location_, JpegMarker::kStart); 45 | if (begin_segment_location == current_segment_->GetEnd()) { 46 | GetNextSegment(); 47 | if (next_segment_) { 48 | current_location_ = 49 | std::max(current_location_, next_segment_->GetBegin()); 50 | current_segment_ = next_segment_; 51 | next_segment_.reset(); 52 | continue; 53 | } 54 | SetDone(); 55 | break; 56 | } 57 | size_t payload_size = 0; 58 | JpegMarker marker( 59 | GetByte(begin_segment_location + JpegMarker::kTypeOffset)); 60 | if (marker.IsValid() && !HasError()) { 61 | payload_size = GetPayloadSize(marker, begin_segment_location); 62 | if (marker.IsValid() && interesting_marker_flags_[marker.GetType()]) { 63 | size_t end_segment_location = 64 | begin_segment_location + JpegMarker::kLength + payload_size; 65 | GetByte(end_segment_location - 1); 66 | if (!HasError()) { 67 | JpegSegment segment(begin_segment_location, end_segment_location, 68 | current_segment_.get(), next_segment_.get()); 69 | segment_processor_->Process(this, segment); 70 | } 71 | } 72 | } 73 | current_location_ = 74 | begin_segment_location + JpegMarker::kLength + payload_size; 75 | } 76 | } 77 | 78 | size_t JpegScanner::GetPayloadSize(const JpegMarker& marker, 79 | size_t begin_location) { 80 | if (marker.HasVariablePayloadSize()) { 81 | return (GetByte(begin_location + JpegMarker::kLength) << 8) | 82 | GetByte(begin_location + JpegMarker::kLength + 1); 83 | } else { 84 | return 0; 85 | } 86 | } 87 | 88 | ValidatedByte JpegScanner::GetValidatedByte(size_t location) { 89 | if (current_segment_->Contains(location)) { 90 | return current_segment_->GetValidatedByte(location); 91 | } 92 | GetNextSegment(); 93 | if (next_segment_ && next_segment_->Contains(location)) { 94 | return next_segment_->GetValidatedByte(location); 95 | } 96 | if (message_handler_) { 97 | stringstream sstream; 98 | sstream << location; 99 | message_handler_->ReportMessage(Message::kPrematureEndOfDataError, 100 | sstream.str()); 101 | } 102 | return InvalidByte(); 103 | } 104 | 105 | Byte JpegScanner::GetByte(size_t location) { 106 | ValidatedByte validated_byte = GetValidatedByte(location); 107 | if (validated_byte.is_valid) { 108 | return validated_byte.value; 109 | } 110 | has_error_ = true; 111 | return 0; 112 | } 113 | 114 | void JpegScanner::GetNextSegment() { 115 | if (!next_segment_ && current_segment_) { 116 | next_segment_ = data_source_->GetDataSegment(current_segment_->GetEnd(), 117 | kMinBufferDataRequestSize); 118 | } 119 | } 120 | 121 | } // namespace image_io 122 | } // namespace photos_editing_formats 123 | -------------------------------------------------------------------------------- /third_party/image_io/src/jpeg/jpeg_xmp_info.cc: -------------------------------------------------------------------------------- 1 | #include "image_io/jpeg/jpeg_xmp_info.h" 2 | 3 | namespace photos_editing_formats { 4 | namespace image_io { 5 | 6 | using std::string; 7 | using std::vector; 8 | 9 | const char kGDepthDataPropertyName[] = "GDepth:Data"; 10 | const char kGImageDataPropertyName[] = "GImage:Data"; 11 | const char kGDepthMimePropertyName[] = "GDepth:Mime"; 12 | const char kGImageMimePropertyName[] = "GImage:Mime"; 13 | 14 | void JpegXmpInfo::InitializeVector(vector* xmp_info_vector) { 15 | xmp_info_vector->clear(); 16 | xmp_info_vector->push_back(JpegXmpInfo(JpegXmpInfo::kGDepthInfoType)); 17 | xmp_info_vector->push_back(JpegXmpInfo(JpegXmpInfo::kGImageInfoType)); 18 | } 19 | 20 | string JpegXmpInfo::GetIdentifier(Type jpeg_xmp_info_type) { 21 | switch (jpeg_xmp_info_type) { 22 | case kGDepthInfoType: 23 | return kXmpGDepthV1Id; 24 | case kGImageInfoType: 25 | return kXmpGImageV1Id; 26 | } 27 | return ""; 28 | } 29 | 30 | string JpegXmpInfo::GetDataPropertyName(Type jpeg_xmp_info_type) { 31 | switch (jpeg_xmp_info_type) { 32 | case kGDepthInfoType: 33 | return kGDepthDataPropertyName; 34 | case kGImageInfoType: 35 | return kGImageDataPropertyName; 36 | } 37 | return ""; 38 | } 39 | 40 | string JpegXmpInfo::GetMimePropertyName(Type jpeg_xmp_info_type) { 41 | switch (jpeg_xmp_info_type) { 42 | case kGDepthInfoType: 43 | return kGDepthMimePropertyName; 44 | case kGImageInfoType: 45 | return kGImageMimePropertyName; 46 | } 47 | return ""; 48 | } 49 | 50 | } // namespace image_io 51 | } // namespace photos_editing_formats 52 | -------------------------------------------------------------------------------- /third_party/image_io/src/jpeg/jpeg_xmp_info_builder.cc: -------------------------------------------------------------------------------- 1 | #include "image_io/jpeg/jpeg_xmp_info_builder.h" 2 | 3 | #include 4 | 5 | namespace photos_editing_formats { 6 | namespace image_io { 7 | 8 | void JpegXmpInfoBuilder::ProcessSegment(const JpegSegment& segment) { 9 | // If the property has not yet been found, look for it, and if found, add the 10 | // segment's range to the vector of ranges. 11 | size_t extended_xmp_data_begin = 12 | segment.GetPayloadDataLocation() + kXmpExtendedHeaderSize; 13 | size_t property_value_begin = extended_xmp_data_begin; 14 | if (property_segment_ranges_.empty()) { 15 | std::string property_name = 16 | JpegXmpInfo::GetDataPropertyName(xmp_info_type_); 17 | property_value_begin = segment.FindXmpPropertyValueBegin( 18 | extended_xmp_data_begin, property_name.c_str()); 19 | if (property_value_begin != segment.GetEnd()) { 20 | property_segment_ranges_.push_back(segment.GetDataRange()); 21 | } 22 | } else if (!property_end_segment_range_.IsValid()) { 23 | // The start of the property value was encountered in a previous segment - 24 | // if the closing quote has not yet been found, then add the segment's range 25 | // to the vector or ranges. 26 | property_segment_ranges_.push_back(segment.GetDataRange()); 27 | } 28 | 29 | // If the start of the property value has been found but the end has not, look 30 | // for the end in this segment. 31 | if (!property_segment_ranges_.empty() && 32 | !property_end_segment_range_.IsValid()) { 33 | size_t property_value_end = 34 | segment.FindXmpPropertyValueEnd(property_value_begin); 35 | if (property_value_end != segment.GetEnd()) { 36 | property_end_segment_range_ = segment.GetDataRange(); 37 | } 38 | } 39 | } 40 | 41 | } // namespace image_io 42 | } // namespace photos_editing_formats 43 | -------------------------------------------------------------------------------- /third_party/image_io/src/modp_b64/BUILD.gn: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style license that can be 3 | # found in the LICENSE file. 4 | 5 | config("modp_b64_config") { 6 | include_dirs = [ "." ] 7 | } 8 | 9 | source_set("modp_b64") { 10 | sources = [ 11 | "modp_b64.cc", 12 | "modp_b64/modp_b64.h", 13 | "modp_b64_data.h", 14 | ] 15 | 16 | public_configs = [ ":modp_b64_config" ] 17 | include_dirs = [ "modp_b64" ] 18 | } 19 | -------------------------------------------------------------------------------- /third_party/image_io/src/modp_b64/DEPS: -------------------------------------------------------------------------------- 1 | include_rules = [ 2 | '+build', 3 | ] -------------------------------------------------------------------------------- /third_party/image_io/src/modp_b64/LICENSE: -------------------------------------------------------------------------------- 1 | * MODP_B64 - High performance base64 encoder/decoder 2 | * Version 1.3 -- 17-Mar-2006 3 | * http://modp.com/release/base64 4 | * 5 | * Copyright (c) 2005, 2006 Nick Galbreath -- nickg [at] modp [dot] com 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are 10 | * met: 11 | * 12 | * Redistributions of source code must retain the above copyright 13 | * notice, this list of conditions and the following disclaimer. 14 | * 15 | * Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 19 | * Neither the name of the modp.com nor the names of its 20 | * contributors may be used to endorse or promote products derived from 21 | * this software without specific prior written permission. 22 | * 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 29 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | -------------------------------------------------------------------------------- /third_party/image_io/src/modp_b64/METADATA: -------------------------------------------------------------------------------- 1 | third_party { 2 | license_type: NOTICE 3 | } 4 | -------------------------------------------------------------------------------- /third_party/image_io/src/modp_b64/MODULE_LICENSE_BSD: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/libultrahdr/6db3a83ee2b1f79850f3f597172289808dc6a331/third_party/image_io/src/modp_b64/MODULE_LICENSE_BSD -------------------------------------------------------------------------------- /third_party/image_io/src/modp_b64/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015 The Android Open Source Project 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | include common.mk 16 | 17 | CXXFLAGS += -I$(SRC)/modp_b64/ 18 | CXX_STATIC_LIBRARY(libmodpb64.pie.a): $(CXX_OBJECTS) 19 | 20 | all: CXX_STATIC_LIBRARY(libmodpb64.pie.a) 21 | -------------------------------------------------------------------------------- /third_party/image_io/src/modp_b64/README.chromium: -------------------------------------------------------------------------------- 1 | Name: modp base64 decoder 2 | Short Name: stringencoders 3 | URL: http://code.google.com/p/stringencoders/ 4 | Version: unknown 5 | License: BSD 6 | Security Critical: yes 7 | 8 | Description: 9 | The modp_b64.c file was modified to remove the inclusion of modp's config.h 10 | and to fix compilation errors that occur under VC8. The file was renamed 11 | modp_b64.cc to force it to be compiled as C++ so that the inclusion of 12 | basictypes.h could be possible. 13 | 14 | The modp_b64.cc and modp_b64.h files were modified to make them safe on 15 | 64-bit systems. 16 | -------------------------------------------------------------------------------- /third_party/image_io/src/modp_b64/modp_b64.gyp: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2009 The Chromium Authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style license that can be 3 | # found in the LICENSE file. 4 | 5 | { 6 | 'targets': [ 7 | { 8 | 'target_name': 'modp_b64', 9 | 'type': 'static_library', 10 | 'toolsets': ['host', 'target'], 11 | 'sources': [ 12 | 'modp_b64.cc', 13 | 'modp_b64.h', 14 | 'modp_b64_data.h', 15 | ], 16 | 'include_dirs': [ 17 | '../..', 18 | ], 19 | }, 20 | ], 21 | 'conditions': [ 22 | ['OS == "win" and target_arch=="ia32"', { 23 | # Even if we are building the browser for Win32, we need a few modules 24 | # to be built for Win64, and this is a prerequsite. 25 | 'targets': [ 26 | { 27 | 'target_name': 'modp_b64_win64', 28 | 'type': 'static_library', 29 | # We can't use dynamic_annotations target for win64 build since it is 30 | # a 32-bit library. 31 | 'include_dirs': [ 32 | '../..', 33 | ], 34 | 'sources': [ 35 | 'modp_b64.cc', 36 | 'modp_b64.h', 37 | 'modp_b64_data.h', 38 | ], 39 | 'configurations': { 40 | 'Common_Base': { 41 | 'msvs_target_platform': 'x64', 42 | }, 43 | }, 44 | }, 45 | ], 46 | }], 47 | ], 48 | } 49 | -------------------------------------------------------------------------------- /third_party/image_io/src/modp_b64/modp_b64_nacl.gyp: -------------------------------------------------------------------------------- 1 | # Copyright 2014 The Chromium Authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style license that can be 3 | # found in the LICENSE file. 4 | 5 | { 6 | 'includes': [ 7 | '../../native_client/build/untrusted.gypi', 8 | ], 9 | 'targets': [ 10 | { 11 | 'target_name': 'modp_b64_nacl', 12 | 'type': 'none', 13 | 'variables': { 14 | 'nlib_target': 'libmodp_b64_nacl.a', 15 | 'build_glibc': 0, 16 | 'build_newlib': 1, 17 | 'build_pnacl_newlib': 1, 18 | }, 19 | 'sources': [ 20 | 'modp_b64.cc', 21 | 'modp_b64.h', 22 | 'modp_b64_data.h', 23 | ], 24 | }, 25 | ], 26 | } 27 | -------------------------------------------------------------------------------- /third_party/image_io/src/utils/file_utils.cc: -------------------------------------------------------------------------------- 1 | #include "image_io/utils/file_utils.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "image_io/base/data_range.h" 9 | 10 | namespace photos_editing_formats { 11 | namespace image_io { 12 | 13 | using std::fstream; 14 | using std::istream; 15 | using std::ostream; 16 | using std::unique_ptr; 17 | 18 | bool GetFileSize(const std::string& file_name, size_t* size) { 19 | struct stat stat_buf; 20 | if (stat(file_name.c_str(), &stat_buf)) { 21 | return false; 22 | } else { 23 | if (size) { 24 | *size = stat_buf.st_size; 25 | } 26 | return true; 27 | } 28 | } 29 | 30 | unique_ptr OpenOutputFile(const std::string& file_name, 31 | MessageHandler* message_handler) { 32 | auto* file_stream = new fstream(file_name, std::ios::out | std::ios::binary); 33 | if (file_stream && !file_stream->is_open()) { 34 | delete file_stream; 35 | file_stream = nullptr; 36 | if (message_handler) { 37 | message_handler->ReportMessage(Message::kStdLibError, file_name); 38 | } 39 | } 40 | return unique_ptr(file_stream); 41 | } 42 | 43 | unique_ptr OpenInputFile(const std::string& file_name, 44 | MessageHandler* message_handler) { 45 | auto* file_stream = new fstream(file_name, std::ios::in | std::ios::binary); 46 | if (file_stream && !file_stream->is_open()) { 47 | delete file_stream; 48 | file_stream = nullptr; 49 | if (message_handler) { 50 | message_handler->ReportMessage(Message::kStdLibError, file_name); 51 | } 52 | } 53 | return unique_ptr(file_stream); 54 | } 55 | 56 | std::shared_ptr ReadEntireFile(const std::string& file_name, 57 | MessageHandler* message_handler) { 58 | size_t buffer_size = 0; 59 | std::shared_ptr shared_data_segment; 60 | if (GetFileSize(file_name, &buffer_size)) { 61 | unique_ptr shared_istream = 62 | OpenInputFile(file_name, message_handler); 63 | if (shared_istream) { 64 | Byte* buffer = new Byte[buffer_size]; 65 | if (buffer) { 66 | shared_data_segment = 67 | DataSegment::Create(DataRange(0, buffer_size), buffer); 68 | shared_istream->read(reinterpret_cast(buffer), buffer_size); 69 | size_t bytes_read = shared_istream->tellg(); 70 | if (bytes_read != buffer_size) { 71 | shared_data_segment.reset(); 72 | } 73 | } 74 | } 75 | } 76 | if (!shared_data_segment && message_handler) { 77 | message_handler->ReportMessage(Message::kStdLibError, file_name); 78 | } 79 | return shared_data_segment; 80 | } 81 | 82 | } // namespace image_io 83 | } // namespace photos_editing_formats 84 | -------------------------------------------------------------------------------- /third_party/image_io/src/xml/xml_attribute_rule.cc: -------------------------------------------------------------------------------- 1 | #include "image_io/xml/xml_attribute_rule.h" 2 | 3 | #include "image_io/xml/xml_handler.h" 4 | #include "image_io/xml/xml_token_context.h" 5 | 6 | namespace photos_editing_formats { 7 | namespace image_io { 8 | 9 | XmlAttributeRule::XmlAttributeRule() : XmlRule("Attribute") { 10 | // S? Name S? = S? 'Value' 11 | AddOptionalWhitespaceTerminal(); 12 | AddNameTerminal().WithAction( 13 | [&](const XmlActionContext& context) { return HandleName(context); }); 14 | AddOptionalWhitespaceTerminal(); 15 | AddLiteralTerminal("="); 16 | AddOptionalWhitespaceTerminal(); 17 | AddQuotedStringTerminal().WithAction( 18 | [&](const XmlActionContext& context) { return HandleValue(context); }); 19 | } 20 | 21 | DataMatchResult XmlAttributeRule::HandleName(const XmlActionContext& context) { 22 | XmlTokenContext token_context(context); 23 | return context.GetHandler()->AttributeName(token_context); 24 | } 25 | 26 | DataMatchResult XmlAttributeRule::HandleValue(const XmlActionContext& context) { 27 | XmlTokenContext token_context(context); 28 | return context.GetHandler()->AttributeValue(token_context); 29 | } 30 | 31 | } // namespace image_io 32 | } // namespace photos_editing_formats 33 | -------------------------------------------------------------------------------- /third_party/image_io/src/xml/xml_cdata_and_comment_rules.cc: -------------------------------------------------------------------------------- 1 | #include "image_io/xml/xml_cdata_and_comment_rules.h" 2 | 3 | #include 4 | 5 | #include "image_io/xml/xml_handler.h" 6 | #include "image_io/xml/xml_token_context.h" 7 | 8 | namespace photos_editing_formats { 9 | namespace image_io { 10 | 11 | XmlCdataRule::XmlCdataRule() : XmlCdataRule(kFirstStartPoint) {} 12 | 13 | XmlCdataRule::XmlCdataRule(StartPoint start_point) : XmlRule("CDATA") { 14 | // 15 | AddLiteralTerminal("").WithAction( 18 | [&](const XmlActionContext& context) { 19 | return HandleCdataValue(context); 20 | }); 21 | if (start_point == kSecondStartPoint) { 22 | SetTerminalIndex(1); 23 | } 24 | } 25 | 26 | DataMatchResult XmlCdataRule::HandleCdataValue( 27 | const XmlActionContext& context) { 28 | XmlTokenContext token_context(context); 29 | return context.GetHandler()->Cdata(token_context); 30 | } 31 | 32 | XmlCommentRule::XmlCommentRule() : XmlCommentRule(kFirstStartPoint) {} 33 | 34 | XmlCommentRule::XmlCommentRule(StartPoint start_point) : XmlRule("Comment") { 35 | // 36 | AddLiteralTerminal("").WithAction( 39 | [&](const XmlActionContext& context) { 40 | return HandleCommentValue(context); 41 | }); 42 | if (start_point == kSecondStartPoint) { 43 | SetTerminalIndex(1); 44 | } 45 | } 46 | 47 | DataMatchResult XmlCommentRule::HandleCommentValue( 48 | const XmlActionContext& context) { 49 | XmlTokenContext token_context(context); 50 | return context.GetHandler()->Comment(token_context); 51 | } 52 | 53 | XmlCdataOrCommentRule::XmlCdataOrCommentRule() 54 | : XmlCdataOrCommentRule(kFirstStartPoint) {} 55 | 56 | XmlCdataOrCommentRule::XmlCdataOrCommentRule(StartPoint start_point) 57 | : XmlRule("CdataOrComment") { 58 | // or 59 | // So after the initial "GetScanner()->GetSentinel(); 72 | if (sentinel == '[') { 73 | std::unique_ptr rule(new XmlCdataRule(kSecondStartPoint)); 74 | SetNextRule(std::move(rule)); 75 | } else if (sentinel == '-') { 76 | std::unique_ptr rule(new XmlCommentRule(kSecondStartPoint)); 77 | SetNextRule(std::move(rule)); 78 | } 79 | return context.GetResultWithBytesConsumed(0); 80 | } 81 | 82 | } // namespace image_io 83 | } // namespace photos_editing_formats 84 | -------------------------------------------------------------------------------- /third_party/image_io/src/xml/xml_handler.cc: -------------------------------------------------------------------------------- 1 | #include "image_io/xml/xml_handler.h" 2 | 3 | namespace photos_editing_formats { 4 | namespace image_io { 5 | 6 | DataMatchResult XmlHandler::AttributeName(const XmlTokenContext& context) { 7 | return context.GetResult(); 8 | } 9 | 10 | DataMatchResult XmlHandler::AttributeValue(const XmlTokenContext& context) { 11 | return context.GetResult(); 12 | } 13 | 14 | DataMatchResult XmlHandler::StartElement(const XmlTokenContext& context) { 15 | return context.GetResult(); 16 | } 17 | 18 | DataMatchResult XmlHandler::FinishElement(const XmlTokenContext& context) { 19 | return context.GetResult(); 20 | } 21 | 22 | DataMatchResult XmlHandler::ElementContent(const XmlTokenContext& context) { 23 | return context.GetResult(); 24 | } 25 | 26 | DataMatchResult XmlHandler::Comment(const XmlTokenContext& context) { 27 | return context.GetResult(); 28 | } 29 | 30 | DataMatchResult XmlHandler::Cdata(const XmlTokenContext& context) { 31 | return context.GetResult(); 32 | } 33 | 34 | DataMatchResult XmlHandler::Pi(const XmlTokenContext& context) { 35 | return context.GetResult(); 36 | } 37 | 38 | } // namespace image_io 39 | } // namespace photos_editing_formats 40 | -------------------------------------------------------------------------------- /third_party/image_io/src/xml/xml_pi_rule.cc: -------------------------------------------------------------------------------- 1 | #include "image_io/xml/xml_pi_rule.h" 2 | 3 | #include "image_io/xml/xml_handler.h" 4 | #include "image_io/xml/xml_token_context.h" 5 | 6 | namespace photos_editing_formats { 7 | namespace image_io { 8 | 9 | XmlPiRule::XmlPiRule() : XmlPiRule(kFirstStartPoint) {} 10 | 11 | XmlPiRule::XmlPiRule(XmlRule::StartPoint start_point) : XmlRule("PI") { 12 | // 13 | AddLiteralTerminal("").WithAction( 15 | [&](const XmlActionContext& context) { return HandlePiValue(context); }); 16 | if (start_point == kSecondStartPoint) { 17 | SetTerminalIndex(1); 18 | } 19 | } 20 | 21 | DataMatchResult XmlPiRule::HandlePiValue(const XmlActionContext& context) { 22 | XmlTokenContext token_context(context); 23 | DataMatchResult result = context.GetHandler()->Pi(token_context); 24 | return result; 25 | } 26 | 27 | } // namespace image_io 28 | } // namespace photos_editing_formats 29 | -------------------------------------------------------------------------------- /third_party/image_io/src/xml/xml_writer.cc: -------------------------------------------------------------------------------- 1 | #include "image_io/xml/xml_writer.h" 2 | 3 | #include 4 | #include 5 | 6 | namespace photos_editing_formats { 7 | namespace image_io { 8 | 9 | using std::ostream; 10 | using std::string; 11 | using std::vector; 12 | 13 | namespace { 14 | 15 | const char kXmlnsColon[] = "xmlns:"; 16 | 17 | } // namespace 18 | 19 | XmlWriter::XmlWriter(std::ostream& os) 20 | : os_(os), element_count_(0), quote_mark_('"') {} 21 | 22 | void XmlWriter::WriteXmlns(const string& prefix, const string& uri) { 23 | string name = string(kXmlnsColon) + prefix; 24 | WriteAttributeNameAndValue(name, uri, true); 25 | } 26 | 27 | size_t XmlWriter::StartWritingElement(const string& element_name) { 28 | MaybeWriteCloseBracket(true); 29 | size_t current_depth = element_data_.size(); 30 | if (current_depth > 0) { 31 | element_data_.back().has_children = true; 32 | } 33 | element_data_.emplace_back(element_name); 34 | os_ << indent_ << "<" << element_name; 35 | indent_ += " "; 36 | element_count_ += 1; 37 | return current_depth; 38 | } 39 | 40 | void XmlWriter::FinishWritingElement() { 41 | if (!element_data_.empty()) { 42 | if (indent_.size() >= 2) { 43 | indent_.resize(indent_.size() - 2); 44 | } 45 | auto& data = element_data_.back(); 46 | if (!data.has_content && !data.has_children) { 47 | if (!data.has_attributes || data.has_children) { 48 | os_ << indent_; 49 | } 50 | os_ << "/>" << std::endl; 51 | } else { 52 | if (!data.has_content) { 53 | os_ << indent_; 54 | } 55 | os_ << "" << std::endl; 56 | } 57 | element_data_.pop_back(); 58 | } 59 | } 60 | 61 | void XmlWriter::FinishWritingElementsToDepth(size_t depth) { 62 | if (!element_data_.empty()) { 63 | for (size_t index = element_data_.size(); index > depth; --index) { 64 | FinishWritingElement(); 65 | } 66 | } 67 | } 68 | 69 | size_t XmlWriter::StartWritingElements(const vector& element_names) { 70 | size_t current_depth = element_data_.size(); 71 | for (const auto& element_name : element_names) { 72 | StartWritingElement(element_name); 73 | } 74 | return current_depth; 75 | } 76 | 77 | void XmlWriter::WriteElementAndContent(const string& element_name, 78 | const string& content) { 79 | StartWritingElement(element_name); 80 | WriteContent(content); 81 | FinishWritingElement(); 82 | } 83 | 84 | void XmlWriter::WriteContent(const string& content) { 85 | MaybeWriteCloseBracket(false); 86 | if (!element_data_.empty()) { 87 | auto& data = element_data_.back(); 88 | data.has_content = true; 89 | os_ << content; 90 | } 91 | } 92 | 93 | void XmlWriter::WriteAttributeNameAndValue(const string& name, 94 | const string& value, 95 | bool add_quote_marks) { 96 | WriteAttributeName(name); 97 | WriteAttributeValue(add_quote_marks, value, add_quote_marks); 98 | } 99 | 100 | void XmlWriter::WriteAttributeName(const string& name) { 101 | if (!element_data_.empty()) { 102 | os_ << std::endl << indent_ << name << "="; 103 | element_data_.back().has_attributes = true; 104 | } 105 | } 106 | 107 | void XmlWriter::WriteAttributeValue(bool add_leading_quote_mark, 108 | const string& value, 109 | bool add_trailing_quote_mark) { 110 | if (!element_data_.empty()) { 111 | if (add_leading_quote_mark) os_ << quote_mark_; 112 | os_ << value; 113 | if (add_trailing_quote_mark) os_ << quote_mark_; 114 | } 115 | } 116 | 117 | void XmlWriter::WriteComment(const std::string& comment) { 118 | MaybeWriteCloseBracket(true); 119 | os_ << indent_ << "" << std::endl; 120 | if (!element_data_.empty()) { 121 | auto& data = element_data_.back(); 122 | data.has_children = true; 123 | } 124 | } 125 | 126 | bool XmlWriter::MaybeWriteCloseBracket(bool with_trailing_newline) { 127 | if (!element_data_.empty()) { 128 | auto& data = element_data_.back(); 129 | if (!data.has_content && !data.has_children) { 130 | os_ << ">"; 131 | if (with_trailing_newline) { 132 | os_ << std::endl; 133 | } 134 | return true; 135 | } 136 | } 137 | return false; 138 | } 139 | 140 | } // namespace image_io 141 | } // namespace photos_editing_formats 142 | --------------------------------------------------------------------------------